@dataverse-kit/form-runtime 0.1.0
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/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/businessRules-U1_MBgyG.d.cts +372 -0
- package/dist/businessRules-U1_MBgyG.d.ts +372 -0
- package/dist/context.cjs +151 -0
- package/dist/context.cjs.map +1 -0
- package/dist/context.d.cts +132 -0
- package/dist/context.d.ts +132 -0
- package/dist/context.mjs +113 -0
- package/dist/context.mjs.map +1 -0
- package/dist/control-DFOg_pc_.d.cts +1027 -0
- package/dist/control-DaXBm-52.d.ts +1027 -0
- package/dist/gridCustomizer-C0V9FAE_.d.ts +569 -0
- package/dist/gridCustomizer-mJO-kmQ4.d.cts +569 -0
- package/dist/hooks.cjs +85 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.cts +24 -0
- package/dist/hooks.d.ts +24 -0
- package/dist/hooks.mjs +60 -0
- package/dist/hooks.mjs.map +1 -0
- package/dist/icons.cjs +202 -0
- package/dist/icons.cjs.map +1 -0
- package/dist/icons.d.cts +130 -0
- package/dist/icons.d.ts +130 -0
- package/dist/icons.mjs +165 -0
- package/dist/icons.mjs.map +1 -0
- package/dist/index.cjs +6509 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +410 -0
- package/dist/index.d.ts +410 -0
- package/dist/index.mjs +6490 -0
- package/dist/index.mjs.map +1 -0
- package/dist/runtime-capabilities-BdGDdu0d.d.cts +119 -0
- package/dist/runtime-capabilities-Brfc7loJ.d.ts +119 -0
- package/dist/theme-BfeZIxmZ.d.cts +74 -0
- package/dist/theme-BfeZIxmZ.d.ts +74 -0
- package/dist/theme.cjs +215 -0
- package/dist/theme.cjs.map +1 -0
- package/dist/theme.d.cts +32 -0
- package/dist/theme.d.ts +32 -0
- package/dist/theme.mjs +186 -0
- package/dist/theme.mjs.map +1 -0
- package/dist/types.cjs +976 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +813 -0
- package/dist/types.d.ts +813 -0
- package/dist/types.mjs +902 -0
- package/dist/types.mjs.map +1 -0
- package/dist/utils.cjs +250 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +99 -0
- package/dist/utils.d.ts +99 -0
- package/dist/utils.mjs +220 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/v8.cjs +4622 -0
- package/dist/v8.cjs.map +1 -0
- package/dist/v8.d.cts +730 -0
- package/dist/v8.d.ts +730 -0
- package/dist/v8.mjs +4622 -0
- package/dist/v8.mjs.map +1 -0
- package/dist/v9.cjs +19 -0
- package/dist/v9.cjs.map +1 -0
- package/dist/v9.d.cts +2 -0
- package/dist/v9.d.ts +2 -0
- package/dist/v9.mjs +1 -0
- package/dist/v9.mjs.map +1 -0
- package/package.json +113 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 khester
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @dataverse-kit/form-runtime
|
|
2
|
+
|
|
3
|
+
Shared React runtime for Dynamics 365 form rendering. Mounted by the
|
|
4
|
+
form-builder designer canvas, the live preview, and code generated for export
|
|
5
|
+
targets (Web Resource, PCF, Static Web App, Standalone Grid Customizer PCF,
|
|
6
|
+
PA Grid Control Customizer). All three paths render the same React tree, so
|
|
7
|
+
what you see in the canvas is what users ship.
|
|
8
|
+
|
|
9
|
+
## Entries
|
|
10
|
+
|
|
11
|
+
| Entry | Purpose |
|
|
12
|
+
|-------|---------|
|
|
13
|
+
| `@dataverse-kit/form-runtime` | v8 default — `<FormRuntime>` rendered with Fluent UI v8 (`@fluentui/react`). The designer canvas always mounts this. |
|
|
14
|
+
| `@dataverse-kit/form-runtime/v9` | v9 sibling — `<FormRuntime>` rendered with Fluent UI v9 (`@fluentui/react-components`). Used by generated v9-target projects. Canvas does **not** mount this (ROADMAP-locked). |
|
|
15
|
+
| `@dataverse-kit/form-runtime/hooks` | FluentUI-agnostic hooks: `useSubgridData`, `useChartData`, `useLookupSearch`, `useFormState`, `useDirtyTracker`. |
|
|
16
|
+
| `@dataverse-kit/form-runtime/utils` | `gridLayoutUtils` — shared by designer/preview/generator for dashboard-layout math. |
|
|
17
|
+
| `@dataverse-kit/form-runtime/theme` | `FormThemeProvider` + `useFormTheme`. |
|
|
18
|
+
|
|
19
|
+
## Dependencies
|
|
20
|
+
|
|
21
|
+
Every consumed `@dataverse-kit/runtime` and `@dataverse-kit/api-service`
|
|
22
|
+
import flows through this package **directly** — no re-exports, no wrappers.
|
|
23
|
+
Per the dynamics-toolkit v1.0 migration preference (full eradication of
|
|
24
|
+
duplicated logic, not wrapper delegation).
|
|
25
|
+
|
|
26
|
+
| Peer dep | Why |
|
|
27
|
+
|----------|-----|
|
|
28
|
+
| `react` (`^16.14 || ^17 || ^18`) | Canvas PCF compatibility caps React at 16.14. |
|
|
29
|
+
| `react-dom` | Same. |
|
|
30
|
+
| `@fluentui/react` (`^8.115`) | v8 default entry. |
|
|
31
|
+
| `@fluentui/react-components` (`^9`) | v9 entry (optional). |
|
|
32
|
+
| `@dataverse-kit/runtime` (`^1`) | FetchXmlParser, ConditionEvaluator, DirtyTracker. |
|
|
33
|
+
| `@dataverse-kit/api-service` (`^0.2`) | `IApiService`, `ServiceFactory`. |
|
|
34
|
+
|
|
35
|
+
## Status
|
|
36
|
+
|
|
37
|
+
**WYSIWYG-canvas refactor complete (2026-05-19).** Every editor
|
|
38
|
+
surface — main canvas, callout editor, and live preview — and every
|
|
39
|
+
generator-emitted host renders through `<FormRuntime>`. The legacy
|
|
40
|
+
parallel rendering pipeline (`ControlRenderer.tsx`, `SectionBlock`,
|
|
41
|
+
`CellBlock`, `CalloutPreview`, `MainFormPreview` etc.) is fully
|
|
42
|
+
retired. ~6,000 LOC of duplicate rendering code deleted across the
|
|
43
|
+
refactor; ~3,000 LOC of feature-parity runtime + tests added.
|
|
44
|
+
|
|
45
|
+
### Phase summary
|
|
46
|
+
|
|
47
|
+
| Phase | Outcome |
|
|
48
|
+
|-------|---------|
|
|
49
|
+
| Phase 1 | Extract this package (`@dataverse-kit/form-runtime`). `<FormRuntime>` dispatcher, 22 per-type v8 controls, capability boundary (`FormRuntimeContext`), instrumentation attrs, live-data hooks. |
|
|
50
|
+
| Phase 2 (m1–m9) | Designer overlay layer (selection, drop zones, drag handles, inline rename, badges, context menu, affordances, empty state, column drops). m9 flipped the runtime canvas + overlay default-on. |
|
|
51
|
+
| Legacy canvas deletion | 7 dead editor-side files removed (`TabBar`, `HeaderBlock`, `CommandBarBlock`, `DialogHeaderBlock`, `DialogButtonsBlock`, `PanelButtonsBlock`, `GridFormCanvas`) — ~1,700 LOC. |
|
|
52
|
+
| Phase 3 (m1–m6) | Runtime gained parity for the legacy preview's features: SectionShell variant/dims/background/collapsible/labels, per-control callouts (`CalloutAnchor`/`CalloutShell`/`CalloutsProvider`), dialog/panel `FooterShell`, business-rule integration (`RuleStatesProvider`), header field summary flyout, tab-content slots (`TabContentSlotsProvider`). m6 deleted the legacy `MainFormPreview`/`DialogFormPreview`/`PanelFormPreview`/`CalloutFormPreview`/`GridFormPreview` paths and the `runtimeCanvasFlag` gate. |
|
|
53
|
+
| Phase 4 | Callout editor moved to runtime (`CalloutEditCanvas` mounts `SectionShell` for section bodies + `CalloutShell` for the preview popup). Cascade deletion of `ControlRenderer.tsx` (2,971 LOC), `SectionBlock.tsx`, `CellBlock.tsx`, `CalloutPreview.tsx` — ~4,100 LOC. |
|
|
54
|
+
|
|
55
|
+
### What this guarantees
|
|
56
|
+
|
|
57
|
+
- **Single source of truth for rendering.** Every form / section /
|
|
58
|
+
cell / control render path runs through the shells in this
|
|
59
|
+
package. No parity-drift risk between editor canvas, preview, and
|
|
60
|
+
generated output.
|
|
61
|
+
- **Designer overlay is feature-complete** for the runtime canvas
|
|
62
|
+
(Phase 2 m1–m8 features all active). Pivot section drops on the
|
|
63
|
+
overlay remain deferred — they need a `SectionShell` pivot-grouping
|
|
64
|
+
pass before they can wire in. Editor-side callout pivot grouping
|
|
65
|
+
works via the form-builder's `DraggablePivotBar`.
|
|
66
|
+
- **Tests: 405 in form-runtime, 352 in form-builder, 1041 in
|
|
67
|
+
export-engine** — all green at the close of Phase 4.
|
|
68
|
+
|
|
69
|
+
### Known deferred items (not blocking)
|
|
70
|
+
|
|
71
|
+
- Pivot section drops on the runtime overlay (waits on
|
|
72
|
+
`SectionShell` pivot-grouping support).
|
|
73
|
+
- Subgrid focused-view / card-list / grid-customizer variants stay
|
|
74
|
+
editor-inline pending follow-up.
|
|
75
|
+
- Live Dataverse entity-image fetch + `PersonaPresence` for
|
|
76
|
+
systemuser lookups in the header flyout — would need a
|
|
77
|
+
`FormRuntimeCapabilities` extension. Initials render fine without
|
|
78
|
+
it.
|
|
79
|
+
- The four hooks declared but not extracted in Phase 1
|
|
80
|
+
(`useFormState`, `useSubgridData`, `useChartData`,
|
|
81
|
+
`useLookupSearch`, `useDirtyTracker`) — the existing editor
|
|
82
|
+
versions are still in use.
|
|
83
|
+
- Package.json `exports` map for `/v8` + `/types/*` subpaths
|
|
84
|
+
(works today via Vite alias; matters for the published-package
|
|
85
|
+
consumer).
|
|
86
|
+
|
|
87
|
+
## Build
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm run typecheck # tsc --noEmit + tests config
|
|
91
|
+
npm run build # tsup → dist/{index,v9,hooks,utils,theme}.{cjs,mjs,d.ts}
|
|
92
|
+
npm run test # vitest run (jsdom environment)
|
|
93
|
+
```
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Business Rules Engine — Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Defines the complete type system for visual business rules:
|
|
5
|
+
* rule definitions, conditions, actions, variables, data sources,
|
|
6
|
+
* execution context, workflows, highlights, and canvas layout.
|
|
7
|
+
*
|
|
8
|
+
* Design principles:
|
|
9
|
+
* - FetchXML-style operator names (eq, gt, like) for Dynamics consultant familiarity
|
|
10
|
+
* - Discriminated unions with `kind` for exhaustive pattern matching on action configs
|
|
11
|
+
* - Record<string, unknown> for JSON-serializable state (not Map/Set)
|
|
12
|
+
* - Reuses existing FormDataSource for FetchXML data sources
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** A complete business rule — stored at entity level, enforced at form level */
|
|
16
|
+
interface BusinessRuleDefinition {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
/** Entity logical name (e.g., "stn_order", "account") */
|
|
21
|
+
entityLogicalName: string;
|
|
22
|
+
/** Where the rule runs */
|
|
23
|
+
scope: 'entity' | 'form' | 'global';
|
|
24
|
+
/** For form-scoped rules */
|
|
25
|
+
targetFormId?: string;
|
|
26
|
+
/** When the rule evaluates */
|
|
27
|
+
trigger: RuleTrigger;
|
|
28
|
+
/** Execution priority (lower = first) */
|
|
29
|
+
priority: number;
|
|
30
|
+
/** Active/inactive toggle */
|
|
31
|
+
enabled: boolean;
|
|
32
|
+
/** Rule-specific data sources (beyond form-level shared ones) */
|
|
33
|
+
dataSources: RuleDataSource[];
|
|
34
|
+
/** Variables computed from data sources, fields, or expressions */
|
|
35
|
+
variables: RuleVariable[];
|
|
36
|
+
/** The IF condition tree */
|
|
37
|
+
conditionTree: RuleConditionGroup;
|
|
38
|
+
/** Actions when condition is TRUE */
|
|
39
|
+
thenActions: RuleAction[];
|
|
40
|
+
/** Actions when condition is FALSE */
|
|
41
|
+
elseActions: RuleAction[];
|
|
42
|
+
/** Visual layout for SVG canvas (Phase 2b) */
|
|
43
|
+
canvas?: RuleCanvasLayout;
|
|
44
|
+
/** Metadata */
|
|
45
|
+
createdAt: string;
|
|
46
|
+
updatedAt: string;
|
|
47
|
+
createdBy?: string;
|
|
48
|
+
}
|
|
49
|
+
interface RuleTrigger {
|
|
50
|
+
type: 'onLoad' | 'onChange' | 'onSave' | 'manual';
|
|
51
|
+
/** For onChange: which fields trigger re-evaluation */
|
|
52
|
+
watchFields?: string[];
|
|
53
|
+
/** For manual: command/button id */
|
|
54
|
+
commandId?: string;
|
|
55
|
+
}
|
|
56
|
+
/** Event that triggers rule evaluation */
|
|
57
|
+
interface TriggerEvent {
|
|
58
|
+
type: RuleTrigger['type'];
|
|
59
|
+
/** For onChange: which field changed */
|
|
60
|
+
fieldName?: string;
|
|
61
|
+
}
|
|
62
|
+
/** A group of conditions joined by AND/OR */
|
|
63
|
+
interface RuleConditionGroup {
|
|
64
|
+
id: string;
|
|
65
|
+
logic: 'and' | 'or';
|
|
66
|
+
conditions: (RuleCondition | RuleConditionGroup)[];
|
|
67
|
+
}
|
|
68
|
+
/** A single condition that evaluates to true/false */
|
|
69
|
+
interface RuleCondition {
|
|
70
|
+
id: string;
|
|
71
|
+
/** Left-hand side source */
|
|
72
|
+
source: 'field' | 'data-source' | 'calculated' | 'form-state';
|
|
73
|
+
/** Field logical name (when source = 'field' or 'form-state') */
|
|
74
|
+
fieldName?: string;
|
|
75
|
+
/** Comparison operator — matches FetchXML operator names */
|
|
76
|
+
operator: ConditionOperator;
|
|
77
|
+
/** Right-hand side literal value */
|
|
78
|
+
value?: ConditionValue;
|
|
79
|
+
/** Right-hand side is another field */
|
|
80
|
+
compareToField?: string;
|
|
81
|
+
/** Data source reference (when source = 'data-source') */
|
|
82
|
+
dataSourceId?: string;
|
|
83
|
+
dataSourceField?: string;
|
|
84
|
+
/** Expression string (when source = 'calculated') */
|
|
85
|
+
expression?: string;
|
|
86
|
+
}
|
|
87
|
+
/** Type guard: is this a condition group (has `logic`) or a leaf condition? */
|
|
88
|
+
declare function isConditionGroup(c: RuleCondition | RuleConditionGroup): c is RuleConditionGroup;
|
|
89
|
+
/** Operators match FetchXML names for consultant familiarity */
|
|
90
|
+
type ConditionOperator = 'eq' | 'ne' | 'gt' | 'ge' | 'lt' | 'le' | 'like' | 'not-like' | 'begins-with' | 'ends-with' | 'null' | 'not-null' | 'between' | 'in' | 'not-in' | 'contain-values' | 'not-contain-values' | 'changed' | 'not-changed';
|
|
91
|
+
type ConditionValue = string | number | boolean | null | string[] | [unknown, unknown];
|
|
92
|
+
interface RuleAction {
|
|
93
|
+
id: string;
|
|
94
|
+
type: RuleActionType;
|
|
95
|
+
/** Primary target — always synced to targets[0] */
|
|
96
|
+
target: ActionTarget;
|
|
97
|
+
/** Multi-target list (when action applies to multiple fields/sections/tabs) */
|
|
98
|
+
targets?: ActionTarget[];
|
|
99
|
+
/** Optional label for the target group (e.g., "Meter Fields") */
|
|
100
|
+
groupName?: string;
|
|
101
|
+
config: ActionConfig;
|
|
102
|
+
/** Execution order within the branch */
|
|
103
|
+
order: number;
|
|
104
|
+
}
|
|
105
|
+
/** Returns targets array, falling back to [action.target] for legacy data */
|
|
106
|
+
declare function getActionTargets(action: RuleAction): ActionTarget[];
|
|
107
|
+
type RuleActionType = 'setFieldValue' | 'setDefaultValue' | 'setVisibility' | 'setLockState' | 'setRequired' | 'showErrorMessage' | 'showRecommendation' | 'setHighlight' | 'setSectionVisibility' | 'setTabVisibility' | 'setSectionLockState' | 'setFormReadOnly' | 'setFormNotification' | 'preventSave' | 'setButtonVisibility' | 'setButtonEnabled' | 'blockCreate' | 'blockUpdate' | 'blockDelete' | 'callCustomAction' | 'callCustomApi' | 'triggerWorkflow' | 'navigateToForm' | 'openDialog';
|
|
108
|
+
interface ActionTarget {
|
|
109
|
+
type: 'field' | 'section' | 'tab' | 'form' | 'button' | 'control';
|
|
110
|
+
/** Control name, section id, tab id, or form id */
|
|
111
|
+
id: string;
|
|
112
|
+
displayName?: string;
|
|
113
|
+
}
|
|
114
|
+
type ActionConfig = SetFieldValueConfig | SetDefaultValueConfig | SetVisibilityConfig | SetLockConfig | SetRequiredConfig | ShowMessageConfig | SetHighlightConfig | SetFormReadOnlyConfig | SetFormNotificationConfig | PreventSaveConfig | CrudBlockConfig | CallApiConfig | TriggerWorkflowConfig | NavigateToFormConfig | OpenDialogConfig;
|
|
115
|
+
interface SetFieldValueConfig {
|
|
116
|
+
kind: 'setFieldValue';
|
|
117
|
+
source: 'constant' | 'variable' | 'expression' | 'field';
|
|
118
|
+
value: unknown;
|
|
119
|
+
}
|
|
120
|
+
interface SetDefaultValueConfig {
|
|
121
|
+
kind: 'setDefaultValue';
|
|
122
|
+
source: 'constant' | 'variable' | 'expression' | 'field';
|
|
123
|
+
value: unknown;
|
|
124
|
+
/** Only apply if field is currently empty */
|
|
125
|
+
onlyIfEmpty: boolean;
|
|
126
|
+
}
|
|
127
|
+
interface SetVisibilityConfig {
|
|
128
|
+
kind: 'setVisibility';
|
|
129
|
+
visible: boolean;
|
|
130
|
+
}
|
|
131
|
+
interface SetLockConfig {
|
|
132
|
+
kind: 'setLock';
|
|
133
|
+
locked: boolean;
|
|
134
|
+
}
|
|
135
|
+
interface SetRequiredConfig {
|
|
136
|
+
kind: 'setRequired';
|
|
137
|
+
level: 'required' | 'recommended' | 'none';
|
|
138
|
+
}
|
|
139
|
+
interface ShowMessageConfig {
|
|
140
|
+
kind: 'showMessage';
|
|
141
|
+
messageType: 'error' | 'warning' | 'info' | 'recommendation';
|
|
142
|
+
message: string;
|
|
143
|
+
/** Supports {{variableName}} interpolation */
|
|
144
|
+
interpolateVariables: boolean;
|
|
145
|
+
}
|
|
146
|
+
interface SetHighlightConfig {
|
|
147
|
+
kind: 'setHighlight';
|
|
148
|
+
/** Hex color (e.g., "#63d868") */
|
|
149
|
+
color: string;
|
|
150
|
+
/** Higher priority wins when multiple rules match */
|
|
151
|
+
priority: number;
|
|
152
|
+
}
|
|
153
|
+
interface SetFormReadOnlyConfig {
|
|
154
|
+
kind: 'setFormReadOnly';
|
|
155
|
+
readOnly: boolean;
|
|
156
|
+
}
|
|
157
|
+
interface SetFormNotificationConfig {
|
|
158
|
+
kind: 'setFormNotification';
|
|
159
|
+
messageType: 'error' | 'warning' | 'info';
|
|
160
|
+
message: string;
|
|
161
|
+
interpolateVariables: boolean;
|
|
162
|
+
}
|
|
163
|
+
interface PreventSaveConfig {
|
|
164
|
+
kind: 'preventSave';
|
|
165
|
+
message: string;
|
|
166
|
+
}
|
|
167
|
+
interface CrudBlockConfig {
|
|
168
|
+
kind: 'crudBlock';
|
|
169
|
+
operation: 'create' | 'update' | 'delete';
|
|
170
|
+
message?: string;
|
|
171
|
+
}
|
|
172
|
+
interface CallApiConfig {
|
|
173
|
+
kind: 'callApi';
|
|
174
|
+
dataSourceId: string;
|
|
175
|
+
resultVariableId?: string;
|
|
176
|
+
onSuccessActions?: RuleAction[];
|
|
177
|
+
onFailureActions?: RuleAction[];
|
|
178
|
+
}
|
|
179
|
+
interface TriggerWorkflowConfig {
|
|
180
|
+
kind: 'triggerWorkflow';
|
|
181
|
+
workflowId: string;
|
|
182
|
+
}
|
|
183
|
+
interface NavigateToFormConfig {
|
|
184
|
+
kind: 'navigateToForm';
|
|
185
|
+
formId: string;
|
|
186
|
+
/** Pass field values to the target form */
|
|
187
|
+
parameterMapping?: Record<string, string>;
|
|
188
|
+
}
|
|
189
|
+
interface OpenDialogConfig {
|
|
190
|
+
kind: 'openDialog';
|
|
191
|
+
formId: string;
|
|
192
|
+
width?: number;
|
|
193
|
+
height?: number;
|
|
194
|
+
}
|
|
195
|
+
interface RuleVariable {
|
|
196
|
+
id: string;
|
|
197
|
+
name: string;
|
|
198
|
+
displayName: string;
|
|
199
|
+
type: 'string' | 'number' | 'boolean' | 'datetime' | 'lookup' | 'optionset';
|
|
200
|
+
source: {
|
|
201
|
+
kind: 'field';
|
|
202
|
+
fieldName: string;
|
|
203
|
+
} | {
|
|
204
|
+
kind: 'dataSource';
|
|
205
|
+
dataSourceId: string;
|
|
206
|
+
outputField: string;
|
|
207
|
+
} | {
|
|
208
|
+
kind: 'expression';
|
|
209
|
+
expression: string;
|
|
210
|
+
} | {
|
|
211
|
+
kind: 'constant';
|
|
212
|
+
value: unknown;
|
|
213
|
+
} | {
|
|
214
|
+
kind: 'context';
|
|
215
|
+
contextPath: string;
|
|
216
|
+
};
|
|
217
|
+
defaultValue?: unknown;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Rule data source — wraps existing FormDataSource with caching,
|
|
221
|
+
* or defines a Custom Action / API source.
|
|
222
|
+
*/
|
|
223
|
+
interface RuleDataSource {
|
|
224
|
+
id: string;
|
|
225
|
+
name: string;
|
|
226
|
+
displayName: string;
|
|
227
|
+
type: 'fetchXml' | 'aggregateFetchXml' | 'customAction' | 'customApi';
|
|
228
|
+
/**
|
|
229
|
+
* For fetchXml/aggregateFetchXml: reference an existing FormDataSource by id.
|
|
230
|
+
* Avoids duplicating FetchXML definitions.
|
|
231
|
+
*/
|
|
232
|
+
formDataSourceId?: string;
|
|
233
|
+
/**
|
|
234
|
+
* Inline FetchXML when not referencing a shared FormDataSource.
|
|
235
|
+
* Supports {{fieldName}} placeholders.
|
|
236
|
+
*/
|
|
237
|
+
fetchXml?: string;
|
|
238
|
+
/** Custom Action / API configuration (Phase 3) */
|
|
239
|
+
apiConfig?: {
|
|
240
|
+
actionName: string;
|
|
241
|
+
inputParameters: ApiParameter[];
|
|
242
|
+
outputParameters: ApiParameter[];
|
|
243
|
+
};
|
|
244
|
+
/** Caching strategy */
|
|
245
|
+
cache: {
|
|
246
|
+
enabled: boolean;
|
|
247
|
+
ttlSeconds: number;
|
|
248
|
+
invalidateOn?: string[];
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
interface ApiParameter {
|
|
252
|
+
name: string;
|
|
253
|
+
type: string;
|
|
254
|
+
source: 'field' | 'variable' | 'constant';
|
|
255
|
+
value: string;
|
|
256
|
+
}
|
|
257
|
+
/** Full runtime context — plain objects for JSON-serializable portions */
|
|
258
|
+
interface RuleExecutionContext {
|
|
259
|
+
/** Current form field values */
|
|
260
|
+
formData: Record<string, unknown>;
|
|
261
|
+
/** Original values at load time (for dirty detection) */
|
|
262
|
+
originalData: Record<string, unknown>;
|
|
263
|
+
/** Fields changed since load (runtime only, not serialized) */
|
|
264
|
+
dirtyFields: Set<string>;
|
|
265
|
+
/** Resolved data source results */
|
|
266
|
+
dataSourceResults: Record<string, unknown>;
|
|
267
|
+
/** Resolved variable values */
|
|
268
|
+
variableValues: Record<string, unknown>;
|
|
269
|
+
/** Form-level state */
|
|
270
|
+
formState: {
|
|
271
|
+
isNew: boolean;
|
|
272
|
+
isDirty: boolean;
|
|
273
|
+
isValid: boolean;
|
|
274
|
+
isSaving: boolean;
|
|
275
|
+
formId: string;
|
|
276
|
+
entityLogicalName: string;
|
|
277
|
+
recordId?: string;
|
|
278
|
+
lastSaved?: string;
|
|
279
|
+
};
|
|
280
|
+
/** Custom Action results (Phase 3) */
|
|
281
|
+
customActionResults: Record<string, unknown>;
|
|
282
|
+
}
|
|
283
|
+
interface RuleExecutionResult {
|
|
284
|
+
ruleId: string;
|
|
285
|
+
ruleName: string;
|
|
286
|
+
conditionMet: boolean;
|
|
287
|
+
actionsExecuted: ActionResult[];
|
|
288
|
+
error?: string;
|
|
289
|
+
durationMs: number;
|
|
290
|
+
}
|
|
291
|
+
interface ActionResult {
|
|
292
|
+
actionId: string;
|
|
293
|
+
actionType: RuleActionType;
|
|
294
|
+
targetId: string;
|
|
295
|
+
success: boolean;
|
|
296
|
+
error?: string;
|
|
297
|
+
}
|
|
298
|
+
interface FieldState {
|
|
299
|
+
visible: boolean;
|
|
300
|
+
locked: boolean;
|
|
301
|
+
required: 'required' | 'recommended' | 'none';
|
|
302
|
+
errorMessage?: string;
|
|
303
|
+
warningMessage?: string;
|
|
304
|
+
recommendationMessage?: string;
|
|
305
|
+
highlightColor?: string;
|
|
306
|
+
}
|
|
307
|
+
interface SectionState {
|
|
308
|
+
visible: boolean;
|
|
309
|
+
locked: boolean;
|
|
310
|
+
}
|
|
311
|
+
interface TabState {
|
|
312
|
+
visible: boolean;
|
|
313
|
+
}
|
|
314
|
+
interface FormNotification {
|
|
315
|
+
id: string;
|
|
316
|
+
type: 'error' | 'warning' | 'info';
|
|
317
|
+
message: string;
|
|
318
|
+
ruleId: string;
|
|
319
|
+
}
|
|
320
|
+
interface WorkflowDefinition {
|
|
321
|
+
id: string;
|
|
322
|
+
name: string;
|
|
323
|
+
description?: string;
|
|
324
|
+
trigger: 'on-save' | 'on-field-change' | 'on-load' | 'manual';
|
|
325
|
+
triggerField?: string;
|
|
326
|
+
steps: WorkflowStep[];
|
|
327
|
+
}
|
|
328
|
+
interface WorkflowStep {
|
|
329
|
+
id: string;
|
|
330
|
+
type: 'validate' | 'save' | 'call-action' | 'refresh' | 'evaluate-rules' | 'set-field';
|
|
331
|
+
actionName?: string;
|
|
332
|
+
fieldName?: string;
|
|
333
|
+
fieldValue?: unknown;
|
|
334
|
+
onError: 'stop' | 'continue' | 'rollback';
|
|
335
|
+
}
|
|
336
|
+
interface WorkflowResult {
|
|
337
|
+
workflowId: string;
|
|
338
|
+
success: boolean;
|
|
339
|
+
steps: WorkflowStepResult[];
|
|
340
|
+
}
|
|
341
|
+
interface WorkflowStepResult {
|
|
342
|
+
stepId: string;
|
|
343
|
+
success: boolean;
|
|
344
|
+
result?: unknown;
|
|
345
|
+
error?: string;
|
|
346
|
+
}
|
|
347
|
+
interface RuleCanvasLayout {
|
|
348
|
+
nodes: CanvasNode[];
|
|
349
|
+
connections: CanvasConnection[];
|
|
350
|
+
zoom: number;
|
|
351
|
+
panX: number;
|
|
352
|
+
panY: number;
|
|
353
|
+
}
|
|
354
|
+
interface CanvasNode {
|
|
355
|
+
id: string;
|
|
356
|
+
type: 'condition' | 'action' | 'branch';
|
|
357
|
+
x: number;
|
|
358
|
+
y: number;
|
|
359
|
+
width: number;
|
|
360
|
+
height: number;
|
|
361
|
+
}
|
|
362
|
+
interface CanvasConnection {
|
|
363
|
+
fromNodeId: string;
|
|
364
|
+
toNodeId: string;
|
|
365
|
+
type: 'then' | 'else' | 'sequence';
|
|
366
|
+
}
|
|
367
|
+
/** Creates a minimal empty rule definition */
|
|
368
|
+
declare function createDefaultBusinessRule(entityLogicalName: string, name?: string): BusinessRuleDefinition;
|
|
369
|
+
/** Creates a default field state (visible, unlocked, not required) */
|
|
370
|
+
declare function createDefaultFieldState(): FieldState;
|
|
371
|
+
|
|
372
|
+
export { type ActionConfig as A, type BusinessRuleDefinition as B, type CallApiConfig as C, type ShowMessageConfig as D, type TriggerEvent as E, type FieldState as F, type TriggerWorkflowConfig as G, type WorkflowResult as H, type WorkflowStep as I, type WorkflowStepResult as J, createDefaultBusinessRule as K, createDefaultFieldState as L, getActionTargets as M, type NavigateToFormConfig as N, type OpenDialogConfig as O, type PreventSaveConfig as P, isConditionGroup as Q, type RuleAction as R, type SectionState as S, type TabState as T, type WorkflowDefinition as W, type ActionResult as a, type ActionTarget as b, type ApiParameter as c, type CanvasConnection as d, type CanvasNode as e, type ConditionOperator as f, type ConditionValue as g, type CrudBlockConfig as h, type FormNotification as i, type RuleActionType as j, type RuleCanvasLayout as k, type RuleCondition as l, type RuleConditionGroup as m, type RuleDataSource as n, type RuleExecutionContext as o, type RuleExecutionResult as p, type RuleTrigger as q, type RuleVariable as r, type SetDefaultValueConfig as s, type SetFieldValueConfig as t, type SetFormNotificationConfig as u, type SetFormReadOnlyConfig as v, type SetHighlightConfig as w, type SetLockConfig as x, type SetRequiredConfig as y, type SetVisibilityConfig as z };
|