@dforge-core/dforge-mcp 0.2.33 → 0.2.34
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 +32 -1
- package/dist/server.js +219 -147
- package/package.json +3 -3
- package/resources/docs/conventions.md +20 -0
- package/resources/schemas/deps.schema.json +7 -2
- package/resources/schemas/domains.schema.json +1 -1
- package/resources/schemas/entity.schema.json +7 -1
- package/resources/schemas/registers.schema.json +415 -0
- package/resources/schemas/reports.schema.json +69 -4
- package/resources/schemas/seed-data.schema.json +12 -1
- package/resources/schemas/settings.schema.json +24 -1
- package/resources/schemas/traits.schema.json +26 -1
- package/skills/dforge-mcp-author/references/conventions.md +4 -3
- package/skills/dforge-mcp-author/references/manifest.md +21 -3
- package/skills/dforge-mcp-author/references/reports.md +6 -2
- package/skills/dforge-module-build/SKILL.md +4 -0
- package/skills/dforge-module-ship/SKILL.md +5 -0
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"$defs": {
|
|
11
11
|
"setting": {
|
|
12
12
|
"type": "object",
|
|
13
|
-
"required": ["fieldTypeCd"],
|
|
14
13
|
"properties": {
|
|
15
14
|
"fieldTypeCd": {
|
|
16
15
|
"type": "string",
|
|
@@ -47,8 +46,32 @@
|
|
|
47
46
|
"params": {
|
|
48
47
|
"type": "object",
|
|
49
48
|
"description": "Field-type-specific parameters. Examples: dropdown → { options: [...] }; number → { min, max }; lookup → { link: { entity, otherKey } }."
|
|
49
|
+
},
|
|
50
|
+
"domain": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"description": "Reference to a reusable column domain. A bare 'domain_cd' means this module's own domain, then a tenant-created one, and never another module's, even one with the same code. 'module_cd.domain_cd' names a domain of any installed module; declare that module as a dependency. The domain supplies fieldTypeCd, baseDatatypeCd and params; declaring any of those alongside 'domain' is rejected at install. The setting keeps its own label, defaultValue, formula and required flag."
|
|
50
53
|
}
|
|
51
54
|
},
|
|
55
|
+
"oneOf": [
|
|
56
|
+
{
|
|
57
|
+
"title": "Domain-backed setting",
|
|
58
|
+
"description": "Setting whose control and option list come from a reusable column domain. Requires 'domain' and must NOT restate what the domain owns.",
|
|
59
|
+
"required": ["domain"],
|
|
60
|
+
"properties": {
|
|
61
|
+
"fieldTypeCd": false,
|
|
62
|
+
"baseDatatypeCd": false,
|
|
63
|
+
"params": false
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"title": "Inline setting",
|
|
68
|
+
"description": "Setting that declares its own control and parameters. Requires 'fieldTypeCd'.",
|
|
69
|
+
"required": ["fieldTypeCd"],
|
|
70
|
+
"properties": {
|
|
71
|
+
"domain": false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
],
|
|
52
75
|
"additionalProperties": false
|
|
53
76
|
}
|
|
54
77
|
}
|
|
@@ -79,9 +79,34 @@
|
|
|
79
79
|
"serverDefault": { "$ref": "#/$defs/serverDefault" }
|
|
80
80
|
},
|
|
81
81
|
"additionalProperties": true
|
|
82
|
+
},
|
|
83
|
+
"domain": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"description": "Reference to a reusable column domain. A bare 'domain_cd' resolves in the module of the entity taking the trait, then tenant-created domains, so one generic trait gives each module its own list; 'module_cd.domain_cd' pins one module's domain for every entity. A module's own traits.json must qualify a domain the module itself defines: written bare, it would bind to a same-named domain of whichever module takes the trait, and pack rejects it. The domain supplies the type, control, sizing and options."
|
|
82
86
|
}
|
|
83
87
|
},
|
|
84
|
-
"additionalProperties": false
|
|
88
|
+
"additionalProperties": false,
|
|
89
|
+
"oneOf": [
|
|
90
|
+
{
|
|
91
|
+
"title": "Domain-backed trait field",
|
|
92
|
+
"description": "Defers to a column domain. Must not restate what the domain owns, and takes no 'link' — it is a plain scalar column.",
|
|
93
|
+
"required": ["domain"],
|
|
94
|
+
"properties": {
|
|
95
|
+
"link": false,
|
|
96
|
+
"dbDatatype": false,
|
|
97
|
+
"fieldTypeCd": false,
|
|
98
|
+
"maxLen": false,
|
|
99
|
+
"params": false
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"title": "Inline trait field",
|
|
104
|
+
"description": "Declares its own type and control, as trait fields always have.",
|
|
105
|
+
"properties": {
|
|
106
|
+
"domain": false
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
]
|
|
85
110
|
},
|
|
86
111
|
"serverDefault": {
|
|
87
112
|
"type": "object",
|
|
@@ -42,8 +42,7 @@ my_module/
|
|
|
42
42
|
│ ├── menus.json
|
|
43
43
|
│ ├── actions.json
|
|
44
44
|
│ ├── folders.json
|
|
45
|
-
│ └── reports
|
|
46
|
-
│ └── <report>.json
|
|
45
|
+
│ └── reports.json
|
|
47
46
|
├── security/
|
|
48
47
|
│ └── roles.json
|
|
49
48
|
├── settings.json
|
|
@@ -54,6 +53,7 @@ my_module/
|
|
|
54
53
|
│ └── de-DE.json # IETF tags, one file per non-English locale
|
|
55
54
|
├── print_templates/
|
|
56
55
|
│ └── <template>.scriban
|
|
56
|
+
├── migrations/ # upgrade data scripts, <version>.sql
|
|
57
57
|
├── files/ # static assets
|
|
58
58
|
└── webhooks.json # optional
|
|
59
59
|
```
|
|
@@ -144,7 +144,8 @@ Both use **semver** (`MAJOR.MINOR.PATCH`).
|
|
|
144
144
|
- If you added a new entity or column → bump both `version` and `dbSchemaVersion`.
|
|
145
145
|
- If you changed a view or menu → bump `version` only.
|
|
146
146
|
- If you changed translations only → bump `version` only.
|
|
147
|
-
- The installer uses `dbSchemaVersion` to decide whether to
|
|
147
|
+
- The installer uses `dbSchemaVersion` to decide whether to apply schema changes. Wrong version = skipped DDL.
|
|
148
|
+
- Data a new version reshapes (backfill, move rows, drop a table it no longer declares) goes in `migrations/<version>.sql`, named by `version`, run once on an upgrade from below it. See `manifest.md` § Upgrade migrations.
|
|
148
149
|
- **Never ship a package without bumping at least `version`** from the previous release. The installer may reject or silently skip a re-install with the same version.
|
|
149
150
|
- For brand-new modules, start at `version: "0.1.0"` and `dbSchemaVersion: "0.0.1"`.
|
|
150
151
|
|
|
@@ -111,7 +111,7 @@ Dependencies are a map of module codes to semver ranges. The installer checks th
|
|
|
111
111
|
|
|
112
112
|
**Declare a dependency only on a module you actually consume something from** — an entity you reference with a link column, extend, grant rights on, or read in a view, report, formula or action. Every entry you write here obliges you to write a matching `deps/<module>.json` contract (below), so a speculative dependency is not free.
|
|
113
113
|
|
|
114
|
-
**Do not depend on `admin`.** It — like `metadata` and `
|
|
114
|
+
**Do not depend on `admin`.** It — like `metadata`, `workspace` and `sys-billing` — is a system module, provisioned into every tenant before any other module installs. Depending on it buys nothing. The one legitimate reason to name a system module is to require a **minimum platform version** for a feature you use, e.g. `"metadata": ">=1.5.0"` for record-report attachments. Its contract names the entity the feature introduced, or declares `"entities": {}` when the feature introduced none (`"admin": ">=1.21.0"` for upgrade migrations).
|
|
115
115
|
|
|
116
116
|
**For bridge modules** (`crm-fin`, `wms-fin`, etc.), depend on both sides:
|
|
117
117
|
|
|
@@ -143,7 +143,7 @@ Every entry in `dependencies` needs a contract file at `deps/<module_code>.json`
|
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
- `version` must be the same range as the manifest's dependency entry.
|
|
146
|
-
- `entities` needs at least one entry
|
|
146
|
+
- `entities` needs at least one entry, except against a system module, where `{}` is a pure platform-version gate. Each entry needs a `pk` and a non-empty `use`.
|
|
147
147
|
- `columns` is optional — omit it when you touch no specific column of that entity. Declare only real storage columns you read, write or join on, at their **storage class** (`int8`, `varchar`, `numeric`, `bool`, `date`, `timestamptz`, …; a `cuid` PK is `int8`). Never declare a virtual column (`R`/`S`/`F`) or a column your own extension adds.
|
|
148
148
|
- `use` tokens are `<kind>:<symbol>` where kind is `ref`, `extends`, `formula`, `action`, `view`, `report`, `print` or `role`. `extends` must be fully qualified: `extends:parties.party`.
|
|
149
149
|
|
|
@@ -174,4 +174,22 @@ The extension file has `"extends": "fin.invoice"` inside. See MODULE_CONVENTIONS
|
|
|
174
174
|
|
|
175
175
|
- Bump `version` on every release (bug fix, feature add, etc.).
|
|
176
176
|
- Bump `dbSchemaVersion` **only** when the DB schema changes. If you added an action but no new columns, `version` goes up but `dbSchemaVersion` stays the same.
|
|
177
|
-
- The installer uses `dbSchemaVersion` to decide whether to
|
|
177
|
+
- The installer uses `dbSchemaVersion` to decide whether to apply schema changes. Upgrade **data** scripts under `migrations/` are keyed by `version` instead — see below.
|
|
178
|
+
|
|
179
|
+
## Upgrade migrations (`migrations/`)
|
|
180
|
+
|
|
181
|
+
A table or column change needs no script: the installer generates the DDL. A script is for the DATA a new version reshapes — filling a new column from an old one, moving rows to a new table, dropping a table the new version no longer declares (the platform never drops one on its own).
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
migrations/
|
|
185
|
+
└── 0.11.0.sql # runs on an upgrade from below 0.11.0 to 0.11.0 or later
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- **Name** — the module `version` the file upgrades to, `MAJOR.MINOR.PATCH.sql`. Keyed by `version`, not `dbSchemaVersion`. A misnamed file, or one newer than the manifest `version`, fails the package at load.
|
|
189
|
+
- **When** — on an upgrade only: every file above the installed version and no higher than the package's, in ascending order. A fresh install or a same-version reinstall runs none.
|
|
190
|
+
- **Where** — inside the install transaction, after the new tables and columns exist and before `NOT NULL` is applied or a register's `totals` cache is rebuilt. A table the new version removed is still there to read. A failing script rolls the upgrade back and the module stays on the old version; refuse unconvertible data with `RAISE EXCEPTION '…'`, which the operator sees.
|
|
191
|
+
- **Ids** — `"dForge".next_id()` mints a row id in SQL. Declare `"admin": ">=1.21.0"` in `dependencies`; that is also what guarantees a platform that runs migrations.
|
|
192
|
+
- **Locks** — a script writing a posted document or its register journal wraps the writes in `SELECT set_config('registry.posting', 'true', true);` … `'false'`, so the post locks stand aside. Period locks do not; reopen a closed period and close it again.
|
|
193
|
+
- A `kind: "pack"` module cannot carry migrations.
|
|
194
|
+
|
|
195
|
+
Reference: `modules/gl/migrations/0.11.0.sql` in dForge-core.
|
|
@@ -7,11 +7,14 @@ SP files: `logic/reports/rpt_*.sql`
|
|
|
7
7
|
|
|
8
8
|
## Structure
|
|
9
9
|
|
|
10
|
-
A report has `description`, a `datasets` map, a `layout` object (`{ panels: [...] }`), optional per-dataset `params`, and an optional `entities` array (record-report attachments). Panels reference datasets by code via `datasetCd`.
|
|
10
|
+
A report has a `label`, a `description`, a `datasets` map, a `layout` object (`{ panels: [...] }`), optional per-dataset `params`, and an optional `entities` array (record-report attachments). Panels reference datasets by code via `datasetCd`.
|
|
11
|
+
|
|
12
|
+
**Name it with `label`, describe it with `description`.** `label` is the report's name: page title, breadcrumb and parameter dialog. `description` says what it shows and appears under the label, as a data view's does. Without a `label` the description becomes the name, so a sentence ends up as the page title. `dforge_module_validate`, `module pack` and install warn about it; install does not refuse it. Translate the name as `reports.<cd>.label`.
|
|
11
13
|
|
|
12
14
|
```json
|
|
13
15
|
{
|
|
14
16
|
"sales_pipeline": {
|
|
17
|
+
"label": "Sales Pipeline",
|
|
15
18
|
"description": "Open opportunities by stage",
|
|
16
19
|
"datasets": {
|
|
17
20
|
"pipeline": {
|
|
@@ -341,7 +344,8 @@ A report can be **attached to an entity** so it opens from a record — the way
|
|
|
341
344
|
|
|
342
345
|
```json
|
|
343
346
|
"credit_check": {
|
|
344
|
-
"
|
|
347
|
+
"label": "Credit Check",
|
|
348
|
+
"description": "Credit limit against outstanding AR and open quotes",
|
|
345
349
|
"entities": [
|
|
346
350
|
{ "entityCd": "parties.party", "params": { "customer_id": "party_id" }, "orderNum": 45 },
|
|
347
351
|
{ "entityCd": "crm.quote", "params": { "customer_id": "customer_id" }, "orderNum": 45 }
|
|
@@ -237,6 +237,10 @@ If none fire, skip specialized views for that entity.
|
|
|
237
237
|
**3c. Reports** only when aggregation/grouping isn't covered by views — or when
|
|
238
238
|
Phase 2a sent you here because the "action" only wanted to show a number.
|
|
239
239
|
|
|
240
|
+
Give each report a short `label` (its name: page title, breadcrumb, parameter
|
|
241
|
+
dialog) and a `description` of what it shows, which appears under the label.
|
|
242
|
+
Without a label the description becomes the title, and validate/pack warn.
|
|
243
|
+
|
|
240
244
|
Params are **report-scoped**: declare them in the report-level `parameters`
|
|
241
245
|
block, or as shorthand under `datasets.<cd>.params` when exactly one dataset uses
|
|
242
246
|
the param. The installer merges both into the report's one param set, report level
|
|
@@ -101,6 +101,11 @@ role / trigger / job counts. Then confirm both version strings with the user:
|
|
|
101
101
|
- **`version`** — always bump (semver) before packing.
|
|
102
102
|
- **`dbSchemaVersion`** — bump only if entity fields were added, removed, or
|
|
103
103
|
type-changed since the last install.
|
|
104
|
+
- **Data on upgrade** — if the new version moves or reshapes existing rows, or
|
|
105
|
+
removes an entity whose table must go, ship `migrations/<version>.sql` named by
|
|
106
|
+
the new `version` and declare `"admin": ">=1.21.0"`. The installer generates the
|
|
107
|
+
DDL; it never moves data or drops a table on its own. See
|
|
108
|
+
`dforge://docs/conventions` § Upgrade Migrations.
|
|
104
109
|
|
|
105
110
|
Get explicit confirmation on both before packing. This version confirmation
|
|
106
111
|
applies only to the initial pack. During the install-fix loop, re-pack without
|