@epistola.app/valtimo-plugin 0.6.0 → 0.7.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.
@@ -1 +1 @@
1
- export declare const EPISTOLA_PLUGIN_LOGO_BASE64 = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzMzNjZjYyI+PHBhdGggZD0iTTE0IDJINmMtMS4xIDAtMiAuOS0yIDJ2MTZjMCAxLjEuOSAyIDIgMmgxMmMxLjEgMCAyLS45IDItMlY4bC02LTZ6bTQgMThINlY0aDd2NWg1djExeiIvPjxwYXRoIGQ9Ik04IDEyaDh2Mkg4em0wIDRoOHYtMkg4em0wLThWNmg0djJ6Ii8+PC9zdmc+";
1
+ export declare const EPISTOLA_PLUGIN_LOGO_BASE64 = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAgMTIwIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjEyMCI+CiAgPCEtLSBTdGFjayBiYXNlIC0tPgogIDxyZWN0IHg9IjM2IiB5PSIxNiIgd2lkdGg9IjU0IiBoZWlnaHQ9IjcwIiByeD0iMyIgZmlsbD0iI2U2YzJiMCIgc3Ryb2tlPSIjNGYyZjJiIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0icm90YXRlKDUgNjMgNTEpIi8+CiAgPHJlY3QgeD0iMzIiIHk9IjIyIiB3aWR0aD0iNTQiIGhlaWdodD0iNzAiIHJ4PSIzIiBmaWxsPSIjZjBkOGM4IiBzdHJva2U9IiM0ZjJmMmIiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjI4IiB5PSIyOCIgd2lkdGg9IjU0IiBoZWlnaHQ9IjcwIiByeD0iMyIgZmlsbD0iI2Y1ZWJlMyIgc3Ryb2tlPSIjNGYyZjJiIiBzdHJva2Utd2lkdGg9IjIuNSIvPgogIDxsaW5lIHgxPSIzOCIgeTE9IjQ0IiB4Mj0iNzIiIHkyPSI0NCIgc3Ryb2tlPSIjYzRhODgyIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgogIDxsaW5lIHgxPSIzOCIgeTE9IjU0IiB4Mj0iNzIiIHkyPSI1NCIgc3Ryb2tlPSIjYzRhODgyIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgogIDxsaW5lIHgxPSIzOCIgeTE9IjY0IiB4Mj0iNTgiIHkyPSI2NCIgc3Ryb2tlPSIjYzRhODgyIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgogIDwhLS0gV2F4IHNlYWwgd2l0aCBjaGVja21hcmsgLS0+CiAgPGNpcmNsZSBjeD0iNTUiIGN5PSI4NCIgcj0iMTUiIGZpbGw9IiNiODVjM2MiIHN0cm9rZT0iIzRmMmYyYiIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPGNpcmNsZSBjeD0iNTUiIGN5PSI4NCIgcj0iMTAuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZDQ4MzZhIiBzdHJva2Utd2lkdGg9IjEiLz4KICA8cG9seWxpbmUgcG9pbnRzPSI0OSw4NCA1Myw4OSA2Miw3OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNGYyZjJiIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo=";
@@ -6,36 +6,59 @@ import { ConfigService } from '@valtimo/shared';
6
6
  import { PreviewSource } from '../../models';
7
7
  import { EpistolaPluginService } from '../../services';
8
8
  import * as i0 from "@angular/core";
9
- export declare class EpistolaDocumentPreviewComponent implements FormioCustomComponent<null>, OnChanges, OnDestroy {
9
+ export declare class EpistolaDocumentPreviewComponent implements FormioCustomComponent<Record<string, any> | null>, OnChanges, OnDestroy {
10
10
  private readonly epistolaPluginService;
11
11
  private readonly http;
12
12
  private readonly sanitizer;
13
13
  private readonly configService;
14
14
  private readonly formIoStateService;
15
15
  private readonly cdr;
16
- value: null;
17
- valueChange: EventEmitter<null>;
16
+ value: Record<string, any> | null;
17
+ valueChange: EventEmitter<Record<string, any>>;
18
18
  disabled: boolean;
19
19
  label: string;
20
+ processDefinitionKey?: string;
21
+ sourceActivityId?: string;
22
+ overrideMapping?: Record<string, any>;
20
23
  sources: PreviewSource[];
21
24
  selectedIndex: number;
22
25
  discovering: boolean;
23
26
  loading: boolean;
24
27
  error: string | null;
25
28
  previewUrl: SafeResourceUrl | null;
29
+ designMode: boolean;
26
30
  private initialized;
27
31
  private currentBlobUrl;
28
32
  private discoverSubscription?;
29
33
  private previewSubscription?;
30
34
  private readonly apiEndpoint;
35
+ /** Whether the component is in configured mode (explicit process link) vs auto-discover mode */
36
+ private get configuredMode();
31
37
  constructor(epistolaPluginService: EpistolaPluginService, http: HttpClient, sanitizer: DomSanitizer, configService: ConfigService, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef);
38
+ get overrideMappingScopes(): string[];
39
+ overrideMappingEntries(scope: string): {
40
+ path: string;
41
+ field: string;
42
+ }[];
32
43
  ngOnChanges(changes: SimpleChanges): void;
33
44
  ngOnDestroy(): void;
34
45
  onSourceChange(event: Event): void;
35
46
  refresh(): void;
47
+ /**
48
+ * Configured mode: preview using the explicitly configured process link + input overrides.
49
+ */
50
+ private loadConfiguredPreview;
51
+ /**
52
+ * Auto-discover mode: discover sources from running process instances.
53
+ */
36
54
  private discoverSources;
37
- private loadPreview;
55
+ /**
56
+ * Auto-discover mode: load preview for the selected discovered source.
57
+ */
58
+ private loadDiscoveredPreview;
59
+ private handlePreviewSuccess;
60
+ private handlePreviewError;
38
61
  private revokeBlobUrl;
39
62
  static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaDocumentPreviewComponent, never>;
40
- 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; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
63
+ 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>;
41
64
  }
@@ -0,0 +1,18 @@
1
+ import { OverrideMapping } from '../override-builder/override-builder.component';
2
+ export declare const FORM_REF_PREFIX = "form:";
3
+ /**
4
+ * Detect if a string value is a JSONata expression (vs a plain literal).
5
+ * Checks for characters that indicate JSONata operators: $, &, (, {, ?, [
6
+ */
7
+ export declare function isExpression(value: string): boolean;
8
+ /**
9
+ * Expand dot-notation keys into nested objects.
10
+ * e.g. { "beslissing.tekst": "value" } -> { beslissing: { tekst: "value" } }
11
+ */
12
+ export declare function expandDotNotation(flat: Record<string, any>): Record<string, any>;
13
+ /**
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.
17
+ */
18
+ export declare function computeInputOverrides(mapping: OverrideMapping, formData: Record<string, any>): Record<string, any>;
@@ -4,7 +4,7 @@ import { FormOutput, SelectItem } from '@valtimo/components';
4
4
  import { CaseManagementParams, ManagementContext } from '@valtimo/shared';
5
5
  import { ProcessLinkStateService } from '@valtimo/process-link';
6
6
  import { BehaviorSubject, Observable } from 'rxjs';
7
- import { AsyncResource, ExpressionFunctionInfo, GenerateDocumentConfig, TemplateField, VariableSuggestions } from '../../models';
7
+ import { AsyncResource, ExpressionFunctionInfo, GenerateDocumentConfig, JsonataFieldError, TemplateField, VariableSuggestions } from '../../models';
8
8
  import { EpistolaPluginService } from '../../services';
9
9
  import * as i0 from "@angular/core";
10
10
  export type VariantSelectionMode = 'explicit' | 'attributes';
@@ -35,11 +35,16 @@ export declare class GenerateDocumentConfigurationComponent implements FunctionC
35
35
  readonly selectedTemplateId$: BehaviorSubject<string>;
36
36
  readonly selectedVariantId$: BehaviorSubject<string>;
37
37
  variantSelectionMode: VariantSelectionMode;
38
+ variantIdExpressionMode: boolean;
39
+ variantIdExpression: string;
40
+ filenameExpressionMode: boolean;
41
+ filenameExpression: string;
38
42
  variantAttributeEntries: {
39
43
  key: string;
40
44
  value: string;
41
45
  required: boolean;
42
46
  _customKey?: boolean;
47
+ _expressionMode?: boolean;
43
48
  }[];
44
49
  availableAttributeKeys: string[];
45
50
  caseDefinitionKey: string | null;
@@ -51,6 +56,7 @@ export declare class GenerateDocumentConfigurationComponent implements FunctionC
51
56
  total: number;
52
57
  };
53
58
  prefillDataMapping: Record<string, any>;
59
+ validationErrors$: BehaviorSubject<JsonataFieldError[]>;
54
60
  private readonly destroy$;
55
61
  private saveSubscription;
56
62
  private readonly formValue$;
@@ -71,6 +77,8 @@ export declare class GenerateDocumentConfigurationComponent implements FunctionC
71
77
  addAttributeEntry(): void;
72
78
  removeAttributeEntry(index: number): void;
73
79
  onAttributeEntryChange(): void;
80
+ onVariantIdExpressionChange(): void;
81
+ onFilenameExpressionChange(): void;
74
82
  onKeySelected(entry: {
75
83
  key: string;
76
84
  value: string;
@@ -109,6 +117,17 @@ export declare class GenerateDocumentConfigurationComponent implements FunctionC
109
117
  private loadVariableSuggestions;
110
118
  private handleValid;
111
119
  private openSaveSubscription;
120
+ /**
121
+ * Build a JSONata validation request from the config and call the backend.
122
+ * Only fields that are JSONata expressions get validated:
123
+ * - dataMapping is always JSONata
124
+ * - filename / variantId only when their `fx` toggle is on
125
+ * - variant attribute values only when isExpression() reports true
126
+ * On invalid response, surface errors and abort the emit.
127
+ * If the validator endpoint itself fails (network/server), proceed with the
128
+ * emit — the validation is a quality-of-life check, not a hard gate.
129
+ */
130
+ private validateAndEmit;
112
131
  static ɵfac: i0.ɵɵFactoryDeclaration<GenerateDocumentConfigurationComponent, never>;
113
132
  static ɵcmp: i0.ɵɵComponentDeclaration<GenerateDocumentConfigurationComponent, "epistola-generate-document-configuration", never, { "save$": { "alias": "save$"; "required": false; }; "disabled$": { "alias": "disabled$"; "required": false; }; "pluginId": { "alias": "pluginId"; "required": false; }; "prefillConfiguration$": { "alias": "prefillConfiguration$"; "required": false; }; "selectedPluginConfigurationData$": { "alias": "selectedPluginConfigurationData$"; "required": false; }; "context$": { "alias": "context$"; "required": false; }; }, { "valid": "valid"; "configuration": "configuration"; }, never, never, true, never>;
114
133
  }
@@ -0,0 +1,42 @@
1
+ import { ChangeDetectorRef, EventEmitter } from '@angular/core';
2
+ import { FormioCustomComponent } from '@valtimo/components';
3
+ import * as i0 from "@angular/core";
4
+ interface OverrideRow {
5
+ scope: 'doc' | 'pv';
6
+ inputPath: string;
7
+ formFieldKey: string;
8
+ }
9
+ export interface FormFieldOption {
10
+ key: string;
11
+ label: string;
12
+ }
13
+ /**
14
+ * Override mapping format: scope → { inputPath → "form:<componentKey>" }
15
+ * The "form:" prefix identifies this as a reference to a Formio component.
16
+ */
17
+ export type OverrideMapping = Record<string, Record<string, string>>;
18
+ export declare class EpistolaOverrideBuilderComponent implements FormioCustomComponent<OverrideMapping | null> {
19
+ private readonly cdr;
20
+ value: OverrideMapping | null;
21
+ valueChange: EventEmitter<OverrideMapping>;
22
+ disabled: boolean;
23
+ label: string;
24
+ availableFields: FormFieldOption[];
25
+ rows: OverrideRow[];
26
+ advancedMode: boolean;
27
+ jsonText: string;
28
+ jsonError: string | null;
29
+ private initialized;
30
+ constructor(cdr: ChangeDetectorRef);
31
+ ngOnChanges(): void;
32
+ toggleMode(): void;
33
+ addRow(): void;
34
+ removeRow(index: number): void;
35
+ emitChange(): void;
36
+ onJsonChange(text: string): void;
37
+ private rowsToMapping;
38
+ private mappingToRows;
39
+ 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>;
41
+ }
42
+ export {};
@@ -0,0 +1,4 @@
1
+ import { Injector } from '@angular/core';
2
+ import { FormioCustomComponentInfo } from '@valtimo/components';
3
+ export declare const EPISTOLA_OVERRIDE_BUILDER_OPTIONS: FormioCustomComponentInfo;
4
+ export declare function registerEpistolaOverrideBuilderComponent(injector: Injector): void;
@@ -0,0 +1,31 @@
1
+ import { ChangeDetectorRef, EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
+ import { FormioCustomComponent } from '@valtimo/components';
3
+ import { EpistolaAdminService } from '../../services';
4
+ import { PluginUsageEntry } from '../../models';
5
+ import * as i0 from "@angular/core";
6
+ export interface ProcessLinkSelection {
7
+ processDefinitionKey: string;
8
+ sourceActivityId: string;
9
+ }
10
+ export declare class EpistolaProcessLinkSelectorComponent implements FormioCustomComponent<ProcessLinkSelection | null>, OnChanges, OnDestroy {
11
+ private readonly adminService;
12
+ private readonly cdr;
13
+ value: ProcessLinkSelection | null;
14
+ valueChange: EventEmitter<ProcessLinkSelection>;
15
+ disabled: boolean;
16
+ label: string;
17
+ filteredEntries: PluginUsageEntry[];
18
+ selectedKey: string;
19
+ loading: boolean;
20
+ error: string | null;
21
+ private initialized;
22
+ private loadSubscription?;
23
+ constructor(adminService: EpistolaAdminService, cdr: ChangeDetectorRef);
24
+ ngOnChanges(changes: SimpleChanges): void;
25
+ ngOnDestroy(): void;
26
+ onSelect(key: string): void;
27
+ entryKey(entry: PluginUsageEntry): string;
28
+ private loadEntries;
29
+ static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaProcessLinkSelectorComponent, never>;
30
+ static ɵcmp: i0.ɵɵComponentDeclaration<EpistolaProcessLinkSelectorComponent, "epistola-process-link-selector-component", never, { "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "label": { "alias": "label"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
31
+ }
@@ -0,0 +1,4 @@
1
+ import { Injector } from '@angular/core';
2
+ import { FormioCustomComponentInfo } from '@valtimo/components';
3
+ export declare const EPISTOLA_PROCESS_LINK_SELECTOR_OPTIONS: FormioCustomComponentInfo;
4
+ export declare function registerEpistolaProcessLinkSelectorComponent(injector: Injector): void;
@@ -0,0 +1,2 @@
1
+ import { CanActivateFn } from '@angular/router';
2
+ export declare const epistolaEnabledGuard: CanActivateFn;
@@ -0,0 +1,28 @@
1
+ export interface EpistolaRuntimeEnv {
2
+ epistolaEnabled?: boolean | string;
3
+ }
4
+ interface EpistolaRuntimeWindow {
5
+ env?: EpistolaRuntimeEnv;
6
+ }
7
+ declare global {
8
+ interface Window extends EpistolaRuntimeWindow {
9
+ }
10
+ }
11
+ /**
12
+ * Reads the runtime feature flag that decides whether the Epistola plugin
13
+ * surfaces (admin menu, /epistola route, plugin specification, Formio
14
+ * components) should activate in the host Valtimo app.
15
+ *
16
+ * The flag is sourced from `window['env']['epistolaEnabled']`, populated at
17
+ * container start by `envsubst` against `assets/config.template.js` (the
18
+ * standard Valtimo runtime-config pattern). Defaults to enabled — only the
19
+ * literal `false` or string `'false'` disables the plugin, matching the
20
+ * backend's `epistola.enabled` `matchIfMissing = true` semantics.
21
+ *
22
+ * Exposed as a runtime helper rather than evaluated directly in `@NgModule`
23
+ * decorator metadata because Angular's AOT compiler cannot statically resolve
24
+ * `window` accesses (NG1010). Read from runtime code such as specification
25
+ * property getters, route guards, or the environment initializer instead.
26
+ */
27
+ export declare function isEpistolaEnabled(): boolean;
28
+ export {};
@@ -26,7 +26,7 @@ export interface VariantAttributeEntry {
26
26
  *
27
27
  * Variant selection supports two modes:
28
28
  * - Explicit: set variantId directly
29
- * - By attributes: set variantAttributes with key-value pairs (values can be value resolver expressions)
29
+ * - By attributes: set variantAttributes with key-value pairs (values can be JSONata expressions)
30
30
  */
31
31
  export interface GenerateDocumentConfig {
32
32
  catalogId: string;
@@ -77,3 +77,22 @@ export interface EvaluationResult {
77
77
  result: Record<string, any> | null;
78
78
  error: string | null;
79
79
  }
80
+ /**
81
+ * Request body for the JSONata save-time validation endpoint.
82
+ * All fields are optional; null/blank values are skipped.
83
+ */
84
+ export interface ValidateJsonataRequest {
85
+ dataMapping?: string | null;
86
+ filename?: string | null;
87
+ variantId?: string | null;
88
+ variantAttributeValues?: Record<string, string> | null;
89
+ }
90
+ export interface JsonataFieldError {
91
+ field: string;
92
+ expression: string;
93
+ message: string;
94
+ }
95
+ export interface JsonataValidationResult {
96
+ valid: boolean;
97
+ errors: JsonataFieldError[];
98
+ }
@@ -1,7 +1,7 @@
1
1
  import { HttpClient } from '@angular/common/http';
2
2
  import { ConfigService } from '@valtimo/shared';
3
3
  import { Observable } from 'rxjs';
4
- import { AttributeDefinition, CatalogInfo, EnvironmentInfo, ExpressionFunctionInfo, PreviewSource, TemplateDetails, TemplateInfo, EvaluationResult, VariableSuggestions, VariantInfo } from '../models';
4
+ import { AttributeDefinition, CatalogInfo, EnvironmentInfo, ExpressionFunctionInfo, JsonataValidationResult, PreviewSource, TemplateDetails, TemplateInfo, EvaluationResult, ValidateJsonataRequest, VariableSuggestions, VariantInfo } from '../models';
5
5
  import * as i0 from "@angular/core";
6
6
  /**
7
7
  * Service for interacting with Epistola plugin API endpoints.
@@ -57,6 +57,11 @@ export declare class EpistolaPluginService {
57
57
  * List all available expression functions for expr: data mapping values.
58
58
  */
59
59
  getExpressionFunctions(): Observable<ExpressionFunctionInfo[]>;
60
+ /**
61
+ * Validate the JSONata syntax of action-config expressions before save.
62
+ * Parse-only; runtime errors (missing variables, type mismatches) are not detected.
63
+ */
64
+ validateJsonata(request: ValidateJsonataRequest): Observable<JsonataValidationResult>;
60
65
  /**
61
66
  * Discover all previewable document sources for a given Valtimo document.
62
67
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epistola.app/valtimo-plugin",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Epistola document generation plugin for Valtimo",
5
5
  "license": "EUPL-1.2",
6
6
  "repository": {
@@ -31,6 +31,8 @@
31
31
  "@valtimo/plugin": "^13.21.0",
32
32
  "@valtimo/process-link": "^13.21.0",
33
33
  "@valtimo/security": "^13.21.0",
34
- "@valtimo/shared": "^13.21.0"
34
+ "@valtimo/shared": "^13.21.0",
35
+ "jsonata": "^2.1.0",
36
+ "monaco-editor": ">=0.40.0"
35
37
  }
36
38
  }
package/public_api.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './lib/models';
2
2
  export * from './lib/services';
3
3
  export * from './lib/epistola.module';
4
4
  export * from './lib/epistola.specification';
5
+ export * from './lib/epistola-runtime-config';
5
6
  export * from './lib/epistola-admin-routing.module';
6
7
  export * from './lib/components/epistola-admin-page/epistola-admin-page.component';
7
8
  export * from './lib/components/epistola-configuration/epistola-configuration.component';
@@ -18,3 +19,7 @@ export * from './lib/components/epistola-preview-button/epistola-preview-button.
18
19
  export * from './lib/components/epistola-preview-button/epistola-preview-button.formio';
19
20
  export * from './lib/components/epistola-document-preview/epistola-document-preview.component';
20
21
  export * from './lib/components/epistola-document-preview/epistola-document-preview.formio';
22
+ export * from './lib/components/override-builder/override-builder.component';
23
+ export * from './lib/components/override-builder/override-builder.formio';
24
+ export * from './lib/components/process-link-selector/process-link-selector.component';
25
+ export * from './lib/components/process-link-selector/process-link-selector.formio';