@dataverse-kit/export-engine 1.0.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/dist/index.cjs +24201 -0
- package/dist/index.d.cts +658 -0
- package/dist/index.d.ts +658 -0
- package/dist/index.mjs +24098 -0
- package/package.json +59 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
import { FormDefinition, BusinessRuleDefinition, RuleVariable, WorkflowDefinition, BusinessProcessFlowDefinition, FormSelectorRule, GridCustomizerDefinition, ControlType, GridColumnDefinition, SubgridColumn, GridColumnDataType } from '@dataverse-kit/form-runtime/types';
|
|
2
|
+
export { V8_ICONS_WITHOUT_V9, V8_PERSONA_SIZE_TO_V9, V8_PRESENCE_TO_V9_STATUS, V8_TO_V9_ICON_MAP, V9IconName, buildV9IconImport, mapV8IconToV9, mapV8PersonaSizeToV9, mapV8PresenceToV9Status, sanitizeV8EnumIdentifier, sanitizeV8PersonaSizeName, sanitizeV8PresenceName } from '@dataverse-kit/form-runtime/icons';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Export-pipeline types owned by export-engine.
|
|
6
|
+
*
|
|
7
|
+
* These are export concepts (target / method / options) — they belong to the
|
|
8
|
+
* export package, not the app. The form-builder app and the design-only fork
|
|
9
|
+
* each keep their own `types/export.ts`; those are structurally identical, so
|
|
10
|
+
* an app's `ExportOptions`/`ExportTarget` is assignable at the `exportProject`
|
|
11
|
+
* call boundary without either app importing from the other.
|
|
12
|
+
*/
|
|
13
|
+
type ExportTarget = 'web-resource' | 'pcf' | 'static-web-app';
|
|
14
|
+
type ExportMethod = 'zip' | 'folder';
|
|
15
|
+
type DeployTarget = {
|
|
16
|
+
type: 'none';
|
|
17
|
+
} | {
|
|
18
|
+
type: 'app';
|
|
19
|
+
appId: string;
|
|
20
|
+
title?: string;
|
|
21
|
+
};
|
|
22
|
+
interface ExportOptions {
|
|
23
|
+
target: ExportTarget;
|
|
24
|
+
projectName: string;
|
|
25
|
+
namespace?: string;
|
|
26
|
+
publisherPrefix?: string;
|
|
27
|
+
includeDeployScript: boolean;
|
|
28
|
+
minify: boolean;
|
|
29
|
+
exportMethod: ExportMethod;
|
|
30
|
+
dataverseUrl?: string;
|
|
31
|
+
deployTarget?: DeployTarget;
|
|
32
|
+
includeSampleData?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* When set, overrides the smart default for generating the DAL (models,
|
|
35
|
+
* constants, hooks). When undefined, the generator computes a default from
|
|
36
|
+
* the project's bindings and saved preferences.
|
|
37
|
+
*/
|
|
38
|
+
generateDataAccessLayer?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Per-export override for the component library used by generated code.
|
|
41
|
+
* Precedence: this field → `project.componentLibrary` → `'fluent-v8'`.
|
|
42
|
+
*/
|
|
43
|
+
componentLibrary?: 'fluent-v8' | 'fluent-v9';
|
|
44
|
+
/**
|
|
45
|
+
* When true, the export engine additionally emits a "rich entity models"
|
|
46
|
+
* tree under `src/entities/` produced by `@dataverse-kit/entity-gen`
|
|
47
|
+
* (only when the rich-entity generator is registered — see ExportEngine's
|
|
48
|
+
* registration seam). Additive; the `generateDataAccessLayer` output is
|
|
49
|
+
* untouched.
|
|
50
|
+
*/
|
|
51
|
+
useRichEntityModels?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Snapshot of Dataverse metadata cached in the UI at export time, keyed by
|
|
54
|
+
* entity logical name. ExportEngine is a pure library — it can't reach into
|
|
55
|
+
* a store — so the snapshot is plumbed through here. Only consumed when
|
|
56
|
+
* `useRichEntityModels` is on.
|
|
57
|
+
*/
|
|
58
|
+
dataverseMetadataSnapshot?: Record<string, unknown>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Project model as export-engine sees it.
|
|
63
|
+
*
|
|
64
|
+
* Owned here (not imported from an app) so the package has no dependency on
|
|
65
|
+
* `apps/*`. The Dataverse-subsystem fields are optional and typed from the
|
|
66
|
+
* shared `@dataverse-kit/form-runtime` types — so both the form-builder app's
|
|
67
|
+
* full project (which populates them) and the design-only fork's stripped
|
|
68
|
+
* project (which omits them) are structurally assignable at the export
|
|
69
|
+
* boundary. Each app still owns its own canonical `FormBuilderProject`; this is
|
|
70
|
+
* the structural contract export-engine consumes.
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Export-time options that persist per project so the user's last choice is
|
|
75
|
+
* remembered. Generators still compute smart defaults when a field is unset.
|
|
76
|
+
*/
|
|
77
|
+
interface ProjectExportOptions {
|
|
78
|
+
generateDataAccessLayer?: boolean;
|
|
79
|
+
includeSampleData?: boolean;
|
|
80
|
+
}
|
|
81
|
+
interface FormBuilderProject {
|
|
82
|
+
id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
description: string;
|
|
85
|
+
exportTarget: ExportTarget;
|
|
86
|
+
componentLibrary: 'fluent-v8' | 'fluent-v9';
|
|
87
|
+
forms: FormDefinition[];
|
|
88
|
+
createdAt: string;
|
|
89
|
+
updatedAt: string;
|
|
90
|
+
dataverseUrl?: string;
|
|
91
|
+
/** Schema version for project-level migrations. */
|
|
92
|
+
schemaVersion: number;
|
|
93
|
+
businessRules?: BusinessRuleDefinition[];
|
|
94
|
+
sharedVariables?: RuleVariable[];
|
|
95
|
+
workflows?: WorkflowDefinition[];
|
|
96
|
+
businessProcessFlows?: BusinessProcessFlowDefinition[];
|
|
97
|
+
formSelectorRules?: FormSelectorRule[];
|
|
98
|
+
gridCustomizers?: GridCustomizerDefinition[];
|
|
99
|
+
/** Per-project export preferences that survive across sessions. */
|
|
100
|
+
exportOptions?: ProjectExportOptions;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Shared helper for resolving the effective component library (Fluent UI v8
|
|
105
|
+
* or v9) for a given export. Generators call this so the precedence rule
|
|
106
|
+
* lives in one place.
|
|
107
|
+
*
|
|
108
|
+
* Phase 3a wires this through to every generator but no generator branches
|
|
109
|
+
* on it yet — output remains v8 for now. Phases 3b–3e add the v9 code paths.
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
type ComponentLibrary = 'fluent-v8' | 'fluent-v9';
|
|
113
|
+
/**
|
|
114
|
+
* Returns the effective component library for a project/export.
|
|
115
|
+
*
|
|
116
|
+
* Priority:
|
|
117
|
+
* 1. Explicit ExportOptions.componentLibrary if present
|
|
118
|
+
* 2. Project-level FormBuilderProject.componentLibrary
|
|
119
|
+
* 3. 'fluent-v8' (legacy default — preserves current behavior)
|
|
120
|
+
*/
|
|
121
|
+
declare function resolveComponentLibrary(project: FormBuilderProject, options?: ExportOptions): ComponentLibrary;
|
|
122
|
+
|
|
123
|
+
/** Result of generating code for a single form. */
|
|
124
|
+
interface GeneratedFile {
|
|
125
|
+
path: string;
|
|
126
|
+
content: string;
|
|
127
|
+
}
|
|
128
|
+
/** Options for form code generation. */
|
|
129
|
+
interface GenerateFormCodeOptions {
|
|
130
|
+
/** 'overlay' wraps in Dialog/Panel/Callout; 'fullpage' renders directly for solo web resources. */
|
|
131
|
+
renderMode?: 'overlay' | 'fullpage';
|
|
132
|
+
/** When true, integrates useBusinessRules hook for runtime visibility/lock/required. */
|
|
133
|
+
hasBusinessRules?: boolean;
|
|
134
|
+
/** Grid customizer definitions from the project — enables inline renderer generation for linked subgrids. */
|
|
135
|
+
gridCustomizers?: GridCustomizerDefinition[];
|
|
136
|
+
/** When true, populates subgrids with sample data instead of empty arrays. */
|
|
137
|
+
includeSampleData?: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* When true, subgrids emit helper components that consume the DAL hooks
|
|
140
|
+
* generated by EntityDataLayerGenerator. Callers should only enable this
|
|
141
|
+
* when they are also emitting the DAL files alongside the form code.
|
|
142
|
+
*/
|
|
143
|
+
includeDataAccessLayer?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Reserved for the v9 code path. Phase 3a wires this through but the
|
|
146
|
+
* generator currently emits Fluent UI v8 only. Phases 3b-3e will branch
|
|
147
|
+
* imports, control mappings, theme provider, and styles based on this.
|
|
148
|
+
*/
|
|
149
|
+
componentLibrary?: 'fluent-v8' | 'fluent-v9';
|
|
150
|
+
}
|
|
151
|
+
/** Generate React component source files from a FormDefinition. */
|
|
152
|
+
declare function generateFormCode(form: FormDefinition, options?: GenerateFormCodeOptions): GeneratedFile[];
|
|
153
|
+
/** Options for `generateAllFormCode`. */
|
|
154
|
+
interface GenerateAllFormCodeOptions {
|
|
155
|
+
/** Per-form render mode. Defaults to 'overlay' for any form not listed. */
|
|
156
|
+
renderModes?: Record<string, 'overlay' | 'fullpage'>;
|
|
157
|
+
/** When true, integrates useBusinessRules hook for runtime visibility/lock/required. */
|
|
158
|
+
hasBusinessRules?: boolean;
|
|
159
|
+
/** Grid customizer definitions from the project — enables inline renderer generation for linked subgrids. */
|
|
160
|
+
gridCustomizers?: GridCustomizerDefinition[];
|
|
161
|
+
/** When true, populates subgrids with sample data instead of empty arrays. */
|
|
162
|
+
includeSampleData?: boolean;
|
|
163
|
+
/** When true, subgrids emit helper components that consume the DAL hooks. */
|
|
164
|
+
includeDataAccessLayer?: boolean;
|
|
165
|
+
/** Reserved for the v9 code path; Phase 3a does not branch on this. */
|
|
166
|
+
componentLibrary?: 'fluent-v8' | 'fluent-v9';
|
|
167
|
+
}
|
|
168
|
+
/** Generate code for all forms in a project and an index barrel. */
|
|
169
|
+
declare function generateAllFormCode(forms: FormDefinition[], options?: GenerateAllFormCodeOptions): GeneratedFile[];
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Phase 3f.1 review fix — shared v9 control-type compatibility constants.
|
|
173
|
+
*
|
|
174
|
+
* Both `v9CompatibilityScanner` (consumer-facing) and `FormCodeGenerator`
|
|
175
|
+
* (generator-facing) need to know which control types lack a Fluent UI
|
|
176
|
+
* v9 equivalent. Extracting the constant + predicate here breaks the
|
|
177
|
+
* scanner→generator import edge that the architectural review flagged
|
|
178
|
+
* and gives any future consumer (UI badges, custom-control manifests,
|
|
179
|
+
* exporter validation) a stable, dependency-free import target.
|
|
180
|
+
*
|
|
181
|
+
* Edit `V9_INCOMPATIBLE_CONTROL_TYPES` to add a new Track B control.
|
|
182
|
+
* Reasons live in the scanner module (UI-facing copy).
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Set of control types with no Fluent UI v9 equivalent. Track B in the
|
|
187
|
+
* Phase 3f migration plan — these controls are excluded from v9 exports
|
|
188
|
+
* (placeholder div emitted, ExportDialog warning shown) rather than
|
|
189
|
+
* migrated.
|
|
190
|
+
*/
|
|
191
|
+
declare const V9_INCOMPATIBLE_CONTROL_TYPES: ReadonlySet<ControlType>;
|
|
192
|
+
/**
|
|
193
|
+
* Test whether a control type can be emitted under Fluent UI v9. A
|
|
194
|
+
* compatible control either has a v9 equivalent today or has one
|
|
195
|
+
* planned in a future Phase 3f sub-phase (currently emitting v8
|
|
196
|
+
* fallback inside FluentProvider — still renders correctly).
|
|
197
|
+
*/
|
|
198
|
+
declare function isControlV9Compatible(controlType: ControlType): boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Phase 1b — symmetric counterpart to `V9_INCOMPATIBLE_CONTROL_TYPES`.
|
|
201
|
+
*
|
|
202
|
+
* Set of control types with no Fluent UI v8 equivalent in
|
|
203
|
+
* `@dataverse-kit/components`. These controls can only render under v9
|
|
204
|
+
* export targets — ExportDialog blocks v8-only targets (Power Pages Web
|
|
205
|
+
* Resource, Canvas App PCF) when the project uses any v9-required control.
|
|
206
|
+
*
|
|
207
|
+
* Currently flagged via `requiresV9: true` on the ControlRegistryEntry in
|
|
208
|
+
* `apps/form-builder/src/utils/controlMetadata.ts`. The constant here is
|
|
209
|
+
* the authoritative list for the export-engine scanner; keeping the names
|
|
210
|
+
* synced between the form-builder registry and this set is enforced by
|
|
211
|
+
* tests in `v9CompatibilityScanner.test.ts`.
|
|
212
|
+
*/
|
|
213
|
+
declare const V9_REQUIRED_CONTROL_TYPES: ReadonlySet<ControlType>;
|
|
214
|
+
/**
|
|
215
|
+
* Test whether a control type requires Fluent UI v9. A v9-required
|
|
216
|
+
* control has no v8 equivalent in the workspace component library and
|
|
217
|
+
* therefore cannot render under v8 export targets.
|
|
218
|
+
*/
|
|
219
|
+
declare function isControlV9Required(controlType: ControlType): boolean;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Phase 3f.1 — v9 compatibility scanner.
|
|
223
|
+
*
|
|
224
|
+
* Walks a `FormBuilderProject` and reports every control whose type
|
|
225
|
+
* has no Fluent UI v9 equivalent. Used by:
|
|
226
|
+
* 1. ExportDialog — pre-export warning when user picks v9 + project
|
|
227
|
+
* contains incompatible controls. User can cancel or proceed; if
|
|
228
|
+
* they proceed, the generator emits a placeholder for the control
|
|
229
|
+
* instead of the v8 component.
|
|
230
|
+
* 2. Designer canvas/palette — future hookup to badge incompatible
|
|
231
|
+
* controls with a ⚠ icon when project's componentLibrary is v9.
|
|
232
|
+
*
|
|
233
|
+
* **Track A** controls (have v9 equivalent — to be migrated in 3f.2–3f.7)
|
|
234
|
+
* are NOT reported. Until their migration ships they keep emitting v8
|
|
235
|
+
* fallback inside FluentProvider, which works correctly.
|
|
236
|
+
*
|
|
237
|
+
* **Track B** controls (no v9 equivalent — permanently excluded under v9):
|
|
238
|
+
* - `rating` — no v9 control
|
|
239
|
+
* - `timeline` — custom Dynamics surface, no v9 equivalent
|
|
240
|
+
* - `webresource` — embeds v8 HTML resources, not applicable to v9
|
|
241
|
+
*
|
|
242
|
+
* Custom controls (Item 6, future) will declare their own
|
|
243
|
+
* `componentLibraryCompatibility` in their manifest. When that lands,
|
|
244
|
+
* extend `isControlV9Compatible` to consult the manifest registry.
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Why a control is incompatible with v9. Today only one reason exists,
|
|
249
|
+
* but the scanner returns it as a tagged value so the warning UI can
|
|
250
|
+
* render different copy per category and so future categories (e.g.
|
|
251
|
+
* `'custom-control-no-v9-decl'` from Item 6) slot in cleanly.
|
|
252
|
+
*/
|
|
253
|
+
type V9IncompatibilityReason = 'no-v9-control';
|
|
254
|
+
/** A specific incompatible control's location in the project. */
|
|
255
|
+
interface V9IncompatibleRef {
|
|
256
|
+
/** Control type string (e.g. `'rating'`). */
|
|
257
|
+
controlType: ControlType;
|
|
258
|
+
/** Author-friendly name for the control (e.g. `'starRating'`). */
|
|
259
|
+
controlName: string;
|
|
260
|
+
/** Author-friendly label (e.g. `'Customer Satisfaction'`). */
|
|
261
|
+
controlLabel: string;
|
|
262
|
+
/** Reason category for the warning UI. */
|
|
263
|
+
reason: V9IncompatibilityReason;
|
|
264
|
+
/** Human-readable explanation for the warning UI. */
|
|
265
|
+
reasonText: string;
|
|
266
|
+
/** Form containing the control. */
|
|
267
|
+
formId: string;
|
|
268
|
+
formName: string;
|
|
269
|
+
/** Tab containing the control (only for main forms). */
|
|
270
|
+
tabId?: string;
|
|
271
|
+
tabLabel?: string;
|
|
272
|
+
/** Section containing the control. `'header'` for header cells, `'callout:<id>'` for callout sections. */
|
|
273
|
+
sectionId: string;
|
|
274
|
+
sectionLabel: string;
|
|
275
|
+
/** Cell containing the control. */
|
|
276
|
+
cellId: string;
|
|
277
|
+
}
|
|
278
|
+
/** Result returned from `scanV9Compatibility`. */
|
|
279
|
+
interface V9CompatibilityResult {
|
|
280
|
+
/** Controls that will be omitted from v9 output (placeholder emitted instead). */
|
|
281
|
+
excluded: V9IncompatibleRef[];
|
|
282
|
+
/** Convenience flag: true iff `excluded.length === 0`. */
|
|
283
|
+
isCompatible: boolean;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Walk a project and collect every control whose type is in the v9
|
|
287
|
+
* incompatibility set. Idempotent and side-effect-free; safe to call
|
|
288
|
+
* from React render paths.
|
|
289
|
+
*/
|
|
290
|
+
declare function scanV9Compatibility(project: FormBuilderProject): V9CompatibilityResult;
|
|
291
|
+
/**
|
|
292
|
+
* Format a result as a single human-readable summary string. Used by
|
|
293
|
+
* ExportDialog when the warning needs to be inlined (e.g. small
|
|
294
|
+
* MessageBar variants without a list view). Returns empty string when
|
|
295
|
+
* `result.isCompatible` is true.
|
|
296
|
+
*/
|
|
297
|
+
declare function summarizeV9Incompatibility(result: V9CompatibilityResult): string;
|
|
298
|
+
/**
|
|
299
|
+
* Why a control requires v9. Today only one reason exists (no v8 equivalent
|
|
300
|
+
* in `@dataverse-kit/components`), but the tagged value lets future
|
|
301
|
+
* categories — e.g. custom controls declaring `requiresV9` in their
|
|
302
|
+
* manifest — slot in cleanly.
|
|
303
|
+
*/
|
|
304
|
+
type V9RequirementReason = 'no-v8-control';
|
|
305
|
+
/** A specific v9-required control's location in the project. */
|
|
306
|
+
interface V9RequiredRef {
|
|
307
|
+
controlType: ControlType;
|
|
308
|
+
controlName: string;
|
|
309
|
+
controlLabel: string;
|
|
310
|
+
reason: V9RequirementReason;
|
|
311
|
+
reasonText: string;
|
|
312
|
+
formId: string;
|
|
313
|
+
formName: string;
|
|
314
|
+
tabId?: string;
|
|
315
|
+
tabLabel?: string;
|
|
316
|
+
sectionId: string;
|
|
317
|
+
sectionLabel: string;
|
|
318
|
+
cellId: string;
|
|
319
|
+
}
|
|
320
|
+
/** Result returned from `scanV9Requirements`. */
|
|
321
|
+
interface V9RequirementResult {
|
|
322
|
+
/** Controls that cannot render under v8 export targets. */
|
|
323
|
+
required: V9RequiredRef[];
|
|
324
|
+
/** Convenience flag: true iff `required.length === 0`. */
|
|
325
|
+
isV8Compatible: boolean;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Walk a project and collect every control whose type is in the v9-required
|
|
329
|
+
* set. Uses the shared `walkProjectControls` engine so designer/preview/
|
|
330
|
+
* generator/scanner all visit the same surfaces by construction.
|
|
331
|
+
*
|
|
332
|
+
* Used by:
|
|
333
|
+
* 1. ExportDialog — disables v8-only target options + shows error
|
|
334
|
+
* MessageBar listing the offending controls when the project has any.
|
|
335
|
+
* 2. `validateExportTarget` in the export-engine entry — rejects v8
|
|
336
|
+
* target exports with a typed `V9RequirementError` for headless
|
|
337
|
+
* callers that skip the dialog.
|
|
338
|
+
*/
|
|
339
|
+
declare function scanV9Requirements(project: FormBuilderProject): V9RequirementResult;
|
|
340
|
+
/**
|
|
341
|
+
* Single human-readable summary for the requirement result. Mirrors
|
|
342
|
+
* `summarizeV9Incompatibility` so ExportDialog can use either consistently.
|
|
343
|
+
*/
|
|
344
|
+
declare function summarizeV9Requirements(result: V9RequirementResult): string;
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Rich-entity (Dataverse codegen) generator — injected via a registration
|
|
348
|
+
* seam instead of a static import so the entity-gen package is NOT pulled into
|
|
349
|
+
* browser builds that don't use it. The full root barrel (`./index`) registers
|
|
350
|
+
* the real `generateRichEntityModelFiles`; the browser barrel (`./browser`)
|
|
351
|
+
* does not register anything, so design-only consumers never bundle entity-gen.
|
|
352
|
+
* When unregistered, `generateProjectFiles` simply emits no rich-entity files.
|
|
353
|
+
*/
|
|
354
|
+
type RichEntityGenerator = (project: FormBuilderProject, options: ExportOptions) => GeneratedFile[];
|
|
355
|
+
declare function registerRichEntityGenerator(fn: RichEntityGenerator | null): void;
|
|
356
|
+
/**
|
|
357
|
+
* Thrown by `exportProject` / `validateExportTarget` when the chosen
|
|
358
|
+
* export target cannot host a v9-required control. Callers (CLI, headless
|
|
359
|
+
* pipelines, or the ExportDialog as a defense-in-depth) should catch this
|
|
360
|
+
* and surface the offending control list rather than retrying.
|
|
361
|
+
*/
|
|
362
|
+
declare class V9RequirementError extends Error {
|
|
363
|
+
readonly required: V9RequiredRef[];
|
|
364
|
+
constructor(required: V9RequiredRef[]);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Pre-export gate: when the resolved component library is v8 and the
|
|
368
|
+
* project contains any v9-required controls (funnel/scatter), reject
|
|
369
|
+
* the export with a typed error listing the offenders.
|
|
370
|
+
*
|
|
371
|
+
* The ExportDialog blocks this via UI affordances, but headless callers
|
|
372
|
+
* (CLI, batch pipelines, future automation) bypass the dialog — keeping
|
|
373
|
+
* the gate at the engine layer protects them too.
|
|
374
|
+
*
|
|
375
|
+
* **Critical**: resolves the effective library via `resolveComponentLibrary`
|
|
376
|
+
* before checking. `options.componentLibrary` is allowed to be undefined
|
|
377
|
+
* (precedence: option → project.componentLibrary → 'fluent-v8'). Without
|
|
378
|
+
* the resolver the gate would fail open when a caller passes undefined on
|
|
379
|
+
* a project whose stored default is v8.
|
|
380
|
+
*/
|
|
381
|
+
declare function validateExportTarget(project: FormBuilderProject, options: ExportOptions): {
|
|
382
|
+
ok: true;
|
|
383
|
+
} | {
|
|
384
|
+
ok: false;
|
|
385
|
+
reason: V9RequirementError;
|
|
386
|
+
};
|
|
387
|
+
/** Export project using the chosen method (ZIP download or folder picker). */
|
|
388
|
+
declare function exportProject(project: FormBuilderProject, options: ExportOptions): Promise<void>;
|
|
389
|
+
/**
|
|
390
|
+
* Preview generated files without downloading. Does NOT enforce the
|
|
391
|
+
* v9-required gate — preview is a read-only inspection used by the dialog
|
|
392
|
+
* to show the file tree even when the export would be blocked. Callers
|
|
393
|
+
* that need the gate should invoke `validateExportTarget` themselves.
|
|
394
|
+
*/
|
|
395
|
+
declare function previewExport(project: FormBuilderProject, options: ExportOptions): GeneratedFile[];
|
|
396
|
+
|
|
397
|
+
/** Generate a complete CRA + rewire project for Dynamics 365 Web Resources. */
|
|
398
|
+
declare function generateWebResourceProject(project: FormBuilderProject, options?: ExportOptions): GeneratedFile[];
|
|
399
|
+
|
|
400
|
+
/** Generate a PCF control scaffold that embeds the generated forms. */
|
|
401
|
+
declare function generatePcfProject(project: FormBuilderProject, options?: ExportOptions): GeneratedFile[];
|
|
402
|
+
|
|
403
|
+
/** Generate a standard Vite + React project for Azure Static Web Apps or standalone hosting. */
|
|
404
|
+
declare function generateStaticWebAppProject(project: FormBuilderProject, options?: ExportOptions): GeneratedFile[];
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* BusinessRuleCodeGenerator — Generates TypeScript code for business rules.
|
|
408
|
+
*
|
|
409
|
+
* Outputs:
|
|
410
|
+
* - Rule definitions as typed constants
|
|
411
|
+
* - useBusinessRules hook for runtime evaluation
|
|
412
|
+
* - FetchXML helper utilities for data source resolution
|
|
413
|
+
* - Deployment manifest for Dataverse rule table
|
|
414
|
+
*/
|
|
415
|
+
|
|
416
|
+
interface BusinessRuleCodeGenOptions {
|
|
417
|
+
/** Include inline comments explaining rule logic */
|
|
418
|
+
includeComments?: boolean;
|
|
419
|
+
/** Generate deployment manifest for Dataverse */
|
|
420
|
+
generateManifest?: boolean;
|
|
421
|
+
/** Entity logical name for the rules */
|
|
422
|
+
entityLogicalName?: string;
|
|
423
|
+
/** Publisher prefix for web resources */
|
|
424
|
+
publisherPrefix?: string;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Generate all business rule related files.
|
|
428
|
+
*/
|
|
429
|
+
declare function generateBusinessRuleCode(rules: BusinessRuleDefinition[], workflows?: WorkflowDefinition[], sharedVariables?: RuleVariable[], options?: BusinessRuleCodeGenOptions): GeneratedFile[];
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Generates a typed Dataverse data-access layer (constants + models + hooks +
|
|
433
|
+
* sample data) from the entities referenced by a project's forms and/or grid
|
|
434
|
+
* customizers.
|
|
435
|
+
*
|
|
436
|
+
* The form-builder already owns every piece of metadata needed to stop emitting
|
|
437
|
+
* `items={[]}` subgrid stubs: bound-control attribute logical names and types,
|
|
438
|
+
* option-set values with labels, lookup target lists, FetchXML data sources,
|
|
439
|
+
* and grid customizer data sources. This generator walks that metadata and
|
|
440
|
+
* produces:
|
|
441
|
+
*
|
|
442
|
+
* src/constants/{Entity}Constants.ts — attribute logical names + option set enums
|
|
443
|
+
* src/models/{Entity}.ts — BaseModel subclass + static list/retrieve/save
|
|
444
|
+
* src/hooks/use{Entities}.ts — useDataverseQuery-backed list + single record
|
|
445
|
+
* src/sampleData/{entity}.json — mock rows matching the model shape (optional)
|
|
446
|
+
* src/constants/index.ts, models/index.ts, hooks/index.ts — barrels
|
|
447
|
+
* src/lib/dataverse/* — inline runtime (BaseModel, hooks, FetchXML builder)
|
|
448
|
+
*
|
|
449
|
+
* Generated files import shared primitives from `../lib/dataverse` (inlined by
|
|
450
|
+
* `dalInlineTemplates`) so exported projects are self-contained.
|
|
451
|
+
*/
|
|
452
|
+
|
|
453
|
+
interface GenerateDataLayerOptions {
|
|
454
|
+
/** When true, `src/sampleData/{entity}.json` files are emitted. */
|
|
455
|
+
includeSampleData?: boolean;
|
|
456
|
+
}
|
|
457
|
+
interface EntityUsageAttribute {
|
|
458
|
+
logicalName: string;
|
|
459
|
+
/** Raw `attributeType` from the control binding ("SingleLineOfText", "DateTime", etc.) */
|
|
460
|
+
rawType: string;
|
|
461
|
+
/** Normalized type used by constants/models/schema. */
|
|
462
|
+
type: 'string' | 'number' | 'integer' | 'boolean' | 'date' | 'datetime' | 'lookup' | 'optionset' | 'money' | 'memo';
|
|
463
|
+
required: boolean;
|
|
464
|
+
maxLength?: number;
|
|
465
|
+
lookupTargets?: string[];
|
|
466
|
+
optionSetOptions?: Array<{
|
|
467
|
+
value: number;
|
|
468
|
+
label: string;
|
|
469
|
+
}>;
|
|
470
|
+
}
|
|
471
|
+
interface EntityUsage {
|
|
472
|
+
entityName: string;
|
|
473
|
+
entityCollectionName: string;
|
|
474
|
+
primaryIdAttribute: string;
|
|
475
|
+
primaryNameAttribute: string;
|
|
476
|
+
displayName: string;
|
|
477
|
+
attributes: Map<string, EntityUsageAttribute>;
|
|
478
|
+
/** Base FetchXML literal (from the form's data source, if any) that list hooks can parameterize. */
|
|
479
|
+
baseFetchXml?: string;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Walks all forms and returns an `EntityUsage` map keyed by entity logical name.
|
|
483
|
+
*
|
|
484
|
+
* When `gridCustomizers` is passed, subgrids whose `gridCustomizerId` resolves
|
|
485
|
+
* to a grid definition with a `dataSource` contribute the richer FetchXML +
|
|
486
|
+
* attribute list from that grid, replacing the bare `entityName`-only path.
|
|
487
|
+
*/
|
|
488
|
+
declare function collectEntityUsage(forms: FormDefinition[], gridCustomizers?: GridCustomizerDefinition[]): Map<string, EntityUsage>;
|
|
489
|
+
/**
|
|
490
|
+
* Builds an `EntityUsage` map from a single grid customizer's data source.
|
|
491
|
+
* Used by the grid-scoped DAL generator (standalone PCF / components-only).
|
|
492
|
+
*
|
|
493
|
+
* When the grid has a `nestedRelationship` pointing at a linked nested grid,
|
|
494
|
+
* the nested child entity is walked too so the generated DAL emits model +
|
|
495
|
+
* constants + hook files for both parent and child.
|
|
496
|
+
*/
|
|
497
|
+
declare function collectEntityUsageFromGrid(grid: GridCustomizerDefinition, allGrids?: GridCustomizerDefinition[]): Map<string, EntityUsage>;
|
|
498
|
+
/**
|
|
499
|
+
* Form-driven entry point — returns generated files for every entity referenced
|
|
500
|
+
* by the given forms, resolving subgrid → gridCustomizerId → dataSource links.
|
|
501
|
+
*/
|
|
502
|
+
declare function generateDataAccessLayer(forms: FormDefinition[], options?: GenerateDataLayerOptions, gridCustomizers?: GridCustomizerDefinition[]): GeneratedFile[];
|
|
503
|
+
/**
|
|
504
|
+
* Grid-driven entry point — emits the DAL file tree for a single grid
|
|
505
|
+
* customizer. Used by Standalone PCF and Components Only grid exports.
|
|
506
|
+
*/
|
|
507
|
+
declare function generateDataAccessLayerForGrid(grid: GridCustomizerDefinition, options?: GenerateDataLayerOptions, allGrids?: GridCustomizerDefinition[]): GeneratedFile[];
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Strip non-alphanumeric chars (keep spaces/underscores/dashes as split
|
|
511
|
+
* points), then PascalCase. Result is always a valid TypeScript/JavaScript
|
|
512
|
+
* identifier — leading digits get a `_` prefix because `export class 123`
|
|
513
|
+
* would otherwise be a syntax error in the generated code.
|
|
514
|
+
*/
|
|
515
|
+
declare function toPascalCase(s: string): string;
|
|
516
|
+
/** PascalCase name that always ends with exactly one "Form" suffix. */
|
|
517
|
+
declare function toFormComponentName(s: string): string;
|
|
518
|
+
/** Safe kebab-case for file/folder names. */
|
|
519
|
+
declare function toSafeFileName(s: string): string;
|
|
520
|
+
|
|
521
|
+
interface CommandEntry {
|
|
522
|
+
command: string;
|
|
523
|
+
description: string;
|
|
524
|
+
category: 'setup' | 'development' | 'build' | 'deploy';
|
|
525
|
+
}
|
|
526
|
+
declare const categoryLabels: Record<CommandEntry['category'], string>;
|
|
527
|
+
declare const CATEGORY_ORDER: CommandEntry['category'][];
|
|
528
|
+
|
|
529
|
+
declare function getCommandReference(target: ExportTarget, projectName: string, namespace?: string): CommandEntry[];
|
|
530
|
+
/** Generate a README.md from the command reference. */
|
|
531
|
+
declare function generateReadme(target: ExportTarget, projectName: string, namespace?: string): string;
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Shared helpers for deciding whether to emit the generated data-access
|
|
535
|
+
* layer and for injecting the required package dependency into generated
|
|
536
|
+
* `package.json` files.
|
|
537
|
+
*
|
|
538
|
+
* Downstream generators (WebResource, StaticWebApp, PCF) call these so the
|
|
539
|
+
* DAL integration logic lives in one place.
|
|
540
|
+
*/
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* The DAL runtime is inlined into generated projects under `src/lib/dataverse/`,
|
|
544
|
+
* so no private npm dependency is required. Only the React Query dependency
|
|
545
|
+
* (which is public) gets injected into the generated `package.json`.
|
|
546
|
+
*/
|
|
547
|
+
/**
|
|
548
|
+
* Returns the effective "generate data access layer" flag for a project/export.
|
|
549
|
+
*
|
|
550
|
+
* Priority:
|
|
551
|
+
* 1. Explicit ExportOptions.generateDataAccessLayer if present
|
|
552
|
+
* 2. Project-level saved preference under project.exportOptions.generateDataAccessLayer
|
|
553
|
+
* 3. Smart default — on when any form has at least one bound attribute
|
|
554
|
+
*/
|
|
555
|
+
declare function resolveDataAccessLayerFlag(project: FormBuilderProject, options?: ExportOptions): boolean;
|
|
556
|
+
/**
|
|
557
|
+
* Injects the public dependencies that the inlined DAL runtime requires into a
|
|
558
|
+
* generated `package.json`. Today that is just React Query — everything else
|
|
559
|
+
* in `src/lib/dataverse/` relies only on built-in Web APIs (`fetch`) and the
|
|
560
|
+
* app's existing React dependency.
|
|
561
|
+
*/
|
|
562
|
+
declare function ensureDataAccessLayerDependency(dependencies: Record<string, string>, enabled: boolean): void;
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Grid Customizer Code Generator
|
|
566
|
+
*
|
|
567
|
+
* Generates PCF Grid Customizer code from GridCustomizerDefinition.
|
|
568
|
+
* Two export modes:
|
|
569
|
+
* - 'full': Complete PCF project with webpack, package.json, etc.
|
|
570
|
+
* - 'components-only': Just the renderer files + types + barrel export
|
|
571
|
+
*
|
|
572
|
+
* Output uses Fluent UI v9 to match Microsoft's Grid Customizer docs.
|
|
573
|
+
*
|
|
574
|
+
* Note: `nestedSelectionMode` (independent vs requires-parent gating) is only
|
|
575
|
+
* honored by FormCodeGenerator's nested-grid emission today. The PA Grid Control
|
|
576
|
+
* and components-only export modes don't emit nested grids, so the setting is
|
|
577
|
+
* silently dropped here — extending it is tracked separately.
|
|
578
|
+
*/
|
|
579
|
+
|
|
580
|
+
type GridExportMode = 'full' | 'components-only' | 'pa-grid-control';
|
|
581
|
+
interface GridExportOptions {
|
|
582
|
+
mode: GridExportMode;
|
|
583
|
+
namespace?: string;
|
|
584
|
+
/**
|
|
585
|
+
* Emit the typed data-access layer (models, constants, hooks, inline runtime)
|
|
586
|
+
* alongside the renderer output. Applies to `full` and `components-only`
|
|
587
|
+
* modes; ignored for `pa-grid-control` which overlays Microsoft's grid and
|
|
588
|
+
* has no data of its own. Defaults to on when the grid has a `dataSource`
|
|
589
|
+
* and the mode supports it.
|
|
590
|
+
*/
|
|
591
|
+
includeDataAccessLayer?: boolean;
|
|
592
|
+
/** When true, also emits `src/sampleData/{entity}.json` mock rows. */
|
|
593
|
+
includeSampleData?: boolean;
|
|
594
|
+
/**
|
|
595
|
+
* Full grid customizer list from the owning project. Required for nested
|
|
596
|
+
* relationship exports — the linked nested grid's data source drives the
|
|
597
|
+
* child entity's DAL emission + the parameterized hook filter.
|
|
598
|
+
*/
|
|
599
|
+
allGrids?: GridCustomizerDefinition[];
|
|
600
|
+
/**
|
|
601
|
+
* Library used for cell-renderer + cell-editor emission in modes `full`
|
|
602
|
+
* and `components-only`. Defaults to 'fluent-v9' (the original behavior).
|
|
603
|
+
* Power Pages portals and Canvas App PCF controls need 'fluent-v8'.
|
|
604
|
+
* The `pa-grid-control` mode IGNORES this — it's a v8 platform contract
|
|
605
|
+
* and always emits v8 regardless.
|
|
606
|
+
*/
|
|
607
|
+
componentLibrary?: 'fluent-v8' | 'fluent-v9';
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Resolves the effective "include data access layer" flag for a grid export.
|
|
611
|
+
* Standalone PCF (`full`) and Components Only emit DAL when the grid has a
|
|
612
|
+
* data source. PA Grid Control never emits DAL.
|
|
613
|
+
*/
|
|
614
|
+
declare function resolveGridDalFlag(def: GridCustomizerDefinition, options: GridExportOptions): boolean;
|
|
615
|
+
declare function generateGridCustomizerProject(def: GridCustomizerDefinition, options?: GridExportOptions): GeneratedFile[];
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Mock Data Generator
|
|
619
|
+
*
|
|
620
|
+
* Shared utility for generating type-aware mock/sample data for grid previews.
|
|
621
|
+
* Used by ControlRenderer (subgrid preview) and GridCustomizer (grid preview).
|
|
622
|
+
*
|
|
623
|
+
* Extracted from ControlRenderer.tsx to avoid duplication.
|
|
624
|
+
*/
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Given a raw Dataverse row (with all its `@OData.Community.Display.V1.FormattedValue`
|
|
628
|
+
* and `_lookup_value` annotations), return a shape where each column's
|
|
629
|
+
* `fieldName` maps to the best display value. Preference order per column:
|
|
630
|
+
*
|
|
631
|
+
* 1. `fieldName@OData.Community.Display.V1.FormattedValue` — option set label,
|
|
632
|
+
* localized date, formatted money, etc.
|
|
633
|
+
* 2. `_fieldName_value@OData.Community.Display.V1.FormattedValue` — lookup
|
|
634
|
+
* display name when the fieldName is a lookup attribute.
|
|
635
|
+
* 3. `_fieldName_value` — lookup id as last resort.
|
|
636
|
+
* 4. `row[fieldName]` — the raw value (plain strings, numbers, dates).
|
|
637
|
+
*
|
|
638
|
+
* Non-mentioned columns pass through untouched so annotation-less fields stay
|
|
639
|
+
* intact. The returned row is a fresh object — the input is not mutated.
|
|
640
|
+
*/
|
|
641
|
+
declare function flattenDataverseRowForPreview(row: Record<string, unknown>, columns: GridColumnDefinition[]): Record<string, unknown>;
|
|
642
|
+
/** Base mock value pools keyed by field name or data type */
|
|
643
|
+
declare const MOCK_VALUE_POOLS: Record<string, string[]>;
|
|
644
|
+
/**
|
|
645
|
+
* Generate mock rows for a subgrid/DetailsList preview.
|
|
646
|
+
* Uses SubgridColumn[] interface from the existing form control system.
|
|
647
|
+
*/
|
|
648
|
+
declare function generateMockSubgridData(columns: SubgridColumn[], maxRows: number): Record<string, string>[];
|
|
649
|
+
/** Extended mock value pools for grid customizer data types */
|
|
650
|
+
declare const TYPED_MOCK_POOLS: Record<GridColumnDataType, unknown[]>;
|
|
651
|
+
/**
|
|
652
|
+
* Generate type-aware mock rows for grid customizer preview.
|
|
653
|
+
* Uses GridColumnDefinition[] interface with richer data types.
|
|
654
|
+
* Priority: renderer-specific pool > field-name pool > data-type pool.
|
|
655
|
+
*/
|
|
656
|
+
declare function generateMockGridData(columns: GridColumnDefinition[], rowCount?: number): Record<string, unknown>[];
|
|
657
|
+
|
|
658
|
+
export { type BusinessRuleCodeGenOptions, categoryLabels as CATEGORY_LABELS, CATEGORY_ORDER, type CommandEntry, type ComponentLibrary, type EntityUsage, type EntityUsageAttribute, type GenerateAllFormCodeOptions, type GenerateDataLayerOptions, type GenerateFormCodeOptions, type GeneratedFile, type GridExportMode, type GridExportOptions, MOCK_VALUE_POOLS, type RichEntityGenerator, TYPED_MOCK_POOLS, type V9CompatibilityResult, type V9IncompatibilityReason, type V9IncompatibleRef, type V9RequiredRef, V9RequirementError, type V9RequirementReason, type V9RequirementResult, V9_INCOMPATIBLE_CONTROL_TYPES, V9_REQUIRED_CONTROL_TYPES, collectEntityUsage, collectEntityUsageFromGrid, ensureDataAccessLayerDependency, exportProject, flattenDataverseRowForPreview, generateAllFormCode, generateBusinessRuleCode, generateDataAccessLayer, generateDataAccessLayerForGrid, generateFormCode, generateGridCustomizerProject, generateMockGridData, generateMockSubgridData, generatePcfProject, generateReadme, generateStaticWebAppProject, generateWebResourceProject, getCommandReference, isControlV9Compatible, isControlV9Required, previewExport, registerRichEntityGenerator, resolveComponentLibrary, resolveDataAccessLayerFlag, resolveGridDalFlag, scanV9Compatibility, scanV9Requirements, summarizeV9Incompatibility, summarizeV9Requirements, toFormComponentName, toPascalCase, toSafeFileName, validateExportTarget };
|