@epistola.app/valtimo-plugin 0.7.0 → 0.8.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 (24) hide show
  1. package/fesm2022/epistola.app-valtimo-plugin.mjs +660 -458
  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 +4 -1
  4. package/lib/components/download-document-configuration/download-document-configuration.component.d.ts +8 -1
  5. package/lib/components/epistola-admin-page/epistola-admin-page.component.d.ts +17 -1
  6. package/lib/components/epistola-document/epistola-document.component.d.ts +65 -0
  7. package/lib/components/{epistola-download/epistola-download.formio.d.ts → epistola-document/epistola-document.formio.d.ts} +2 -2
  8. package/lib/components/epistola-document-preview/epistola-document-preview.component.d.ts +13 -25
  9. package/lib/components/epistola-retry-form/epistola-retry-form.component.d.ts +3 -7
  10. package/lib/epistola.module.d.ts +4 -5
  11. package/lib/models/admin.d.ts +28 -0
  12. package/lib/models/config.d.ts +7 -11
  13. package/lib/services/epistola-admin.service.d.ts +14 -1
  14. package/lib/services/epistola-plugin.service.d.ts +46 -7
  15. package/lib/services/epistola-task-context.interceptor.d.ts +29 -0
  16. package/lib/services/epistola-task-context.matcher.d.ts +19 -0
  17. package/lib/services/epistola-task-context.service.d.ts +26 -0
  18. package/lib/services/index.d.ts +2 -0
  19. package/package.json +1 -1
  20. package/public_api.d.ts +2 -4
  21. package/sbom.json +1 -0
  22. package/lib/components/epistola-download/epistola-download.component.d.ts +0 -24
  23. package/lib/components/epistola-preview-button/epistola-preview-button.component.d.ts +0 -35
  24. package/lib/components/epistola-preview-button/epistola-preview-button.formio.d.ts +0 -4
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
2
  import { FunctionConfigurationComponent } from '@valtimo/plugin';
3
3
  import { FormOutput } from '@valtimo/components';
4
- import { Observable } from 'rxjs';
4
+ import { BehaviorSubject, Observable } from 'rxjs';
5
5
  import { CheckJobStatusConfig } from '../../models';
6
6
  import * as i0 from "@angular/core";
7
7
  export declare class CheckJobStatusConfigurationComponent implements FunctionConfigurationComponent, OnInit, OnDestroy {
@@ -14,6 +14,9 @@ export declare class CheckJobStatusConfigurationComponent implements FunctionCon
14
14
  private saveSubscription;
15
15
  private readonly formValue$;
16
16
  private readonly valid$;
17
+ /** Resolved synchronously before the v-form renders — see download-document-configuration for the why. */
18
+ resolvedPrefill: Partial<CheckJobStatusConfig>;
19
+ readonly prefillResolved$: BehaviorSubject<boolean>;
17
20
  safeDisabled$: Observable<boolean>;
18
21
  ngOnInit(): void;
19
22
  ngOnDestroy(): void;
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
2
  import { FunctionConfigurationComponent } from '@valtimo/plugin';
3
3
  import { FormOutput } from '@valtimo/components';
4
- import { Observable } from 'rxjs';
4
+ import { BehaviorSubject, Observable } from 'rxjs';
5
5
  import { DownloadDocumentConfig } from '../../models';
6
6
  import * as i0 from "@angular/core";
7
7
  export declare class DownloadDocumentConfigurationComponent implements FunctionConfigurationComponent, OnInit, OnDestroy {
@@ -14,6 +14,13 @@ export declare class DownloadDocumentConfigurationComponent implements FunctionC
14
14
  private saveSubscription;
15
15
  private readonly formValue$;
16
16
  private readonly valid$;
17
+ /**
18
+ * Resolved prefill — populated synchronously before the v-form renders. Avoids the
19
+ * v-input `[defaultValue]` async-binding race that otherwise drops one of the
20
+ * fields when prefill arrives after mount.
21
+ */
22
+ resolvedPrefill: Partial<DownloadDocumentConfig>;
23
+ readonly prefillResolved$: BehaviorSubject<boolean>;
17
24
  safeDisabled$: Observable<boolean>;
18
25
  ngOnInit(): void;
19
26
  ngOnDestroy(): 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 { PendingJob, PluginUsageEntry } from '../../models';
4
+ import { BpmnValidationViolation, 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,8 +26,16 @@ export declare class EpistolaAdminPageComponent implements OnInit {
26
26
  cards: ConfigurationCard[];
27
27
  selectedCard: ConfigurationCard | null;
28
28
  activeTab: 'actions' | 'pending';
29
+ overviewTab: 'configurations' | 'validations';
29
30
  loading: boolean;
30
31
  pluginVersion: string | null;
32
+ validationViolations: BpmnValidationViolation[];
33
+ reconcilingExecutionIds: Set<string>;
34
+ reconcileFeedback: {
35
+ executionId: string;
36
+ type: 'success' | 'pending' | 'error';
37
+ message: string;
38
+ } | null;
31
39
  private connectionStatuses;
32
40
  private usageEntries;
33
41
  private pendingJobs;
@@ -40,8 +48,16 @@ export declare class EpistolaAdminPageComponent implements OnInit {
40
48
  selectConfiguration(card: ConfigurationCard): void;
41
49
  backToOverview(): void;
42
50
  setActiveTab(tab: 'actions' | 'pending'): void;
51
+ setOverviewTab(tab: 'configurations' | 'validations'): void;
43
52
  refresh(): void;
44
53
  exportProcessLink(entry: PluginUsageEntry): void;
54
+ /**
55
+ * Manually reconcile a single stuck catch event. Pulls the current Epistola job
56
+ * status and re-runs message correlation if the job is in a terminal state.
57
+ * Refreshes the Pending list on success so the row drops out of the table.
58
+ */
59
+ reconcilePending(job: PendingJob): void;
60
+ isReconciling(job: PendingJob): boolean;
45
61
  private updateUrl;
46
62
  private loadData;
47
63
  private tryBuildCards;
@@ -0,0 +1,65 @@
1
+ import { ChangeDetectorRef, EventEmitter, OnDestroy, OnInit } from '@angular/core';
2
+ import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
3
+ import { FormioCustomComponent, FormIoStateService } from '@valtimo/components';
4
+ import { EpistolaPluginService, EpistolaTaskContextService } from '../../services';
5
+ import * as i0 from "@angular/core";
6
+ export type EpistolaDocumentDisplay = 'inline' | 'button' | 'both';
7
+ /**
8
+ * Unified Formio component for the after-generation Epistola PDF UX. Reads
9
+ * the PDF id and tenant id from named process variables on the caller's
10
+ * task via the {@code /documents/download} endpoint.
11
+ *
12
+ * <p>Three presentations, all backed by the same backend call:
13
+ * <ul>
14
+ * <li>{@code display="inline"} — render the PDF inline in a panel.</li>
15
+ * <li>{@code display="button"} — show a click-to-save download button only.</li>
16
+ * <li>{@code display="both"} (default) — inline panel with a download icon
17
+ * in the header.</li>
18
+ * </ul>
19
+ *
20
+ * <p>For the dry-run / what-would-be-generated UX use
21
+ * {@code epistola-document-preview} instead.
22
+ */
23
+ export declare class EpistolaDocumentComponent implements FormioCustomComponent<unknown>, OnInit, OnDestroy {
24
+ private readonly epistolaPluginService;
25
+ private readonly sanitizer;
26
+ private readonly formIoStateService;
27
+ private readonly taskContext;
28
+ private readonly cdr;
29
+ value: unknown;
30
+ valueChange: EventEmitter<unknown>;
31
+ disabled: boolean;
32
+ label: string;
33
+ /** How to present the document. `both` (default) shows an inline panel with a download icon. */
34
+ display: EpistolaDocumentDisplay;
35
+ /**
36
+ * Process-variable name holding the Epistola result. Default: `epistolaResult`.
37
+ *
38
+ * Type-tolerant on the backend: if the named variable holds a rich result object
39
+ * (`Map<String, Object>` written by `generate-document` and updated by the result
40
+ * collector), the backend digs out the `documentId` key. If it holds a plain
41
+ * String (custom flow that wrote a bare id), the backend uses it as-is.
42
+ */
43
+ documentVariable: string;
44
+ /** Process-variable name holding the Epistola tenant id. Default: `epistolaTenantId`. */
45
+ tenantIdVariable: string;
46
+ /** Filename used for the download disposition. */
47
+ filename: string;
48
+ loading: boolean;
49
+ downloading: boolean;
50
+ error: string | null;
51
+ previewUrl: SafeResourceUrl | null;
52
+ private currentBlobUrl;
53
+ private subscription?;
54
+ get designMode(): boolean;
55
+ constructor(epistolaPluginService: EpistolaPluginService, sanitizer: DomSanitizer, formIoStateService: FormIoStateService, taskContext: EpistolaTaskContextService, cdr: ChangeDetectorRef);
56
+ ngOnInit(): void;
57
+ ngOnDestroy(): void;
58
+ refresh(): void;
59
+ download(): void;
60
+ private loadInline;
61
+ private buildRequest;
62
+ private revokeBlobUrl;
63
+ 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>;
65
+ }
@@ -1,4 +1,4 @@
1
1
  import { Injector } from '@angular/core';
2
2
  import { FormioCustomComponentInfo } from '@valtimo/components';
3
- export declare const EPISTOLA_DOWNLOAD_OPTIONS: FormioCustomComponentInfo;
4
- export declare function registerEpistolaDownloadComponent(injector: Injector): void;
3
+ export declare const EPISTOLA_DOCUMENT_OPTIONS: FormioCustomComponentInfo;
4
+ export declare function registerEpistolaDocumentComponent(injector: Injector): void;
@@ -1,18 +1,14 @@
1
1
  import { ChangeDetectorRef, EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
- import { HttpClient } from '@angular/common/http';
3
2
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
4
3
  import { FormioCustomComponent, FormIoStateService } from '@valtimo/components';
5
- import { ConfigService } from '@valtimo/shared';
6
- import { PreviewSource } from '../../models';
7
- import { EpistolaPluginService } from '../../services';
4
+ import { EpistolaPluginService, EpistolaTaskContextService } from '../../services';
8
5
  import * as i0 from "@angular/core";
9
6
  export declare class EpistolaDocumentPreviewComponent implements FormioCustomComponent<Record<string, any> | null>, OnChanges, OnDestroy {
10
7
  private readonly epistolaPluginService;
11
- private readonly http;
12
8
  private readonly sanitizer;
13
- private readonly configService;
14
9
  private readonly formIoStateService;
15
10
  private readonly cdr;
11
+ private readonly taskContext;
16
12
  value: Record<string, any> | null;
17
13
  valueChange: EventEmitter<Record<string, any>>;
18
14
  disabled: boolean;
@@ -20,21 +16,20 @@ export declare class EpistolaDocumentPreviewComponent implements FormioCustomCom
20
16
  processDefinitionKey?: string;
21
17
  sourceActivityId?: string;
22
18
  overrideMapping?: Record<string, any>;
23
- sources: PreviewSource[];
24
- selectedIndex: number;
25
- discovering: boolean;
26
19
  loading: boolean;
27
20
  error: string | null;
28
21
  previewUrl: SafeResourceUrl | null;
29
22
  designMode: boolean;
30
23
  private initialized;
31
24
  private currentBlobUrl;
32
- private discoverSubscription?;
33
25
  private previewSubscription?;
34
- private readonly apiEndpoint;
35
- /** Whether the component is in configured mode (explicit process link) vs auto-discover mode */
36
- private get configuredMode();
37
- constructor(epistolaPluginService: EpistolaPluginService, http: HttpClient, sanitizer: DomSanitizer, configService: ConfigService, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef);
26
+ constructor(epistolaPluginService: EpistolaPluginService, sanitizer: DomSanitizer, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef, taskContext: EpistolaTaskContextService);
27
+ /**
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).
31
+ */
32
+ private get currentTaskId();
38
33
  get overrideMappingScopes(): string[];
39
34
  overrideMappingEntries(scope: string): {
40
35
  path: string;
@@ -42,20 +37,13 @@ export declare class EpistolaDocumentPreviewComponent implements FormioCustomCom
42
37
  }[];
43
38
  ngOnChanges(changes: SimpleChanges): void;
44
39
  ngOnDestroy(): void;
45
- onSourceChange(event: Event): void;
46
40
  refresh(): void;
47
41
  /**
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
- */
54
- private discoverSources;
55
- /**
56
- * Auto-discover mode: load preview for the selected discovered source.
42
+ * Preview using the explicitly configured process link + input overrides.
43
+ * Requires a runtime task context — the backend authorizes the request against
44
+ * the task's process instance and case document, so all three ids must match.
57
45
  */
58
- private loadDiscoveredPreview;
46
+ private loadPreview;
59
47
  private handlePreviewSuccess;
60
48
  private handlePreviewError;
61
49
  private revokeBlobUrl;
@@ -1,17 +1,14 @@
1
1
  import { ChangeDetectorRef, EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
- import { HttpClient } from '@angular/common/http';
3
2
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
4
3
  import { FormioCustomComponent, FormIoStateService } from '@valtimo/components';
5
- import { ConfigService } from '@valtimo/shared';
6
- import { EpistolaPluginService } from '../../services';
4
+ import { EpistolaPluginService, EpistolaTaskContextService } from '../../services';
7
5
  import * as i0 from "@angular/core";
8
6
  export declare class EpistolaRetryFormComponent implements FormioCustomComponent<string>, OnChanges, OnDestroy {
9
7
  private readonly epistolaPluginService;
10
8
  private readonly formIoStateService;
11
9
  private readonly cdr;
12
- private readonly http;
13
10
  private readonly sanitizer;
14
- private readonly configService;
11
+ private readonly taskContext;
15
12
  value: string;
16
13
  valueChange: EventEmitter<string>;
17
14
  disabled: boolean;
@@ -32,9 +29,8 @@ export declare class EpistolaRetryFormComponent implements FormioCustomComponent
32
29
  private currentBlobUrl;
33
30
  private resolvedSourceActivityId?;
34
31
  private processDefinitionKey?;
35
- private readonly apiEndpoint;
36
32
  formOptions: any;
37
- constructor(epistolaPluginService: EpistolaPluginService, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef, http: HttpClient, sanitizer: DomSanitizer, configService: ConfigService);
33
+ constructor(epistolaPluginService: EpistolaPluginService, formIoStateService: FormIoStateService, cdr: ChangeDetectorRef, sanitizer: DomSanitizer, taskContext: EpistolaTaskContextService);
38
34
  ngOnChanges(changes: SimpleChanges): void;
39
35
  ngOnDestroy(): void;
40
36
  togglePreview(): void;
@@ -9,14 +9,13 @@ import * as i6 from "./components/epistola-configuration/epistola-configuration.
9
9
  import * as i7 from "./components/generate-document-configuration/generate-document-configuration.component";
10
10
  import * as i8 from "./components/check-job-status-configuration/check-job-status-configuration.component";
11
11
  import * as i9 from "./components/download-document-configuration/download-document-configuration.component";
12
- import * as i10 from "./components/epistola-download/epistola-download.component";
12
+ import * as i10 from "./components/epistola-document/epistola-document.component";
13
13
  import * as i11 from "./components/epistola-retry-form/epistola-retry-form.component";
14
- import * as i12 from "./components/epistola-preview-button/epistola-preview-button.component";
15
- import * as i13 from "./components/epistola-document-preview/epistola-document-preview.component";
16
- import * as i14 from "./components/epistola-admin-page/epistola-admin-page.component";
14
+ import * as i12 from "./components/epistola-document-preview/epistola-document-preview.component";
15
+ import * as i13 from "./components/epistola-admin-page/epistola-admin-page.component";
17
16
  export declare class EpistolaPluginModule {
18
17
  static forRoot(): ModuleWithProviders<EpistolaPluginModule>;
19
18
  static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaPluginModule, never>;
20
- static ɵmod: i0.ɵɵNgModuleDeclaration<EpistolaPluginModule, never, [typeof i1.CommonModule, typeof i2.HttpClientModule, typeof i3.PluginTranslatePipeModule, typeof i4.FormModule, typeof i4.InputModule, typeof i4.SelectModule, typeof i5.EpistolaAdminRoutingModule, typeof i6.EpistolaConfigurationComponent, typeof i7.GenerateDocumentConfigurationComponent, typeof i8.CheckJobStatusConfigurationComponent, typeof i9.DownloadDocumentConfigurationComponent, typeof i10.EpistolaDownloadComponent, typeof i11.EpistolaRetryFormComponent, typeof i12.EpistolaPreviewButtonComponent, typeof i13.EpistolaDocumentPreviewComponent, typeof i14.EpistolaAdminPageComponent], [typeof i6.EpistolaConfigurationComponent, typeof i7.GenerateDocumentConfigurationComponent, typeof i8.CheckJobStatusConfigurationComponent, typeof i9.DownloadDocumentConfigurationComponent, typeof i10.EpistolaDownloadComponent, typeof i11.EpistolaRetryFormComponent, typeof i12.EpistolaPreviewButtonComponent, typeof i13.EpistolaDocumentPreviewComponent, typeof i14.EpistolaAdminPageComponent]>;
19
+ static ɵmod: i0.ɵɵNgModuleDeclaration<EpistolaPluginModule, never, [typeof i1.CommonModule, typeof i2.HttpClientModule, typeof i3.PluginTranslatePipeModule, typeof i4.FormModule, typeof i4.InputModule, typeof i4.SelectModule, typeof i5.EpistolaAdminRoutingModule, typeof i6.EpistolaConfigurationComponent, typeof i7.GenerateDocumentConfigurationComponent, typeof i8.CheckJobStatusConfigurationComponent, typeof i9.DownloadDocumentConfigurationComponent, typeof i10.EpistolaDocumentComponent, typeof i11.EpistolaRetryFormComponent, typeof i12.EpistolaDocumentPreviewComponent, typeof i13.EpistolaAdminPageComponent], [typeof i6.EpistolaConfigurationComponent, typeof i7.GenerateDocumentConfigurationComponent, typeof i8.CheckJobStatusConfigurationComponent, typeof i9.DownloadDocumentConfigurationComponent, typeof i10.EpistolaDocumentComponent, typeof i11.EpistolaRetryFormComponent, typeof i12.EpistolaDocumentPreviewComponent, typeof i13.EpistolaAdminPageComponent]>;
21
20
  static ɵinj: i0.ɵɵInjectorDeclaration<EpistolaPluginModule>;
22
21
  }
@@ -47,3 +47,31 @@ export interface PluginUsageEntry {
47
47
  configurationTitle: string;
48
48
  problems: string[];
49
49
  }
50
+ /**
51
+ * Outcome of a manual reconcile attempt for a stuck Epistola catch event.
52
+ * `correlated=true` means the Epistola job is in a terminal state and message
53
+ * correlation ran (count = how many process instances received it). `false`
54
+ * means the job is still PENDING/IN_PROGRESS — the backend returns 409.
55
+ */
56
+ export interface ReconcileResult {
57
+ executionId: string;
58
+ processInstanceId: string;
59
+ tenantId: string;
60
+ requestId: string;
61
+ epistolaStatus: string;
62
+ correlatedCount: number | null;
63
+ correlated: boolean;
64
+ }
65
+ /**
66
+ * A BPMN race-safety violation reported by the backend's deployment validator.
67
+ * `code` is one of the constants in
68
+ * `app.epistola.valtimo.web.rest.dto.BpmnValidationViolation` (kept stable so
69
+ * the UI can render specific remediation copy per code).
70
+ */
71
+ export interface BpmnValidationViolation {
72
+ processDefinitionKey: string;
73
+ processDefinitionName: string;
74
+ activityId: string;
75
+ code: string;
76
+ message: string;
77
+ }
@@ -55,19 +55,15 @@ export interface CheckJobStatusConfig {
55
55
  * Specifies which process variables to read from and write to.
56
56
  */
57
57
  export interface DownloadDocumentConfig {
58
- documentIdVariable: string;
58
+ /**
59
+ * Name of the process variable that holds the result. May be a plain
60
+ * String document id (legacy) or a `Map<String, Object>` rich result with
61
+ * a `documentId` key (canonical, written by `generate-document` and
62
+ * updated by the result collector). The action extracts the document id.
63
+ */
64
+ documentVariable: string;
59
65
  contentVariable: string;
60
66
  }
61
- /**
62
- * A previewable document source discovered from running process instances.
63
- */
64
- export interface PreviewSource {
65
- processDefinitionKey: string;
66
- activityId: string;
67
- templateId: string;
68
- templateName: string;
69
- processInstanceId: string;
70
- }
71
67
  export interface VariableSuggestions {
72
68
  doc: string[];
73
69
  pv: string[];
@@ -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 { ConnectionStatus, PendingJob, PluginUsageEntry, VersionInfo } from '../models';
4
+ import { BpmnValidationViolation, ConnectionStatus, PendingJob, PluginUsageEntry, ReconcileResult, VersionInfo } from '../models';
5
5
  import * as i0 from "@angular/core";
6
6
  /**
7
7
  * Service for Epistola plugin administrative operations.
@@ -28,6 +28,19 @@ export declare class EpistolaAdminService {
28
28
  * Get all process instances currently waiting for an Epistola document generation result.
29
29
  */
30
30
  getPendingJobs(): Observable<PendingJob[]>;
31
+ /**
32
+ * Manually reconcile a stuck Epistola catch event by querying Epistola for the
33
+ * job's current status and re-running message correlation. Returns 200 with
34
+ * `correlated=true` on success, 409 with `correlated=false` when the job is
35
+ * still in flight, or surfaces a validation error when the execution can't be
36
+ * recovered (no subscription, missing variable, unknown tenant).
37
+ */
38
+ reconcilePending(executionId: string): Observable<ReconcileResult>;
39
+ /**
40
+ * Get the latest BPMN race-safety validation violations across deployed
41
+ * process definitions. Empty list = healthy.
42
+ */
43
+ getValidationViolations(): Observable<BpmnValidationViolation[]>;
31
44
  /**
32
45
  * Export a single process link as a .process-link.json file.
33
46
  */
@@ -1,8 +1,38 @@
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, JsonataValidationResult, PreviewSource, TemplateDetails, TemplateInfo, EvaluationResult, ValidateJsonataRequest, VariableSuggestions, VariantInfo } from '../models';
4
+ import { AttributeDefinition, CatalogInfo, EnvironmentInfo, ExpressionFunctionInfo, JsonataValidationResult, TemplateDetails, TemplateInfo, EvaluationResult, ValidateJsonataRequest, VariableSuggestions, VariantInfo } from '../models';
5
5
  import * as i0 from "@angular/core";
6
+ /**
7
+ * Body of a {@link EpistolaPluginService.previewToBlob} call. Mirrors the
8
+ * backend {@code PreviewRequest} record. {@code processInstanceId},
9
+ * {@code processDefinitionKey} and {@code sourceActivityId} together identify
10
+ * the {@code generate-document} process link being previewed; {@code overrides}
11
+ * and {@code inputOverrides} let the caller substitute data before the
12
+ * JSONata mapping runs.
13
+ */
14
+ export interface PreviewBlobRequest {
15
+ taskId: string;
16
+ documentId: string;
17
+ processDefinitionKey?: string | null;
18
+ sourceActivityId?: string | null;
19
+ processInstanceId?: string | null;
20
+ inputOverrides?: Record<string, unknown> | null;
21
+ overrides?: Record<string, unknown> | null;
22
+ }
23
+ /**
24
+ * Query-string parameters for {@link EpistolaPluginService.downloadDocumentBlob}.
25
+ * The backend resolves the Epistola PDF id and tenant id from the named process
26
+ * variables on the caller's task — no raw PDF id is sent on the wire.
27
+ */
28
+ export interface DownloadDocumentRequest {
29
+ taskId: string;
30
+ caseDocumentId: string;
31
+ documentVariable: string;
32
+ tenantIdVariable: string;
33
+ filename: string;
34
+ disposition: 'attachment' | 'inline';
35
+ }
6
36
  /**
7
37
  * Service for interacting with Epistola plugin API endpoints.
8
38
  * Provides methods to fetch templates, environments, variants,
@@ -51,8 +81,10 @@ export declare class EpistolaPluginService {
51
81
  evaluateMapping(expression: string, documentId: string, processInstanceId?: string): Observable<EvaluationResult>;
52
82
  /**
53
83
  * Get a dynamically generated Formio form for retrying a failed document generation.
84
+ *
85
+ * @param taskId Operaton user task id (required — backend authorizes via OperatonTask:VIEW)
54
86
  */
55
- getRetryForm(processInstanceId: string, documentId?: string, sourceActivityId?: string): Observable<any>;
87
+ getRetryForm(taskId: string, processInstanceId: string, documentId?: string, sourceActivityId?: string): Observable<any>;
56
88
  /**
57
89
  * List all available expression functions for expr: data mapping values.
58
90
  */
@@ -63,14 +95,21 @@ export declare class EpistolaPluginService {
63
95
  */
64
96
  validateJsonata(request: ValidateJsonataRequest): Observable<JsonataValidationResult>;
65
97
  /**
66
- * Discover all previewable document sources for a given Valtimo document.
98
+ * Preview a document by dry-running the {@code generate-document} process
99
+ * link. Returns the rendered PDF as a {@link Blob}.
100
+ *
101
+ * <p>The {@code X-Skip-Interceptor: 422} header tells the global Valtimo
102
+ * error interceptor to skip its toast for validation failures so the
103
+ * caller can render an inline error message.
67
104
  */
68
- getPreviewSources(documentId: string): Observable<PreviewSource[]>;
105
+ previewToBlob(request: PreviewBlobRequest): Observable<Blob>;
69
106
  /**
70
- * Preview a document by dry-running the generate-document process link.
71
- * Returns the resolved data as a mock preview (Phase 1).
107
+ * Stream an already-generated Epistola PDF for the caller's task. The
108
+ * backend resolves the Epistola document id and tenant id from the named
109
+ * process variables on the task's process instance, so the wire never
110
+ * carries a raw PDF id.
72
111
  */
73
- previewDocument(documentId: string, processDefinitionKey: string, sourceActivityId: string, processInstanceId?: string, overrides?: Record<string, any>): Observable<any>;
112
+ downloadDocumentBlob(request: DownloadDocumentRequest): Observable<Blob>;
74
113
  static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaPluginService, never>;
75
114
  static ɵprov: i0.ɵɵInjectableDeclaration<EpistolaPluginService>;
76
115
  }
@@ -0,0 +1,29 @@
1
+ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
2
+ import { Observable } from 'rxjs';
3
+ import { EpistolaTaskContextService } from './epistola-task-context.service';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Sniffs Valtimo's task-open signal and pushes the active taskInstanceId into
7
+ * {@link EpistolaTaskContextService}. The signal is the canonical
8
+ * {@code GET /api/v2/process-link/task/{taskId}} call that
9
+ * {@code TaskDetailContentComponent.loadTaskDetails(...)} fires unconditionally
10
+ * before any task form is rendered (see @valtimo/task internals).
11
+ *
12
+ * <p>This interceptor does <b>not</b> modify the outgoing request. It only
13
+ * captures the taskId from the URL.
14
+ *
15
+ * <p>Workaround for Valtimo 13.21 not exposing taskInstanceId through any
16
+ * injectable service. Remove once upstream adds e.g.
17
+ * {@code FormIoStateService.setTaskInstanceId(...)}.
18
+ *
19
+ * <p>The actual URL-matching logic lives in
20
+ * {@link extractTaskInstanceIdFromUrl} so it can be unit-tested without an
21
+ * Angular harness.
22
+ */
23
+ export declare class EpistolaTaskContextInterceptor implements HttpInterceptor {
24
+ private readonly taskContext;
25
+ constructor(taskContext: EpistolaTaskContextService);
26
+ intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>;
27
+ static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaTaskContextInterceptor, never>;
28
+ static ɵprov: i0.ɵɵInjectableDeclaration<EpistolaTaskContextInterceptor>;
29
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Pure helpers for {@link EpistolaTaskContextInterceptor}, extracted so they
3
+ * can be unit-tested without pulling in {@code @angular/core} (which ts-jest
4
+ * cannot transform without {@code jest-preset-angular}).
5
+ */
6
+ /**
7
+ * Pattern Valtimo uses for the canonical task-open call:
8
+ * {@code GET /api/v2/process-link/task/{taskInstanceId}}.
9
+ *
10
+ * Captures the {@code taskInstanceId} (UUID v4-style 36-character hyphenated
11
+ * hex string). Anchored at the end of the URL or at a query-string delimiter
12
+ * so we don't accidentally match a longer trailing segment.
13
+ */
14
+ export declare const TASK_PROCESS_LINK_PATTERN: RegExp;
15
+ /**
16
+ * Returns the captured {@code taskInstanceId} from a Valtimo task-open
17
+ * request URL, or {@code null} if the request does not match.
18
+ */
19
+ export declare function extractTaskInstanceIdFromUrl(method: string, url: string): string | null;
@@ -0,0 +1,26 @@
1
+ import { Observable } from 'rxjs';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Holds the currently-open Operaton user task instance id so that custom
5
+ * Formio components rendered inside a Valtimo task form (preview, download,
6
+ * retry-form) can include it in backend requests for PBAC.
7
+ *
8
+ * Populated by {@link EpistolaTaskContextInterceptor}, which sniffs Valtimo's
9
+ * canonical "load process link for task" GET (`/api/v2/process-link/task/{taskId}`)
10
+ * — the request always fires when a task opens, before the form renders.
11
+ *
12
+ * <p><b>Why this exists:</b> Valtimo 13.21 does not expose the active task
13
+ * instance id through any service that custom Formio components can inject
14
+ * (`FormIoStateService` carries documentId and processInstanceId only;
15
+ * `TaskDetailContentComponent.taskInstanceId$` is private to that component
16
+ * and Formio elements live in their own injector tree). This service is a
17
+ * workaround until upstream exposes `taskInstanceId` via `FormIoStateService`.
18
+ */
19
+ export declare class EpistolaTaskContextService {
20
+ private readonly _taskInstanceId$;
21
+ readonly taskInstanceId$: Observable<string | null>;
22
+ get taskInstanceId(): string | null;
23
+ setTaskInstanceId(id: string | null): void;
24
+ static ɵfac: i0.ɵɵFactoryDeclaration<EpistolaTaskContextService, never>;
25
+ static ɵprov: i0.ɵɵInjectableDeclaration<EpistolaTaskContextService>;
26
+ }
@@ -1,3 +1,5 @@
1
1
  export * from './epistola-admin.service';
2
2
  export * from './epistola-menu.service';
3
3
  export * from './epistola-plugin.service';
4
+ export * from './epistola-task-context.service';
5
+ export * from './epistola-task-context.interceptor';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epistola.app/valtimo-plugin",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Epistola document generation plugin for Valtimo",
5
5
  "license": "EUPL-1.2",
6
6
  "repository": {
package/public_api.d.ts CHANGED
@@ -11,12 +11,10 @@ export * from './lib/components/check-job-status-configuration/check-job-status-
11
11
  export * from './lib/components/download-document-configuration/download-document-configuration.component';
12
12
  export * from './lib/components/jsonata-editor/jsonata-editor.component';
13
13
  export * from './lib/components/mapping-builder/mapping-builder.component';
14
- export * from './lib/components/epistola-download/epistola-download.component';
15
- export * from './lib/components/epistola-download/epistola-download.formio';
14
+ export * from './lib/components/epistola-document/epistola-document.component';
15
+ export * from './lib/components/epistola-document/epistola-document.formio';
16
16
  export * from './lib/components/epistola-retry-form/epistola-retry-form.component';
17
17
  export * from './lib/components/epistola-retry-form/epistola-retry-form.formio';
18
- export * from './lib/components/epistola-preview-button/epistola-preview-button.component';
19
- export * from './lib/components/epistola-preview-button/epistola-preview-button.formio';
20
18
  export * from './lib/components/epistola-document-preview/epistola-document-preview.component';
21
19
  export * from './lib/components/epistola-document-preview/epistola-document-preview.formio';
22
20
  export * from './lib/components/override-builder/override-builder.component';