@epistola.app/valtimo-plugin 0.9.4 → 0.11.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.
Files changed (30) hide show
  1. package/fesm2022/epistola.app-valtimo-plugin.mjs +2430 -395
  2. package/fesm2022/epistola.app-valtimo-plugin.mjs.map +1 -1
  3. package/lib/components/check-job-status-configuration/check-job-status-configuration.component.d.ts +2 -2
  4. package/lib/components/download-document-configuration/download-document-config.util.d.ts +15 -0
  5. package/lib/components/download-document-configuration/download-document-configuration.component.d.ts +12 -3
  6. package/lib/components/epistola-admin-page/epistola-admin-page.component.d.ts +28 -4
  7. package/lib/components/epistola-configuration/epistola-configuration.component.d.ts +2 -2
  8. package/lib/components/epistola-document/epistola-document.component.d.ts +11 -7
  9. package/lib/components/epistola-document-preview/epistola-document-preview.component.d.ts +57 -13
  10. package/lib/components/epistola-document-preview/preview-utils.d.ts +39 -6
  11. package/lib/components/epistola-retry-form/epistola-retry-form.component.d.ts +9 -7
  12. package/lib/components/formio-builder-utils.d.ts +14 -0
  13. package/lib/components/generate-document-configuration/generate-document-configuration.component.d.ts +4 -2
  14. package/lib/components/jsonata-editor/jsonata-editor.component.d.ts +11 -3
  15. package/lib/components/override-builder/legacy-override-converter.d.ts +23 -0
  16. package/lib/components/override-builder/override-builder.component.d.ts +52 -20
  17. package/lib/components/override-builder/override-jsonata.d.ts +25 -0
  18. package/lib/models/admin.d.ts +57 -0
  19. package/lib/models/config.d.ts +25 -1
  20. package/lib/services/epistola-admin.service.d.ts +13 -4
  21. package/lib/services/epistola-plugin.service.d.ts +16 -10
  22. package/lib/services/index.d.ts +1 -2
  23. package/lib/services/prefilled-task-id.d.ts +52 -0
  24. package/lib/utils/extract-referenced-paths.d.ts +19 -0
  25. package/lib/utils/jsonata-monaco.d.ts +2 -2
  26. package/package.json +2 -1
  27. package/sbom.json +1 -1
  28. package/lib/services/epistola-task-context.interceptor.d.ts +0 -29
  29. package/lib/services/epistola-task-context.matcher.d.ts +0 -19
  30. package/lib/services/epistola-task-context.service.d.ts +0 -26
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
- import { FunctionConfigurationComponent } from '@valtimo/plugin';
2
+ import { FunctionConfigurationComponent, FunctionConfigurationData } from '@valtimo/plugin';
3
3
  import { FormOutput } from '@valtimo/components';
4
4
  import { BehaviorSubject, Observable } from 'rxjs';
5
5
  import { CheckJobStatusConfig } from '../../models';
@@ -10,7 +10,7 @@ export declare class CheckJobStatusConfigurationComponent implements FunctionCon
10
10
  pluginId: string;
11
11
  prefillConfiguration$: Observable<CheckJobStatusConfig>;
12
12
  valid: EventEmitter<boolean>;
13
- configuration: EventEmitter<CheckJobStatusConfig>;
13
+ configuration: EventEmitter<FunctionConfigurationData>;
14
14
  private saveSubscription;
15
15
  private readonly formValue$;
16
16
  private readonly valid$;
@@ -0,0 +1,15 @@
1
+ import { DownloadDocumentConfig } from '../../models';
2
+ /**
3
+ * Pure helpers for the download-document configurator, extracted so they can be unit-tested
4
+ * without the Angular component (mirrors the process-link-selector util pattern). See
5
+ * `docs/adr/0001-download-document-content-storage.md`.
6
+ */
7
+ export type StorageTarget = 'TEMPORARY_RESOURCE' | 'PROCESS_VARIABLE';
8
+ export declare const DEFAULT_STORAGE_TARGET: StorageTarget;
9
+ /** Normalize a (possibly undefined) storageTarget to a concrete target, applying the default. */
10
+ export declare function resolveStorageTarget(target?: string): StorageTarget;
11
+ /**
12
+ * A config is valid when the input variable and the output variable that matches the chosen
13
+ * storage target are both set.
14
+ */
15
+ export declare function isDownloadDocumentConfigValid(config: Partial<DownloadDocumentConfig> | null | undefined): boolean;
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
- import { FunctionConfigurationComponent } from '@valtimo/plugin';
3
- import { FormOutput } from '@valtimo/components';
2
+ import { FunctionConfigurationComponent, FunctionConfigurationData } from '@valtimo/plugin';
3
+ import { FormOutput, SelectItem } from '@valtimo/components';
4
4
  import { BehaviorSubject, Observable } from 'rxjs';
5
5
  import { DownloadDocumentConfig } from '../../models';
6
6
  import * as i0 from "@angular/core";
@@ -10,7 +10,7 @@ export declare class DownloadDocumentConfigurationComponent implements FunctionC
10
10
  pluginId: string;
11
11
  prefillConfiguration$: Observable<DownloadDocumentConfig>;
12
12
  valid: EventEmitter<boolean>;
13
- configuration: EventEmitter<DownloadDocumentConfig>;
13
+ configuration: EventEmitter<FunctionConfigurationData>;
14
14
  private saveSubscription;
15
15
  private readonly formValue$;
16
16
  private readonly valid$;
@@ -22,6 +22,15 @@ export declare class DownloadDocumentConfigurationComponent implements FunctionC
22
22
  resolvedPrefill: Partial<DownloadDocumentConfig>;
23
23
  readonly prefillResolved$: BehaviorSubject<boolean>;
24
24
  safeDisabled$: Observable<boolean>;
25
+ /**
26
+ * Static option set for the storage target. Values match the backend
27
+ * {@code DocumentStorageTarget} enum constants; labels are explained further via the
28
+ * translated field title/tooltip.
29
+ */
30
+ readonly storageTargetOptions: SelectItem[];
31
+ readonly defaultStorageTarget: import("./download-document-config.util").StorageTarget;
32
+ /** Drives which output-variable field is shown (resource id vs inline content). */
33
+ readonly selectedTarget$: BehaviorSubject<string>;
25
34
  ngOnInit(): void;
26
35
  ngOnDestroy(): void;
27
36
  formValueChange(formOutput: FormOutput): void;
@@ -1,7 +1,7 @@
1
1
  import { OnInit } from '@angular/core';
2
2
  import { ActivatedRoute, Router } from '@angular/router';
3
3
  import { EpistolaAdminService } from '../../services/epistola-admin.service';
4
- import { BpmnValidationViolation, ChangelogRelease, ClasspathCatalog, PendingJob, PluginUsageEntry } from '../../models';
4
+ import { BpmnValidationReport, BpmnValidationViolation, ChangelogRelease, ClasspathCatalog, FormCarrierIssue, LegacyOverrideForm, PendingJob, PluginUsageEntry } from '../../models';
5
5
  import * as i0 from "@angular/core";
6
6
  /**
7
7
  * Combined view model for a single plugin configuration card.
@@ -26,12 +26,12 @@ export declare class EpistolaAdminPageComponent implements OnInit {
26
26
  cards: ConfigurationCard[];
27
27
  selectedCard: ConfigurationCard | null;
28
28
  activeTab: 'actions' | 'pending' | 'catalogs';
29
- overviewTab: 'configurations' | 'validations' | 'changelog';
29
+ overviewTab: 'configurations' | 'validations' | 'changelog' | 'forms';
30
30
  loading: boolean;
31
31
  pluginVersion: string | null;
32
32
  changelog: ChangelogRelease[] | null;
33
33
  changelogLoading: boolean;
34
- validationViolations: BpmnValidationViolation[];
34
+ validationReport: BpmnValidationReport | null;
35
35
  reconcilingExecutionIds: Set<string>;
36
36
  reconcileFeedback: {
37
37
  executionId: string;
@@ -46,6 +46,17 @@ export declare class EpistolaAdminPageComponent implements OnInit {
46
46
  type: 'success' | 'error';
47
47
  message: string;
48
48
  } | null;
49
+ formIssues: FormCarrierIssue[] | null;
50
+ formIssuesLoading: boolean;
51
+ repairingFormIds: Set<string>;
52
+ repairingAll: boolean;
53
+ formFeedback: {
54
+ formId: string;
55
+ type: 'success' | 'error';
56
+ message: string;
57
+ } | null;
58
+ legacyOverrideForms: LegacyOverrideForm[] | null;
59
+ legacyOverrideLoading: boolean;
49
60
  private connectionStatuses;
50
61
  private usageEntries;
51
62
  private pendingJobs;
@@ -54,11 +65,24 @@ export declare class EpistolaAdminPageComponent implements OnInit {
54
65
  private pendingLoaded;
55
66
  private deepLinkConfigId;
56
67
  constructor(adminService: EpistolaAdminService, route: ActivatedRoute, router: Router);
68
+ /** Violations from the latest report (empty when healthy or not yet loaded). */
69
+ get validationViolations(): BpmnValidationViolation[];
70
+ /** Scan cadence in whole minutes, for the "refreshes every N min" note. */
71
+ get refreshIntervalMinutes(): number;
72
+ /** Combined "forms needing attention" count for the tab badge (carrier + legacy override). */
73
+ get formsAttentionCount(): number;
74
+ /** Whether the forms tab has loaded at least one of its two scans. */
75
+ get formsScanLoaded(): boolean;
57
76
  ngOnInit(): void;
58
77
  selectConfiguration(card: ConfigurationCard): void;
59
78
  backToOverview(): void;
60
79
  setActiveTab(tab: 'actions' | 'pending' | 'catalogs'): void;
61
- setOverviewTab(tab: 'configurations' | 'validations' | 'changelog'): void;
80
+ setOverviewTab(tab: 'configurations' | 'validations' | 'changelog' | 'forms'): void;
81
+ private loadLegacyOverrideForms;
82
+ private loadFormIssues;
83
+ isRepairingForm(issue: FormCarrierIssue): boolean;
84
+ repairForm(issue: FormCarrierIssue): void;
85
+ repairAllForms(): void;
62
86
  private loadChangelog;
63
87
  refresh(): void;
64
88
  exportProcessLink(entry: PluginUsageEntry): void;
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
- import { PluginConfigurationComponent } from '@valtimo/plugin';
2
+ import { PluginConfigurationComponent, PluginConfigurationData } from '@valtimo/plugin';
3
3
  import { FormOutput } from '@valtimo/components';
4
4
  import { Observable } from 'rxjs';
5
5
  import { EpistolaPluginConfig } from '../../models';
@@ -10,7 +10,7 @@ export declare class EpistolaConfigurationComponent implements PluginConfigurati
10
10
  pluginId: string;
11
11
  prefillConfiguration$: Observable<EpistolaPluginConfig>;
12
12
  valid: EventEmitter<boolean>;
13
- configuration: EventEmitter<EpistolaPluginConfig>;
13
+ configuration: EventEmitter<PluginConfigurationData>;
14
14
  /** Epistola slug pattern: lowercase alphanumeric with hyphens, no leading/trailing hyphens. */
15
15
  private static readonly SLUG_PATTERN;
16
16
  private saveSubscription;
@@ -1,7 +1,7 @@
1
- import { ChangeDetectorRef, EventEmitter, OnDestroy, OnInit } from '@angular/core';
1
+ import { ChangeDetectorRef, EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
2
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
3
3
  import { FormioCustomComponent, FormIoStateService } from '@valtimo/components';
4
- import { EpistolaPluginService, EpistolaTaskContextService } from '../../services';
4
+ import { EpistolaPluginService } from '../../services';
5
5
  import * as i0 from "@angular/core";
6
6
  export type EpistolaDocumentDisplay = 'inline' | 'button' | 'both';
7
7
  /**
@@ -20,11 +20,10 @@ export type EpistolaDocumentDisplay = 'inline' | 'button' | 'both';
20
20
  * <p>For the dry-run / what-would-be-generated UX use
21
21
  * {@code epistola-document-preview} instead.
22
22
  */
23
- export declare class EpistolaDocumentComponent implements FormioCustomComponent<unknown>, OnInit, OnDestroy {
23
+ export declare class EpistolaDocumentComponent implements FormioCustomComponent<unknown>, OnChanges, OnDestroy {
24
24
  private readonly epistolaPluginService;
25
25
  private readonly sanitizer;
26
26
  private readonly formIoStateService;
27
- private readonly taskContext;
28
27
  private readonly cdr;
29
28
  value: unknown;
30
29
  valueChange: EventEmitter<unknown>;
@@ -45,6 +44,11 @@ export declare class EpistolaDocumentComponent implements FormioCustomComponent<
45
44
  tenantIdVariable: string;
46
45
  /** Filename used for the download disposition. */
47
46
  filename: string;
47
+ /**
48
+ * Task id forwarded by the Formio wrapper from the server-prefilled form
49
+ * ({@code epistola:taskId} value resolver), populated in every Valtimo task-open flow.
50
+ */
51
+ taskInstanceId?: string | null;
48
52
  loading: boolean;
49
53
  downloading: boolean;
50
54
  error: string | null;
@@ -52,8 +56,8 @@ export declare class EpistolaDocumentComponent implements FormioCustomComponent<
52
56
  private currentBlobUrl;
53
57
  private subscription?;
54
58
  get designMode(): boolean;
55
- constructor(epistolaPluginService: EpistolaPluginService, sanitizer: DomSanitizer, formIoStateService: FormIoStateService, taskContext: EpistolaTaskContextService, cdr: ChangeDetectorRef);
56
- ngOnInit(): void;
59
+ constructor(epistolaPluginService: EpistolaPluginService, sanitizer: DomSanitizer, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef);
60
+ ngOnChanges(changes: SimpleChanges): void;
57
61
  ngOnDestroy(): void;
58
62
  refresh(): void;
59
63
  download(): void;
@@ -61,5 +65,5 @@ export declare class EpistolaDocumentComponent implements FormioCustomComponent<
61
65
  private buildRequest;
62
66
  private revokeBlobUrl;
63
67
  static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaDocumentComponent, never>;
64
- static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaDocumentComponent, "epistola-document-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "display": { "alias": "display"; "required": false; }; "documentVariable": { "alias": "documentVariable"; "required": false; }; "tenantIdVariable": { "alias": "tenantIdVariable"; "required": false; }; "filename": { "alias": "filename"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
68
+ static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaDocumentComponent, "epistola-document-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "display": { "alias": "display"; "required": false; }; "documentVariable": { "alias": "documentVariable"; "required": false; }; "tenantIdVariable": { "alias": "tenantIdVariable"; "required": false; }; "filename": { "alias": "filename"; "required": false; }; "taskInstanceId": { "alias": "taskInstanceId"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
65
69
  }
@@ -1,21 +1,55 @@
1
1
  import { ChangeDetectorRef, EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
2
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
3
3
  import { FormioCustomComponent, FormIoStateService } from '@valtimo/components';
4
- import { EpistolaPluginService, EpistolaTaskContextService } from '../../services';
4
+ import { EpistolaPluginService } from '../../services';
5
5
  import * as i0 from "@angular/core";
6
6
  export declare class EpistolaDocumentPreviewComponent implements FormioCustomComponent<Record<string, any> | null>, OnChanges, OnDestroy {
7
7
  private readonly epistolaPluginService;
8
8
  private readonly sanitizer;
9
9
  private readonly formIoStateService;
10
10
  private readonly cdr;
11
- private readonly taskContext;
12
11
  value: Record<string, any> | null;
13
12
  valueChange: EventEmitter<Record<string, any>>;
14
13
  disabled: boolean;
15
14
  label: string;
16
15
  processDefinitionKey?: string;
17
16
  sourceActivityId?: string;
18
- overrideMapping?: Record<string, any>;
17
+ /**
18
+ * The override mapping: a JSONata expression string over `$form`, or — for
19
+ * not-yet-re-saved forms — the legacy `form:`-ref object.
20
+ */
21
+ overrideMapping?: string | Record<string, any>;
22
+ /**
23
+ * Task id forwarded by the Formio wrapper from the server-prefilled form
24
+ * ({@code epistola:taskId} value resolver), populated in every Valtimo task-open flow.
25
+ */
26
+ taskInstanceId?: string | null;
27
+ /**
28
+ * The computed input overrides (`{ doc, pv }`) the preview renders with, pushed
29
+ * by the Formio wrapper. Kept separate from the Formio `value`: Valtimo's custom
30
+ * component bridge only mirrors `value` to the DOM (never to Formio's data
31
+ * model), so Formio resets it to `emptyValue` on every redraw — which would
32
+ * cancel the preview. This dedicated input is never touched by Formio.
33
+ */
34
+ inputOverrides?: Record<string, any> | null;
35
+ /**
36
+ * Forces the Formio wrapper to recompute the input overrides from the live form
37
+ * data. Set by the wrapper for override-driven previews; lets the Refresh button
38
+ * work before the first change (e.g. on initial load with pre-filled fields).
39
+ */
40
+ requestOverrides?: () => void;
41
+ /**
42
+ * Current auto-refresh state, forwarded by the wrapper (seeded from the builder's
43
+ * `autoRefresh` option, default on). Seeds the header toggle's initial state.
44
+ */
45
+ autoRefresh?: boolean;
46
+ /**
47
+ * Tells the wrapper to enable/disable auto-refresh (recompute on change/blur).
48
+ * Set by the wrapper for override-driven previews; called by the header toggle.
49
+ */
50
+ setAutoRefresh?: (enabled: boolean) => void;
51
+ /** Runtime state of the header auto-refresh toggle. */
52
+ autoRefreshEnabled: boolean;
19
53
  loading: boolean;
20
54
  error: string | null;
21
55
  previewUrl: SafeResourceUrl | null;
@@ -23,21 +57,31 @@ export declare class EpistolaDocumentPreviewComponent implements FormioCustomCom
23
57
  private initialized;
24
58
  private currentBlobUrl;
25
59
  private previewSubscription?;
26
- constructor(epistolaPluginService: EpistolaPluginService, sanitizer: DomSanitizer, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef, taskContext: EpistolaTaskContextService);
60
+ constructor(epistolaPluginService: EpistolaPluginService, sanitizer: DomSanitizer, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef);
27
61
  /**
28
- * Resolve the active task id from {@link EpistolaTaskContextService}, populated
29
- * by {@code EpistolaTaskContextInterceptor} on the canonical Valtimo task-open
30
- * call. Returns null when used outside a task context (e.g. Formio builder).
62
+ * The active task id, forwarded by the Formio wrapper from the server-prefilled
63
+ * form ({@code epistola:taskId} value resolver). Null outside a task context
64
+ * (e.g. Formio builder), in which case the component fails closed.
31
65
  */
32
66
  private get currentTaskId();
33
- get overrideMappingScopes(): string[];
34
- overrideMappingEntries(scope: string): {
35
- path: string;
36
- field: string;
37
- }[];
67
+ /**
68
+ * The override mapping as a JSONata expression for the design-mode summary.
69
+ * Legacy `form:`-ref objects are converted on the fly for display.
70
+ */
71
+ get overrideExpression(): string;
38
72
  ngOnChanges(changes: SimpleChanges): void;
39
73
  ngOnDestroy(): void;
40
74
  refresh(): void;
75
+ /** Toggle auto-refresh for this session; flipping it on triggers an immediate refresh. */
76
+ onToggleAutoRefresh(event: Event): void;
77
+ /**
78
+ * Load the preview only when there is enough data for it. Override-driven
79
+ * previews (those with an override mapping) wait until the mapped form data
80
+ * has been computed; until then they show a placeholder rather than firing a
81
+ * request that Epistola would reject with a 400 for missing required fields.
82
+ */
83
+ private triggerPreview;
84
+ private showWaitingForInput;
41
85
  /**
42
86
  * Preview using the explicitly configured process link + input overrides.
43
87
  * Requires a runtime task context — the backend authorizes the request against
@@ -48,5 +92,5 @@ export declare class EpistolaDocumentPreviewComponent implements FormioCustomCom
48
92
  private handlePreviewError;
49
93
  private revokeBlobUrl;
50
94
  static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaDocumentPreviewComponent, never>;
51
- static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaDocumentPreviewComponent, "epistola-document-preview-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "processDefinitionKey": { "alias": "processDefinitionKey"; "required": false; }; "sourceActivityId": { "alias": "sourceActivityId"; "required": false; }; "overrideMapping": { "alias": "overrideMapping"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
95
+ static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaDocumentPreviewComponent, "epistola-document-preview-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "processDefinitionKey": { "alias": "processDefinitionKey"; "required": false; }; "sourceActivityId": { "alias": "sourceActivityId"; "required": false; }; "overrideMapping": { "alias": "overrideMapping"; "required": false; }; "taskInstanceId": { "alias": "taskInstanceId"; "required": false; }; "inputOverrides": { "alias": "inputOverrides"; "required": false; }; "requestOverrides": { "alias": "requestOverrides"; "required": false; }; "autoRefresh": { "alias": "autoRefresh"; "required": false; }; "setAutoRefresh": { "alias": "setAutoRefresh"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
52
96
  }
@@ -1,5 +1,10 @@
1
- import { OverrideMapping } from '../override-builder/override-builder.component';
2
- export declare const FORM_REF_PREFIX = "form:";
1
+ /** Re-exported for backward compatibility with existing imports/tests. */
2
+ export { FORM_REF_PREFIX } from '../override-builder/legacy-override-converter';
3
+ /**
4
+ * An override mapping is either the new JSONata expression **string** (over
5
+ * `$form`) or — for not-yet-re-saved forms — the legacy `form:`-ref **object**.
6
+ */
7
+ export type OverrideMappingValue = string | Record<string, any> | null | undefined;
3
8
  /**
4
9
  * Detect if a string value is a JSONata expression (vs a plain literal).
5
10
  * Checks for characters that indicate JSONata operators: $, &, (, {, ?, [
@@ -11,8 +16,36 @@ export declare function isExpression(value: string): boolean;
11
16
  */
12
17
  export declare function expandDotNotation(flat: Record<string, any>): Record<string, any>;
13
18
  /**
14
- * Given an override mapping (scope -> { inputPath -> "form:<componentKey>" })
15
- * and form data, produce the inputOverrides object for the backend.
16
- * The "form:" prefix identifies form field references; the remainder is the Formio component key.
19
+ * A preview is "override-driven" when it has a non-empty override mapping: its
20
+ * input data comes from the form via the mapping, so it must wait for that data
21
+ * before it can render. Previews without a mapping load straight from the base
22
+ * doc/case data.
23
+ */
24
+ export declare function isOverrideDriven(mapping?: OverrideMappingValue): boolean;
25
+ /**
26
+ * Whether the computed input overrides carry any usable data yet.
27
+ */
28
+ export declare function hasUsableOverrides(overrides?: Record<string, any> | null): boolean;
29
+ /**
30
+ * Decide whether a preview request should fire given the configured override
31
+ * mapping and the currently computed overrides.
32
+ *
33
+ * - Override-driven previews only load once the mapped form data is present;
34
+ * before that they show a "complete the form" placeholder and fire nothing
35
+ * (avoids a doomed request that Epistola rejects with a 400 for missing
36
+ * required fields).
37
+ * - Previews without a mapping always load (base data is the whole input).
38
+ */
39
+ export declare function shouldLoadPreview(mapping?: OverrideMappingValue, overrides?: Record<string, any> | null): boolean;
40
+ /**
41
+ * Given an override mapping and the live form data, produce the inputOverrides
42
+ * object (`{ doc, pv }`) the backend overlays onto the real document / process
43
+ * variables before the data mapping runs.
44
+ *
45
+ * The mapping is a JSONata expression over `$form`; legacy `form:`-ref objects
46
+ * are converted on the fly via {@link legacyOverrideToJsonata}. Evaluation is
47
+ * asynchronous because `jsonata().evaluate()` returns a Promise. Only `doc` and
48
+ * `pv` scopes (with at least one resolved field) are kept — matching what the
49
+ * backend consumes.
17
50
  */
18
- export declare function computeInputOverrides(mapping: OverrideMapping, formData: Record<string, any>): Record<string, any>;
51
+ export declare function computeInputOverrides(mapping: OverrideMappingValue, formData: Record<string, any>): Promise<Record<string, any>>;
@@ -1,19 +1,22 @@
1
1
  import { ChangeDetectorRef, EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
2
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
3
- import { FormioCustomComponent, FormIoStateService } from '@valtimo/components';
4
- import { EpistolaPluginService, EpistolaTaskContextService } from '../../services';
3
+ import { FormioCustomComponent } from '@valtimo/components';
4
+ import { EpistolaPluginService } from '../../services';
5
5
  import * as i0 from "@angular/core";
6
6
  export declare class EpistolaRetryFormComponent implements FormioCustomComponent<string>, OnChanges, OnDestroy {
7
7
  private readonly epistolaPluginService;
8
- private readonly formIoStateService;
9
8
  private readonly cdr;
10
9
  private readonly sanitizer;
11
- private readonly taskContext;
12
10
  value: string;
13
11
  valueChange: EventEmitter<string>;
14
12
  disabled: boolean;
15
13
  label: string;
16
14
  sourceActivityId?: string;
15
+ /**
16
+ * Task id forwarded by the Formio wrapper from the server-prefilled form
17
+ * ({@code epistola:taskId} value resolver), populated in every Valtimo task-open flow.
18
+ */
19
+ taskInstanceId?: string | null;
17
20
  formDefinition: any;
18
21
  submission: any;
19
22
  loading: boolean;
@@ -28,9 +31,8 @@ export declare class EpistolaRetryFormComponent implements FormioCustomComponent
28
31
  private previewSubject;
29
32
  private currentBlobUrl;
30
33
  private resolvedSourceActivityId?;
31
- private processDefinitionKey?;
32
34
  formOptions: any;
33
- constructor(epistolaPluginService: EpistolaPluginService, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef, sanitizer: DomSanitizer, taskContext: EpistolaTaskContextService);
35
+ constructor(epistolaPluginService: EpistolaPluginService, cdr: ChangeDetectorRef, sanitizer: DomSanitizer);
34
36
  ngOnChanges(changes: SimpleChanges): void;
35
37
  ngOnDestroy(): void;
36
38
  togglePreview(): void;
@@ -38,5 +40,5 @@ export declare class EpistolaRetryFormComponent implements FormioCustomComponent
38
40
  private loadPreview;
39
41
  private loadForm;
40
42
  static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaRetryFormComponent, never>;
41
- static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaRetryFormComponent, "epistola-retry-form-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "sourceActivityId": { "alias": "sourceActivityId"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
43
+ static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaRetryFormComponent, "epistola-retry-form-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "sourceActivityId": { "alias": "sourceActivityId"; "required": false; }; "taskInstanceId": { "alias": "taskInstanceId"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
42
44
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Hides a registered custom Formio component from the builder's component palette,
3
+ * while keeping it fully usable inside other components' `editForm`s and at runtime.
4
+ *
5
+ * Formio's `WebformBuilder` only adds a component to the palette when
6
+ * `component.builderInfo && component.builderInfo.schema` is truthy. Overriding the
7
+ * registered class's static `builderInfo` getter to `false` therefore removes it from
8
+ * the palette. Runtime instantiation and editForm usage don't consult `builderInfo`,
9
+ * so they are unaffected.
10
+ *
11
+ * Call this AFTER the component is registered (and after any `setComponent` re-registration),
12
+ * so it targets the final class in `Formio.Components.components[type]`.
13
+ */
14
+ export declare function hideFormioComponentFromBuilder(type: string): void;
@@ -1,5 +1,5 @@
1
1
  import { ChangeDetectorRef, EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
- import { FunctionConfigurationComponent, PluginConfigurationData } from '@valtimo/plugin';
2
+ import { FunctionConfigurationComponent, FunctionConfigurationData, PluginConfigurationData } from '@valtimo/plugin';
3
3
  import { FormOutput, SelectedValue, SelectItem } from '@valtimo/components';
4
4
  import { CaseManagementParams, ManagementContext } from '@valtimo/shared';
5
5
  import { ProcessLinkStateService } from '@valtimo/process-link';
@@ -19,7 +19,7 @@ export declare class GenerateDocumentConfigurationComponent implements FunctionC
19
19
  selectedPluginConfigurationData$?: Observable<PluginConfigurationData>;
20
20
  context$?: Observable<[ManagementContext, CaseManagementParams]>;
21
21
  valid: EventEmitter<boolean>;
22
- configuration: EventEmitter<GenerateDocumentConfig>;
22
+ configuration: EventEmitter<FunctionConfigurationData>;
23
23
  catalogs$: BehaviorSubject<AsyncResource<SelectItem[]>>;
24
24
  templates$: BehaviorSubject<AsyncResource<SelectItem[]>>;
25
25
  variants$: BehaviorSubject<AsyncResource<SelectItem[]>>;
@@ -68,6 +68,8 @@ export declare class GenerateDocumentConfigurationComponent implements FunctionC
68
68
  processVariables: string[];
69
69
  expressionFunctions: ExpressionFunctionInfo[];
70
70
  variableSuggestions: VariableSuggestions | null;
71
+ /** Context variables for the JSONata editor's autocomplete ($doc/$pv/$case). */
72
+ editorContextVariables: Record<string, string[]>;
71
73
  prefillDataMapping: Record<string, any>;
72
74
  validationErrors$: BehaviorSubject<JsonataFieldError[]>;
73
75
  private readonly destroy$;
@@ -1,11 +1,19 @@
1
1
  import { EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
- import { ExpressionFunctionInfo, VariableSuggestions } from '../../models';
2
+ import { ExpressionFunctionInfo } from '../../models';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class JsonataEditorComponent implements OnChanges, OnDestroy {
5
5
  expression: string;
6
6
  disabled: boolean;
7
- suggestions: VariableSuggestions | null;
7
+ /**
8
+ * Context variables in scope, keyed by name (without `$`), each mapping to its
9
+ * field/path suggestions — e.g. `{ doc: [...], pv: [...] }` for the data
10
+ * mapping, `{ form: [...] }` for the override builder. Drives both the
11
+ * `$`-variable list and `$<name>.` field completion.
12
+ */
13
+ contextVariables: Record<string, string[]>;
8
14
  functions: ExpressionFunctionInfo[];
15
+ /** Footer hint listing the context variables in scope. */
16
+ variablesHint: string;
9
17
  expressionChange: EventEmitter<string>;
10
18
  validChange: EventEmitter<boolean>;
11
19
  editorModel: {
@@ -25,5 +33,5 @@ export declare class JsonataEditorComponent implements OnChanges, OnDestroy {
25
33
  private tryRegisterLanguage;
26
34
  private validateExpression;
27
35
  static ɵfac: i0.ɵɵFactoryDeclaration<JsonataEditorComponent, never>;
28
- static ɵcmp: i0.ɵɵComponentDeclaration<JsonataEditorComponent, "epistola-jsonata-editor", never, { "expression": { "alias": "expression"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "suggestions": { "alias": "suggestions"; "required": false; }; "functions": { "alias": "functions"; "required": false; }; }, { "expressionChange": "expressionChange"; "validChange": "validChange"; }, never, never, true, never>;
36
+ static ɵcmp: i0.ɵɵComponentDeclaration<JsonataEditorComponent, "epistola-jsonata-editor", never, { "expression": { "alias": "expression"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "contextVariables": { "alias": "contextVariables"; "required": false; }; "functions": { "alias": "functions"; "required": false; }; "variablesHint": { "alias": "variablesHint"; "required": false; }; }, { "expressionChange": "expressionChange"; "validChange": "validChange"; }, never, never, true, never>;
29
37
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Prefix that marked a form-field reference in the legacy override-mapping
3
+ * object format (e.g. `"form:motivationField"`).
4
+ */
5
+ export declare const FORM_REF_PREFIX = "form:";
6
+ /**
7
+ * Whether a stored override-mapping value is in the legacy **object** format
8
+ * (`{ scope: { inputPath: "form:fieldKey" } }`) rather than the new JSONata
9
+ * **string** format.
10
+ */
11
+ export declare function isLegacyOverrideMapping(value: unknown): value is Record<string, any>;
12
+ /**
13
+ * TEMPORARY migration shim.
14
+ *
15
+ * Converts a legacy override-mapping object into the equivalent JSONata string
16
+ * over `$form`. Funnelling every legacy value through this one function keeps
17
+ * the rest of the codebase JSONata-only.
18
+ *
19
+ * @deprecated Remove once all deployed forms have been re-saved in the JSONata
20
+ * format. The admin page's "legacy override format" warning tracks which
21
+ * forms still need migrating.
22
+ */
23
+ export declare function legacyOverrideToJsonata(mapping: Record<string, any>): string;
@@ -1,42 +1,74 @@
1
- import { ChangeDetectorRef, EventEmitter } from '@angular/core';
1
+ import { ChangeDetectorRef, EventEmitter, OnDestroy, SimpleChanges } from '@angular/core';
2
2
  import { FormioCustomComponent } from '@valtimo/components';
3
+ import { OverrideRow } from './override-jsonata';
4
+ import { EpistolaPluginService } from '../../services';
5
+ import { ReferencedPath } from '../../utils/extract-referenced-paths';
3
6
  import * as i0 from "@angular/core";
4
- interface OverrideRow {
5
- scope: 'doc' | 'pv';
6
- inputPath: string;
7
- formFieldKey: string;
8
- }
9
7
  export interface FormFieldOption {
10
8
  key: string;
11
9
  label: string;
12
10
  }
13
11
  /**
14
- * Override mapping format: scope { inputPath → "form:<componentKey>" }
15
- * The "form:" prefix identifies this as a reference to a Formio component.
12
+ * Override mapping value: a JSONata expression (over `$form`) that produces the
13
+ * `{ doc, pv }` overlay applied during preview. Legacy form definitions may
14
+ * still carry the old `{ scope: { inputPath: "form:key" } }` object; it is
15
+ * converted to JSONata on load (see {@link legacyOverrideToJsonata}).
16
16
  */
17
17
  export type OverrideMapping = Record<string, Record<string, string>>;
18
- export declare class EpistolaOverrideBuilderComponent implements FormioCustomComponent<OverrideMapping | null> {
18
+ export declare class EpistolaOverrideBuilderComponent implements FormioCustomComponent<string | OverrideMapping | null>, OnDestroy {
19
19
  private readonly cdr;
20
- value: OverrideMapping | null;
21
- valueChange: EventEmitter<OverrideMapping>;
20
+ private readonly pluginService;
21
+ value: string | OverrideMapping | null;
22
+ valueChange: EventEmitter<string | OverrideMapping>;
22
23
  disabled: boolean;
23
24
  label: string;
24
25
  availableFields: FormFieldOption[];
26
+ /**
27
+ * Identify the selected generate-document process link, forwarded from the
28
+ * preview component's editForm. Used to fetch the link's data mapping and
29
+ * surface which `$doc`/`$pv` paths it consumes — purely informational guidance.
30
+ */
31
+ processDefinitionKey: string;
32
+ sourceActivityId: string;
25
33
  rows: OverrideRow[];
26
34
  advancedMode: boolean;
27
- jsonText: string;
28
- jsonError: string | null;
35
+ /** True when the current expression can't be represented by the simple table. */
36
+ simpleUnavailable: boolean;
37
+ expression: string;
38
+ /** `$doc`/`$pv`/`$case` paths the selected template's data mapping references. */
39
+ referencedPaths: ReferencedPath[];
40
+ readonly exampleExpression = "{ \"doc\": { \"naam\": $form.voornaam & ' ' & $form.achternaam } }";
29
41
  private initialized;
30
- constructor(cdr: ChangeDetectorRef);
31
- ngOnChanges(): void;
42
+ private readonly destroy$;
43
+ /** Link last fetched, so we refetch only when the selected process link changes. */
44
+ private lastFetchedLinkKey;
45
+ constructor(cdr: ChangeDetectorRef, pluginService: EpistolaPluginService);
46
+ get formFieldKeys(): string[];
47
+ get hasReferencedPaths(): boolean;
48
+ /** Referenced paths for a scope, excluding whole-scope refs (empty path) that aren't completions. */
49
+ referencedPathsForScope(scope: ReferencedPath['scope']): string[];
50
+ /** Autocomplete context for the advanced editor: form fields plus the mapping's referenced paths. */
51
+ get editorContextVariables(): Record<string, string[]>;
52
+ /** Render a referenced path as a `$scope.path` reference (or `$scope` for a whole-scope ref). */
53
+ formatReferencedPath(ref: ReferencedPath): string;
54
+ ngOnChanges(_changes?: SimpleChanges): void;
55
+ ngOnDestroy(): void;
56
+ /**
57
+ * Fetch the selected process link's data mapping and extract the `$doc`/`$pv`/`$case`
58
+ * paths it references, so the author sees what this template consumes. Refetches only
59
+ * when the selected link changes; clears when no link is selected. Best-effort and
60
+ * non-blocking — a failed fetch simply shows no suggestions.
61
+ */
62
+ private refreshReferencedPaths;
32
63
  toggleMode(): void;
33
64
  addRow(): void;
34
65
  removeRow(index: number): void;
66
+ /** Simple-table change: serialize rows back to a JSONata expression. */
35
67
  emitChange(): void;
36
- onJsonChange(text: string): void;
37
- private rowsToMapping;
38
- private mappingToRows;
68
+ /** Advanced-editor change. */
69
+ onExpressionChange(expr: string): void;
70
+ private loadFromExpression;
71
+ private emit;
39
72
  static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaOverrideBuilderComponent, never>;
40
- static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaOverrideBuilderComponent, "epistola-override-builder-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "availableFields": { "alias": "availableFields"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
73
+ static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaOverrideBuilderComponent, "epistola-override-builder-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; "availableFields": { "alias": "availableFields"; "required": false; }; "processDefinitionKey": { "alias": "processDefinitionKey"; "required": false; }; "sourceActivityId": { "alias": "sourceActivityId"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
41
74
  }
42
- export {};