@dforge-core/metadata 0.0.14 → 0.0.16
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 +157 -0
- package/dist/index.d.ts +187 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/data_views.schema.json +40 -0
- package/schemas/entity.schema.json +77 -0
- package/schemas/folders.schema.json +1 -1
- package/schemas/manifest.schema.json +6 -0
- package/schemas/reports.schema.json +41 -17
- package/src/actions.ts +31 -3
- package/src/entity.ts +53 -0
- package/src/folders.ts +10 -1
- package/src/index.ts +4 -1
- package/src/manifest.ts +21 -0
- package/src/reports.ts +75 -9
package/src/actions.ts
CHANGED
|
@@ -24,13 +24,41 @@ export interface ActionDef {
|
|
|
24
24
|
executionMode: ActionExecutionMode;
|
|
25
25
|
/** DSL script name (file under `logic/actions/<script>.dsl`). */
|
|
26
26
|
script: string;
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Run the whole selection in one transaction, so a failure on any record
|
|
29
|
+
* rolls back the records already processed. **Defaults to `true`** when
|
|
30
|
+
* omitted (`ActionDef.IsTransacted` in the installer is a non-nullable
|
|
31
|
+
* `bool` initialised to `true`), so omit it only when you want atomicity.
|
|
32
|
+
*
|
|
33
|
+
* `false` opens no transaction, and what follows a failure depends on
|
|
34
|
+
* {@link ActionDef.executionMode}: `single` / `each` report it and continue
|
|
35
|
+
* with the next record, so use that for independent per-record work that
|
|
36
|
+
* should process as many records as pass; `batch` is a single script
|
|
37
|
+
* invocation with no loop to continue, so the run simply ends with its
|
|
38
|
+
* earlier writes committed.
|
|
39
|
+
*
|
|
40
|
+
* On a run queued to the background the **rollback** guarantee is lost
|
|
41
|
+
* outright — the worker opens no transaction, so nothing is ever undone. What
|
|
42
|
+
* remains of the flag there depends on the mode: the worker's `single`/`each`
|
|
43
|
+
* loop still reads it for control flow (stop after the first failed record vs.
|
|
44
|
+
* continue), while its `batch` path never reads it at all — one invocation,
|
|
45
|
+
* which ends on failure under either value.
|
|
46
|
+
*/
|
|
28
47
|
isTransacted?: boolean;
|
|
29
48
|
/** Display order. */
|
|
30
49
|
orderNum?: number;
|
|
31
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* @deprecated Not read by the installer — use {@link ActionDef.isAsync}.
|
|
52
|
+
* The module manifest model binds `isAsync` only, so this key is silently
|
|
53
|
+
* ignored and the action installs as synchronous.
|
|
54
|
+
*/
|
|
32
55
|
async?: boolean;
|
|
33
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Permit background execution. It does not force it: `action.execute`
|
|
58
|
+
* carries its own `async` argument and the server branches on that, so an
|
|
59
|
+
* action with parameters is offered to the user as both "Run" (inline) and
|
|
60
|
+
* "Run in Background". A parameterless `isAsync` action is queued directly.
|
|
61
|
+
*/
|
|
34
62
|
isAsync?: boolean;
|
|
35
63
|
}
|
|
36
64
|
|
package/src/entity.ts
CHANGED
|
@@ -32,6 +32,48 @@ export interface EntityReference {
|
|
|
32
32
|
onUpdate?: ReferentialAction;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Per-view overrides for one column (`views.<name>.columns.<column_cd>`). Every
|
|
37
|
+
* property is optional; an omitted one falls back to the entity-level value.
|
|
38
|
+
*
|
|
39
|
+
* An EMPTY value is not the same as an omitted one — the runtime merges view over
|
|
40
|
+
* entity with COALESCE, so `flags: ""` means "no flags in this view" (a column
|
|
41
|
+
* neither visible nor editable) and `params: {}` suppresses the entity-level
|
|
42
|
+
* params rather than inheriting them.
|
|
43
|
+
*/
|
|
44
|
+
export interface EntityViewColumnDef {
|
|
45
|
+
/** Flag letters for this column in this view, e.g. "VO" to expose it read-only. */
|
|
46
|
+
flags?: string;
|
|
47
|
+
orderNum?: number;
|
|
48
|
+
isNullable?: boolean;
|
|
49
|
+
editMask?: string;
|
|
50
|
+
displayFmt?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Formula override for this column in this view, same DSL as a field's
|
|
53
|
+
* `formula`. Only on a column the entity declares as `columnType: "F"` — on any
|
|
54
|
+
* other column that field is the SQL default, so an override would be inert.
|
|
55
|
+
*/
|
|
56
|
+
formula?: string;
|
|
57
|
+
/** Lookup filter override for a reference column in this view. */
|
|
58
|
+
refFilter?: unknown;
|
|
59
|
+
/** Control-specific configuration override for this view. */
|
|
60
|
+
params?: Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** One entity view: the columns it exposes, plus optional per-view overrides. */
|
|
64
|
+
export interface EntityViewDef {
|
|
65
|
+
/**
|
|
66
|
+
* Column code → per-view overrides. Columns ABSENT from this map are hidden in
|
|
67
|
+
* a folder bound to the view — that is the mechanism, not an oversight. `{}`
|
|
68
|
+
* (or null) exposes a column with no overrides. Must include the entity's
|
|
69
|
+
* primary key: records are addressed by it (hide it by omitting `V` from its
|
|
70
|
+
* flags instead).
|
|
71
|
+
*/
|
|
72
|
+
columns: Record<string, EntityViewColumnDef | null>;
|
|
73
|
+
/** Free-form view configuration, stored on entity_view.params. */
|
|
74
|
+
params?: Record<string, unknown>;
|
|
75
|
+
}
|
|
76
|
+
|
|
35
77
|
/** Automatic document numbering config (entity `numberSequence`). */
|
|
36
78
|
export interface NumberSequenceDef {
|
|
37
79
|
/** Column code that receives the auto-generated number. */
|
|
@@ -128,4 +170,15 @@ export interface EntityDef {
|
|
|
128
170
|
accumulation?: AccumulationConfig;
|
|
129
171
|
/** Entity-level platform behavior flags. */
|
|
130
172
|
params?: { restricted?: boolean } & Record<string, unknown>;
|
|
173
|
+
/**
|
|
174
|
+
* Entity views keyed by view name — the platform's column-level security.
|
|
175
|
+
* Unrelated to `isView`/`viewSql` above (a SQL-view-backed entity) and to
|
|
176
|
+
* `ui/data_views.json` (grids, kanban, calendars), both of which the word
|
|
177
|
+
* "view" also names in this platform. A
|
|
178
|
+
* folder binds one view per entity through `ui/folders.json`
|
|
179
|
+
* (`entities.<code>.viewName`); users working in that folder see ONLY the
|
|
180
|
+
* columns the view lists. An entity without views (or a folder naming the
|
|
181
|
+
* conventional `"default"`, which declares nothing) shows the full column set.
|
|
182
|
+
*/
|
|
183
|
+
views?: Record<string, EntityViewDef>;
|
|
131
184
|
}
|
package/src/folders.ts
CHANGED
|
@@ -7,7 +7,16 @@ import type { Filter } from "./filter";
|
|
|
7
7
|
|
|
8
8
|
/** Per-entity binding within a folder. */
|
|
9
9
|
export interface FolderEntityBinding {
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Entity view to bind for this entity in this folder — a key under the entity
|
|
12
|
+
* definition's `views` (see `EntityViewDef`), NOT a data view code from
|
|
13
|
+
* `ui/data_views.json`. Users in this folder then see only the columns that
|
|
14
|
+
* view lists.
|
|
15
|
+
*
|
|
16
|
+
* The conventional `"default"` declares nothing and means "no view" (the full
|
|
17
|
+
* column set); any other name the entity does not declare fails the install,
|
|
18
|
+
* since falling back would grant more access than naming a view asks for.
|
|
19
|
+
*/
|
|
11
20
|
viewName?: string;
|
|
12
21
|
/** Enable the quick-add (+) button for this entity here. */
|
|
13
22
|
quickAdd?: boolean;
|
package/src/index.ts
CHANGED
|
@@ -57,6 +57,8 @@ export { FILTER_GROUP_OPERATORS, FILTER_OPERATORS } from "./filter";
|
|
|
57
57
|
export type {
|
|
58
58
|
EntityDef,
|
|
59
59
|
EntityReference,
|
|
60
|
+
EntityViewDef,
|
|
61
|
+
EntityViewColumnDef,
|
|
60
62
|
NumberSequenceDef,
|
|
61
63
|
PeriodConfig,
|
|
62
64
|
AccumulationConfig,
|
|
@@ -88,6 +90,7 @@ export {
|
|
|
88
90
|
chartTypes,
|
|
89
91
|
type ReportsFile,
|
|
90
92
|
type ReportDef,
|
|
93
|
+
type ReportEntityAttachment,
|
|
91
94
|
type ReportLayout,
|
|
92
95
|
type ReportPanel,
|
|
93
96
|
type Dataset,
|
|
@@ -98,7 +101,7 @@ export {
|
|
|
98
101
|
type VizType,
|
|
99
102
|
} from "./reports";
|
|
100
103
|
|
|
101
|
-
export type { ManifestDef, ManifestAuthor, ModuleDependency } from "./manifest";
|
|
104
|
+
export type { ManifestDef, ManifestAuthor, ModuleDependency, ModuleFeature } from "./manifest";
|
|
102
105
|
export type { DepsFile, DepEntity, DepColumn, DepColumnType, DepColumnMode, DepProvenance, DepProvenanceKind } from "./deps";
|
|
103
106
|
export { DEP_COLUMN_TYPES } from "./deps";
|
|
104
107
|
export type { DomainsFile, DomainDef } from "./domains";
|
package/src/manifest.ts
CHANGED
|
@@ -10,6 +10,13 @@ export interface ManifestAuthor {
|
|
|
10
10
|
/** A dependency value: a semver range, or a partial-dep object. */
|
|
11
11
|
export type ModuleDependency = string | { version: string; entities?: string[] };
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* A platform behaviour a package can opt into via `manifest.features`.
|
|
15
|
+
* Mirrors `dForge.Core.ModuleFeatures` and the `features` enum in
|
|
16
|
+
* manifest.schema.json — all three are edited together.
|
|
17
|
+
*/
|
|
18
|
+
export type ModuleFeature = "report-security";
|
|
19
|
+
|
|
13
20
|
/** A module package manifest (`manifest.json`). */
|
|
14
21
|
export interface ManifestDef {
|
|
15
22
|
/** Package format version (currently 1). */
|
|
@@ -47,6 +54,20 @@ export interface ManifestDef {
|
|
|
47
54
|
icon?: string;
|
|
48
55
|
/** Non-English locales the package promises to translate. */
|
|
49
56
|
supportedLocales?: string[];
|
|
57
|
+
/**
|
|
58
|
+
* Opt-in platform behaviours this package was authored for. Absent or empty
|
|
59
|
+
* = the pre-feature behaviour for all of them, so a module written before a
|
|
60
|
+
* feature existed keeps working until its author declares it and republishes.
|
|
61
|
+
*
|
|
62
|
+
* Unknown names are rejected at package load, never ignored — a misspelled
|
|
63
|
+
* feature would silently leave the old behaviour in place while the manifest
|
|
64
|
+
* claims otherwise.
|
|
65
|
+
*
|
|
66
|
+
* - `report-security` — this module's reports require 'E' on their
|
|
67
|
+
* `sec_object`. Declare the matching `"report:<code>": "E"` grants in
|
|
68
|
+
* `security/roles.json` first, or the reports go dark for every role.
|
|
69
|
+
*/
|
|
70
|
+
features?: ModuleFeature[];
|
|
50
71
|
/** Initial creation date (YYYY-MM-DD). Informational. */
|
|
51
72
|
created?: string;
|
|
52
73
|
/** Last manifest edit date (YYYY-MM-DD). Informational. */
|
package/src/reports.ts
CHANGED
|
@@ -35,25 +35,46 @@ export interface ParamDefBase {
|
|
|
35
35
|
label?: string;
|
|
36
36
|
/** Display order in the parameter form (falls back to declaration order). */
|
|
37
37
|
orderNum?: number;
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Whether the user must provide a value. Stored inverted as `param.is_nullable`.
|
|
40
|
+
* There is no `isRequired` spelling — the installer reads this key only.
|
|
41
|
+
*/
|
|
39
42
|
required?: boolean;
|
|
40
|
-
/** Alternate spelling of `required` used by some modules. Prefer `required`. */
|
|
41
|
-
isRequired?: boolean;
|
|
42
43
|
/** Default value applied when the user doesn't provide one. */
|
|
43
44
|
default?: unknown;
|
|
44
|
-
/** Entity link for lookup-type params. */
|
|
45
|
-
link?: { entity: string; otherKey?: string };
|
|
46
45
|
/**
|
|
47
|
-
* Field-type-specific params
|
|
46
|
+
* Field-type-specific params, nested under this key — there is no top-level
|
|
47
|
+
* `link`. A lookup param needs `{ link: { entity, otherKey? } }`.
|
|
48
|
+
* Most importantly `options` for a dropdown.
|
|
48
49
|
* Options accept the same rich `{value,label,icon,color}` form entity columns
|
|
49
50
|
* use; a bare string list renders the raw codes in every locale, so label them.
|
|
50
51
|
* Omitted on a domain-backed param: the domain owns the list.
|
|
51
52
|
*/
|
|
52
53
|
params?: Record<string, unknown>;
|
|
54
|
+
/**
|
|
55
|
+
* Declares a REFERENCE parameter: the submitted value is the whole picked
|
|
56
|
+
* record rather than its bare key. The JSON counterpart of the action DSL's
|
|
57
|
+
* `paramCd: ref <entityCd>`, stored in the same `param.column_type`.
|
|
58
|
+
*
|
|
59
|
+
* Optional, and the choice is not cosmetic. Omitting it (a plain `lookup`)
|
|
60
|
+
* submits the key, which is what a filter comparing against a reference
|
|
61
|
+
* column needs — the server destructures a key object across every key
|
|
62
|
+
* column and ignores non-key fields. Declare `"R"` when the report wants the
|
|
63
|
+
* record itself, not just its identity.
|
|
64
|
+
*
|
|
65
|
+
* Either way the picker is configured by `params.link` (`{ entity, otherKey? }`);
|
|
66
|
+
* `otherKey` is filled from the target's primary key when omitted, comma-joined
|
|
67
|
+
* and paired POSITIONALLY with the key columns.
|
|
68
|
+
*/
|
|
69
|
+
columnType?: "R";
|
|
53
70
|
}
|
|
54
71
|
|
|
55
72
|
/**
|
|
56
|
-
* A report parameter definition
|
|
73
|
+
* A report parameter definition. Declared in the report-level `parameters` block,
|
|
74
|
+
* or as shorthand under the `params` of the dataset that consumes it — the
|
|
75
|
+
* installer merges both into the report's single param set, so either way the
|
|
76
|
+
* parameter serves the whole report. Report level wins on a code collision, and
|
|
77
|
+
* is the only sensible home for a parameter several datasets use.
|
|
57
78
|
*
|
|
58
79
|
* A parameter takes its control from an explicit `fieldTypeCd` **or** from a
|
|
59
80
|
* column `domain` — never both. Declaring both is the one rejected combination
|
|
@@ -111,10 +132,42 @@ export interface Dataset {
|
|
|
111
132
|
procedureName?: string;
|
|
112
133
|
/** Optional column metadata overrides: field code → override. */
|
|
113
134
|
columnsDef?: Record<string, ColumnDef>;
|
|
114
|
-
/**
|
|
135
|
+
/**
|
|
136
|
+
* Parameters declared on this dataset — shorthand for the report-level
|
|
137
|
+
* `parameters` block, convenient when exactly one dataset uses the parameter.
|
|
138
|
+
* The installer merges both into the report's one param set either way.
|
|
139
|
+
*/
|
|
115
140
|
params?: Record<string, ParamDef>;
|
|
116
141
|
}
|
|
117
142
|
|
|
143
|
+
/**
|
|
144
|
+
* One (entity, report) **record-report attachment**: the report becomes openable
|
|
145
|
+
* from that entity's record, with the record's values feeding its parameters.
|
|
146
|
+
* Each entry becomes one `dForge.entity_report` row.
|
|
147
|
+
*
|
|
148
|
+
* The binding is per-attachment, not per-report — the same report can attach to
|
|
149
|
+
* several entities with different parameter mappings, which is why the mapping
|
|
150
|
+
* lives here rather than on the report.
|
|
151
|
+
*/
|
|
152
|
+
export interface ReportEntityAttachment {
|
|
153
|
+
/**
|
|
154
|
+
* Entity the report attaches to, qualified `module.entity` for anything
|
|
155
|
+
* outside the declaring module. That module must be a declared dependency.
|
|
156
|
+
*/
|
|
157
|
+
entityCd: string;
|
|
158
|
+
/**
|
|
159
|
+
* Parameter mapping: report param code → **source column on the entity**.
|
|
160
|
+
* (Not a param declaration — those live in the report's `parameters` block or a
|
|
161
|
+
* dataset's `params`.) Resolved server-side
|
|
162
|
+
* from the record's PK. Source columns are limited to the PK, reference (`R`)
|
|
163
|
+
* columns, and bounded scalars; source and target must be type-compatible.
|
|
164
|
+
* Params left unmapped keep their normal behaviour (default, or prompt).
|
|
165
|
+
*/
|
|
166
|
+
params?: Record<string, string>;
|
|
167
|
+
/** Sort position in the record's combined action + report menu. */
|
|
168
|
+
orderNum?: number;
|
|
169
|
+
}
|
|
170
|
+
|
|
118
171
|
/** A single visualization panel within the report layout. */
|
|
119
172
|
export interface ReportPanel {
|
|
120
173
|
vizType: VizType;
|
|
@@ -136,8 +189,21 @@ export interface ReportDef {
|
|
|
136
189
|
layout: ReportLayout;
|
|
137
190
|
/** Dataset code → dataset definition. */
|
|
138
191
|
datasets: Record<string, Dataset>;
|
|
139
|
-
/**
|
|
192
|
+
/** Auto-refresh interval in seconds. Omit (or 0) for no auto-refresh. */
|
|
193
|
+
reloadInterval?: number;
|
|
194
|
+
/**
|
|
195
|
+
* Report-level parameter declarations — the canonical home for a parameter, and
|
|
196
|
+
* the only one that fits a parameter several datasets use. Merged with each
|
|
197
|
+
* dataset's `params` into the report's single param set; this block wins on a
|
|
198
|
+
* code collision.
|
|
199
|
+
*/
|
|
140
200
|
parameters?: Record<string, ParamDef>;
|
|
201
|
+
/**
|
|
202
|
+
* Record-report attachments: entities this report can be opened from, with the
|
|
203
|
+
* mapping from report parameter to source column on each. Omit for a report
|
|
204
|
+
* that is only reached from a menu.
|
|
205
|
+
*/
|
|
206
|
+
entities?: ReportEntityAttachment[];
|
|
141
207
|
}
|
|
142
208
|
|
|
143
209
|
/** A `ui/reports.json` file: report code → definition. */
|