@dforge-core/metadata 0.0.1 → 0.0.2
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/README.md +144 -0
- package/package.json +8 -4
- package/schemas/data_views.schema.json +350 -0
- package/schemas/entity.schema.json +450 -0
- package/schemas/folders.schema.json +108 -0
- package/schemas/jobs.schema.json +83 -0
- package/schemas/manifest.schema.json +146 -0
- package/schemas/menus.schema.json +86 -0
- package/schemas/print_templates.schema.json +82 -0
- package/schemas/reports.schema.json +225 -0
- package/schemas/roles.schema.json +32 -0
- package/schemas/seed_data.schema.json +23 -0
- package/schemas/settings.schema.json +55 -0
- package/schemas/traits.schema.json +99 -0
- package/schemas/triggers.schema.json +59 -0
- package/schemas/webhooks.schema.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# @dforge-core/metadata
|
|
2
|
+
|
|
3
|
+
Canonical dForge authoring registries, module-file types, and JSON schemas — the
|
|
4
|
+
single source of truth shared by the web app, the SDK, the diagram library, the
|
|
5
|
+
CLI, the MCP server, and the VS Code extension.
|
|
6
|
+
|
|
7
|
+
- **Runtime-dependency-free.** Safe to import anywhere — editors, bundled web
|
|
8
|
+
apps, Node CLIs, MCP servers.
|
|
9
|
+
- **One source of truth.** The registries mirror the platform metadata seed
|
|
10
|
+
(`server/database/system-modules/metadata/seed-data/`) and the structural
|
|
11
|
+
types mirror the JSON schemas under `docs/schemas/`. Parity tests fail the
|
|
12
|
+
build if either drifts.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
pnpm add @dforge-core/metadata
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What's inside
|
|
21
|
+
|
|
22
|
+
| Surface | Exports |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| **Field types** | `fieldTypes`, `fieldTypeCds`, `isFieldTypeCd`, `getFieldType`, `fieldTypesByColumnType` |
|
|
25
|
+
| **Base datatypes** | `baseDatatypes`, `baseToDbDatatype` |
|
|
26
|
+
| **Column types** | `columnTypes`, `getColumnType` |
|
|
27
|
+
| **Traits** | `traits`, `getTrait`, `expandTrait`, `expandTraits` |
|
|
28
|
+
| **Derivation** | `deriveDbDatatype`, `deriveBaseDatatype`, `defaultParams`, `NUMERIC_TOTAL` |
|
|
29
|
+
| **Aggregation** | `AggType`, `AGG_TYPE_LIST` |
|
|
30
|
+
| **Display flags** | `flagDefs` (`V` Visible · `I` Identity · `E` Editable · `M` Mandatory · `H` Hidden) |
|
|
31
|
+
| **View / report kinds** | `dataViewKinds`, `vizTypes`, `chartTypes` |
|
|
32
|
+
| **Scalar enums** | `FieldTypeCd`, `BaseDatatypeCd`, `ColumnTypeCd`, `FlagCd`, `AlignType` |
|
|
33
|
+
| **Module-file types** | `ManifestDef`, `EntityDef`, `DataViewsFile`, `ReportsFile`, `MenusFile`, `FoldersFile`, `RolesFile`, `SettingsFile`, `JobsFile`, `TriggersFile`, `WebhooksFile`, `PrintTemplatesFile`, `SeedDataFile`, `ActionsFile`, … |
|
|
34
|
+
| **Filter expression** | `Filter`, `FilterCondition`, `FilterGroup`, `SortClause` |
|
|
35
|
+
| **JSON schemas** | `./schemas/<name>.schema.json` (see [Schemas](#json-schemas)) |
|
|
36
|
+
|
|
37
|
+
## Registries & derivation
|
|
38
|
+
|
|
39
|
+
An author picks a friendly `fieldTypeCd`; the helpers derive the physical
|
|
40
|
+
metadata so no one types a raw SQL type by hand.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import {
|
|
44
|
+
getFieldType,
|
|
45
|
+
isFieldTypeCd,
|
|
46
|
+
deriveDbDatatype,
|
|
47
|
+
deriveBaseDatatype,
|
|
48
|
+
defaultParams,
|
|
49
|
+
} from "@dforge-core/metadata";
|
|
50
|
+
|
|
51
|
+
isFieldTypeCd("currency"); // true
|
|
52
|
+
isFieldTypeCd("reference"); // false — not a real code (it's `lookup`)
|
|
53
|
+
|
|
54
|
+
getFieldType("currency");
|
|
55
|
+
// { cd: "currency", columnType: "D", baseDatatypeCd: "number", precision: 2, ... }
|
|
56
|
+
|
|
57
|
+
deriveDbDatatype("currency"); // "numeric(18,2)"
|
|
58
|
+
deriveDbDatatype("text"); // "varchar"
|
|
59
|
+
deriveDbDatatype("textarea"); // "text"
|
|
60
|
+
deriveDbDatatype("lookup"); // null — relationship-backed, no own column
|
|
61
|
+
deriveBaseDatatype("color"); // "string"
|
|
62
|
+
defaultParams("number"); // { min: 0, max: 10000 }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Traits
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { expandTrait, expandTraits } from "@dforge-core/metadata";
|
|
69
|
+
|
|
70
|
+
// Expand a trait into the FieldDef map it contributes to an entity.
|
|
71
|
+
expandTrait("audit", "invoice");
|
|
72
|
+
expandTraits(["identity", "audit"], "invoice");
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Module-file types
|
|
76
|
+
|
|
77
|
+
The structural types describe the *authoring* shape of every file in a `.dforge`
|
|
78
|
+
module package — the same shapes the JSON schemas validate.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import type { ManifestDef, EntityDef, DataViewsFile } from "@dforge-core/metadata";
|
|
82
|
+
|
|
83
|
+
const entity: EntityDef = {
|
|
84
|
+
description: "Customer",
|
|
85
|
+
dbObject: "customer",
|
|
86
|
+
fields: {
|
|
87
|
+
/* … */
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
> Note: these are the **authoring** shapes. The resolved **runtime** model
|
|
93
|
+
> returned by the API (`metadata.getModel`) is a different contract — see
|
|
94
|
+
> `@dforge/sdk`'s `Model*` types, which reuse the scalar enums from this package.
|
|
95
|
+
|
|
96
|
+
## JSON schemas
|
|
97
|
+
|
|
98
|
+
The 14 canonical schemas are shipped alongside the types and stay byte-identical
|
|
99
|
+
to `docs/schemas/` (a parity test enforces it; `prepack` re-syncs before
|
|
100
|
+
publish). Import them directly or point a validator / editor at the files.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import entitySchema from "@dforge-core/metadata/schemas/entity.schema.json" with { type: "json" };
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```jsonc
|
|
107
|
+
// VS Code settings.json — validate module files against the shipped schemas
|
|
108
|
+
"json.schemas": [
|
|
109
|
+
{
|
|
110
|
+
"fileMatch": ["entities/*.json"],
|
|
111
|
+
"url": "./node_modules/@dforge-core/metadata/schemas/entity.schema.json"
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Available: `manifest`, `entity`, `data_views`, `folders`, `menus`, `roles`,
|
|
117
|
+
`settings`, `reports`, `jobs`, `triggers`, `webhooks`, `print_templates`,
|
|
118
|
+
`traits`, `seed_data`.
|
|
119
|
+
|
|
120
|
+
## Source of truth & parity
|
|
121
|
+
|
|
122
|
+
This package never edits the canonical sources — it mirrors them and guards the
|
|
123
|
+
mirror:
|
|
124
|
+
|
|
125
|
+
- **Registries** mirror the platform metadata seed; `test/registries.test.ts`
|
|
126
|
+
fails if a code drifts from `field_types.json` (and a compile-time coverage
|
|
127
|
+
guard fails if the `FieldTypeCd` union and the `fieldTypes` array diverge).
|
|
128
|
+
- **Schemas** are copied from `docs/schemas/` by `pnpm sync-schemas`;
|
|
129
|
+
`test/schemas.test.ts` fails if the shipped copy drifts. `prepack` re-syncs.
|
|
130
|
+
|
|
131
|
+
When consumed standalone (no monorepo around the package) the parity checks are
|
|
132
|
+
skipped — the shipped data is authoritative on its own.
|
|
133
|
+
|
|
134
|
+
## Scripts
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
pnpm build # tsc → dist/
|
|
138
|
+
pnpm test # vitest (registry + schema parity)
|
|
139
|
+
pnpm sync-schemas # refresh schemas/ from docs/schemas/
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dforge-core/metadata",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Canonical dForge authoring registries — field types, base datatypes, column types, traits, data-view kinds and chart types — with derivation helpers. Runtime-dependency-free; the single source of truth shared by editors, the web app and the CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "dForge",
|
|
@@ -33,17 +33,21 @@
|
|
|
33
33
|
"source": "./src/index.ts",
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
35
|
"default": "./dist/index.js"
|
|
36
|
-
}
|
|
36
|
+
},
|
|
37
|
+
"./schemas/*": "./schemas/*",
|
|
38
|
+
"./package.json": "./package.json"
|
|
37
39
|
},
|
|
38
40
|
"files": [
|
|
39
41
|
"dist",
|
|
40
|
-
"src"
|
|
42
|
+
"src",
|
|
43
|
+
"schemas"
|
|
41
44
|
],
|
|
42
45
|
"scripts": {
|
|
46
|
+
"sync-schemas": "node scripts/sync-schemas.mjs",
|
|
43
47
|
"build": "tsc -p tsconfig.build.json",
|
|
44
48
|
"dev": "tsc -p tsconfig.build.json --watch",
|
|
45
49
|
"test": "vitest run",
|
|
46
|
-
"prepack": "pnpm build",
|
|
50
|
+
"prepack": "pnpm sync-schemas && pnpm build",
|
|
47
51
|
"package": "pnpm pack"
|
|
48
52
|
},
|
|
49
53
|
"devDependencies": {
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://dforge.dev/schemas/data_views.schema.json",
|
|
4
|
+
"title": "dForge Data Views",
|
|
5
|
+
"description": "Data view definitions for a dForge module",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": {
|
|
8
|
+
"$ref": "#/$defs/dataView"
|
|
9
|
+
},
|
|
10
|
+
"$defs": {
|
|
11
|
+
"dataView": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"required": ["viewType", "dataSources"],
|
|
14
|
+
"properties": {
|
|
15
|
+
"viewType": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"enum": ["grid", "list", "kanban", "calendar", "gallery", "tree-grid", "diagram", "master-detail", "library"],
|
|
18
|
+
"description": "View display type"
|
|
19
|
+
},
|
|
20
|
+
"label": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Human-readable view name"
|
|
23
|
+
},
|
|
24
|
+
"icon": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Bootstrap icon class (e.g. 'bi-bounding-box')"
|
|
27
|
+
},
|
|
28
|
+
"description": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Optional description text shown on view cards"
|
|
31
|
+
},
|
|
32
|
+
"dataSources": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"items": {
|
|
35
|
+
"$ref": "#/$defs/dataSource"
|
|
36
|
+
},
|
|
37
|
+
"minItems": 1,
|
|
38
|
+
"description": "Data sources providing data for this view"
|
|
39
|
+
},
|
|
40
|
+
"filter": {
|
|
41
|
+
"$ref": "#/$defs/filter",
|
|
42
|
+
"description": "Default filter criteria (applied to all dataSources unless one declares its own)"
|
|
43
|
+
},
|
|
44
|
+
"order": {
|
|
45
|
+
"description": "Default sort order"
|
|
46
|
+
},
|
|
47
|
+
"viewConfig": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"description": "View-type-specific configuration"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"allOf": [
|
|
54
|
+
{ "$ref": "#/$defs/rules/kanban" },
|
|
55
|
+
{ "$ref": "#/$defs/rules/calendar" },
|
|
56
|
+
{ "$ref": "#/$defs/rules/tree-grid" },
|
|
57
|
+
{ "$ref": "#/$defs/rules/list" },
|
|
58
|
+
{ "$ref": "#/$defs/rules/diagram" },
|
|
59
|
+
{ "$ref": "#/$defs/rules/master-detail" }
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
"rules": {
|
|
64
|
+
"kanban": {
|
|
65
|
+
"if": {
|
|
66
|
+
"properties": { "viewType": { "const": "kanban" } },
|
|
67
|
+
"required": ["viewType"]
|
|
68
|
+
},
|
|
69
|
+
"then": {
|
|
70
|
+
"properties": {
|
|
71
|
+
"viewConfig": { "$ref": "#/$defs/kanbanViewConfig" }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"calendar": {
|
|
76
|
+
"if": {
|
|
77
|
+
"properties": { "viewType": { "const": "calendar" } },
|
|
78
|
+
"required": ["viewType"]
|
|
79
|
+
},
|
|
80
|
+
"then": {
|
|
81
|
+
"properties": {
|
|
82
|
+
"viewConfig": { "$ref": "#/$defs/calendarViewConfig" }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"tree-grid": {
|
|
87
|
+
"if": {
|
|
88
|
+
"properties": { "viewType": { "const": "tree-grid" } },
|
|
89
|
+
"required": ["viewType"]
|
|
90
|
+
},
|
|
91
|
+
"then": {
|
|
92
|
+
"properties": {
|
|
93
|
+
"viewConfig": { "$ref": "#/$defs/treeGridViewConfig" }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"list": {
|
|
98
|
+
"if": {
|
|
99
|
+
"properties": { "viewType": { "const": "list" } },
|
|
100
|
+
"required": ["viewType"]
|
|
101
|
+
},
|
|
102
|
+
"then": {
|
|
103
|
+
"properties": {
|
|
104
|
+
"viewConfig": { "$ref": "#/$defs/listViewConfig" }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"diagram": {
|
|
109
|
+
"if": {
|
|
110
|
+
"properties": { "viewType": { "const": "diagram" } },
|
|
111
|
+
"required": ["viewType"]
|
|
112
|
+
},
|
|
113
|
+
"then": {
|
|
114
|
+
"properties": {
|
|
115
|
+
"viewConfig": { "$ref": "#/$defs/diagramViewConfig" }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"master-detail": {
|
|
120
|
+
"if": {
|
|
121
|
+
"properties": { "viewType": { "const": "master-detail" } },
|
|
122
|
+
"required": ["viewType"]
|
|
123
|
+
},
|
|
124
|
+
"then": {
|
|
125
|
+
"properties": {
|
|
126
|
+
"dataSources": { "minItems": 2 }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
"kanbanViewConfig": {
|
|
133
|
+
"type": "object",
|
|
134
|
+
"required": ["groupByField"],
|
|
135
|
+
"properties": {
|
|
136
|
+
"groupByField": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"description": "Column code of a dropdown/flags/reference field to group cards by"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"additionalProperties": false
|
|
142
|
+
},
|
|
143
|
+
"calendarViewConfig": {
|
|
144
|
+
"type": "object",
|
|
145
|
+
"required": ["dateField"],
|
|
146
|
+
"properties": {
|
|
147
|
+
"dateField": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"description": "Column code of the date/timestamp field used to place events on the calendar"
|
|
150
|
+
},
|
|
151
|
+
"titleField": {
|
|
152
|
+
"type": "string",
|
|
153
|
+
"description": "Column code of the field displayed as event title. Defaults to the entity's toString template."
|
|
154
|
+
},
|
|
155
|
+
"colorField": {
|
|
156
|
+
"type": "string",
|
|
157
|
+
"description": "Optional column whose value drives the event pill color. For dropdown/flags columns, colors come from params.options rich form; otherwise a deterministic hash is used."
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"additionalProperties": false
|
|
161
|
+
},
|
|
162
|
+
"treeGridViewConfig": {
|
|
163
|
+
"type": "object",
|
|
164
|
+
"required": ["parentField"],
|
|
165
|
+
"properties": {
|
|
166
|
+
"parentField": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"description": "Column code of the self-referencing FK (parent record)"
|
|
169
|
+
},
|
|
170
|
+
"labelField": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"description": "Field to display as node label (defaults to entity toString)"
|
|
173
|
+
},
|
|
174
|
+
"iconField": {
|
|
175
|
+
"type": "string",
|
|
176
|
+
"description": "Field containing a Bootstrap icon class per node"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"additionalProperties": false
|
|
180
|
+
},
|
|
181
|
+
"listViewConfig": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"titleField": {
|
|
185
|
+
"type": "string",
|
|
186
|
+
"description": "Column code of the primary display field"
|
|
187
|
+
},
|
|
188
|
+
"subtitleField": {
|
|
189
|
+
"type": "string",
|
|
190
|
+
"description": "Column code of the secondary display field"
|
|
191
|
+
},
|
|
192
|
+
"levels": {
|
|
193
|
+
"type": "array",
|
|
194
|
+
"items": { "$ref": "#/$defs/listLevelConfig" },
|
|
195
|
+
"description": "Hierarchical child levels for expandable list rows"
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
"additionalProperties": false
|
|
199
|
+
},
|
|
200
|
+
"listLevelConfig": {
|
|
201
|
+
"type": "object",
|
|
202
|
+
"required": ["entityCode", "foreignKey"],
|
|
203
|
+
"properties": {
|
|
204
|
+
"entityCode": {
|
|
205
|
+
"type": "string",
|
|
206
|
+
"description": "Entity code for this child level"
|
|
207
|
+
},
|
|
208
|
+
"foreignKey": {
|
|
209
|
+
"type": "string",
|
|
210
|
+
"description": "FK column in the child entity linking back to the parent"
|
|
211
|
+
},
|
|
212
|
+
"columns": {
|
|
213
|
+
"type": "array",
|
|
214
|
+
"items": { "type": "string" },
|
|
215
|
+
"description": "Columns to display inline for each child row"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
"additionalProperties": false
|
|
219
|
+
},
|
|
220
|
+
"diagramViewConfig": {
|
|
221
|
+
"type": "object",
|
|
222
|
+
"properties": {
|
|
223
|
+
"groupByField": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"description": "Column code to group diagram nodes by (e.g. 'module', 'project')"
|
|
226
|
+
},
|
|
227
|
+
"defaultHiddenGroups": {
|
|
228
|
+
"type": "array",
|
|
229
|
+
"items": { "type": "string" },
|
|
230
|
+
"description": "Group values to hide by default in the diagram"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"additionalProperties": false
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
"viewColumn": {
|
|
237
|
+
"oneOf": [
|
|
238
|
+
{
|
|
239
|
+
"type": "string",
|
|
240
|
+
"description": "Column code (shorthand)"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"type": "object",
|
|
244
|
+
"required": ["column_cd"],
|
|
245
|
+
"properties": {
|
|
246
|
+
"column_cd": {
|
|
247
|
+
"type": "string",
|
|
248
|
+
"description": "Column code"
|
|
249
|
+
},
|
|
250
|
+
"width": {
|
|
251
|
+
"type": "integer",
|
|
252
|
+
"minimum": 1,
|
|
253
|
+
"description": "Column width in pixels"
|
|
254
|
+
},
|
|
255
|
+
"visible": {
|
|
256
|
+
"type": "boolean",
|
|
257
|
+
"default": true,
|
|
258
|
+
"description": "Whether the column is visible"
|
|
259
|
+
},
|
|
260
|
+
"pinned": {
|
|
261
|
+
"type": "string",
|
|
262
|
+
"enum": ["left", "right"],
|
|
263
|
+
"description": "Pin column to left or right edge"
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
"additionalProperties": false
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
},
|
|
270
|
+
"dataSource": {
|
|
271
|
+
"type": "object",
|
|
272
|
+
"required": ["entityCode"],
|
|
273
|
+
"properties": {
|
|
274
|
+
"entityCode": {
|
|
275
|
+
"type": "string",
|
|
276
|
+
"description": "Entity code to query"
|
|
277
|
+
},
|
|
278
|
+
"level": {
|
|
279
|
+
"type": "integer",
|
|
280
|
+
"minimum": 0,
|
|
281
|
+
"description": "Nesting level (0 = root, 1+ = detail). Defaults to 0"
|
|
282
|
+
},
|
|
283
|
+
"label": {
|
|
284
|
+
"type": "string",
|
|
285
|
+
"description": "Human-readable label for this data source (used in master-detail tabs)"
|
|
286
|
+
},
|
|
287
|
+
"columns": {
|
|
288
|
+
"type": "array",
|
|
289
|
+
"items": { "$ref": "#/$defs/viewColumn" },
|
|
290
|
+
"description": "Column configuration — strings or objects with width/visibility"
|
|
291
|
+
},
|
|
292
|
+
"parentSetField": {
|
|
293
|
+
"type": "string",
|
|
294
|
+
"description": "Set field name on parent entity linking to this detail level"
|
|
295
|
+
},
|
|
296
|
+
"filter": {
|
|
297
|
+
"$ref": "#/$defs/filter",
|
|
298
|
+
"description": "Per-source filter criteria; overrides the view-level filter for this source"
|
|
299
|
+
},
|
|
300
|
+
"order": {
|
|
301
|
+
"description": "Per-source sort order (array of {c, d} entries, where d is 'asc' or 'desc')"
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
"additionalProperties": false
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
"filter": {
|
|
308
|
+
"description": "Canonical dForge filter expression. Either a single condition `{c, o, v}` or a group `{g, i: [...]}`. Used by data views, reports, folders (row-level security), and the API.",
|
|
309
|
+
"oneOf": [
|
|
310
|
+
{ "$ref": "#/$defs/filterCondition" },
|
|
311
|
+
{ "$ref": "#/$defs/filterGroup" }
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
"filterCondition": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"required": ["c", "o"],
|
|
317
|
+
"properties": {
|
|
318
|
+
"c": {
|
|
319
|
+
"type": "string",
|
|
320
|
+
"description": "Column code (supports dot navigation: 'customer.name')"
|
|
321
|
+
},
|
|
322
|
+
"o": {
|
|
323
|
+
"type": "string",
|
|
324
|
+
"description": "Operator: eq, neq, =, !=, gt, gtEq, grEq, lt, ltEq, in, nIn, like, isNull, isNotNull, etc."
|
|
325
|
+
},
|
|
326
|
+
"v": {
|
|
327
|
+
"description": "Comparison value. Scalars, arrays (for in/nIn), or parameter references like '@param_code'."
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
"additionalProperties": false
|
|
331
|
+
},
|
|
332
|
+
"filterGroup": {
|
|
333
|
+
"type": "object",
|
|
334
|
+
"required": ["g", "i"],
|
|
335
|
+
"properties": {
|
|
336
|
+
"g": {
|
|
337
|
+
"type": "string",
|
|
338
|
+
"enum": ["and", "or"],
|
|
339
|
+
"description": "Group combinator"
|
|
340
|
+
},
|
|
341
|
+
"i": {
|
|
342
|
+
"type": "array",
|
|
343
|
+
"items": { "$ref": "#/$defs/filter" },
|
|
344
|
+
"description": "Group items: nested conditions or sub-groups"
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"additionalProperties": false
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|