hierarchical-approval 4.0.2 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -6
- package/README.md +1 -1
- package/dist/{ApprovalEngine-XgGBQLC_.d.cts → ApprovalEngine-D0_F5OPZ.d.cts} +35 -10
- package/dist/{ApprovalEngine-Dqe-rC6K.d.ts → ApprovalEngine-D4bXQrKD.d.ts} +35 -10
- package/dist/Clock-D8Qp39q_.d.cts +8 -0
- package/dist/Clock-D8Qp39q_.d.ts +8 -0
- package/dist/{IAuditAdapter-Dt8qjkQL.d.cts → IAuditAdapter-D9WE0t7A.d.cts} +2 -1
- package/dist/{IAuditAdapter-DkbyFFjb.d.ts → IAuditAdapter-FI_RF_XU.d.ts} +2 -1
- package/dist/{IAuthorizationPolicy-YJ_08Mof.d.cts → IAuthorizationPolicy-BKKw7jGN.d.ts} +6 -1
- package/dist/{IAuthorizationPolicy-eo6glbpE.d.ts → IAuthorizationPolicy-DDmjeYV-.d.cts} +6 -1
- package/dist/{IMetricsAdapter-DWq8IFaf.d.cts → IMetricsAdapter-WROxYSXd.d.cts} +1 -0
- package/dist/{IMetricsAdapter-DWq8IFaf.d.ts → IMetricsAdapter-WROxYSXd.d.ts} +1 -0
- package/dist/{INotificationAdapter-BTO9FSKy.d.ts → INotificationAdapter-CLROEfRd.d.ts} +26 -1
- package/dist/{INotificationAdapter-XbD69gss.d.cts → INotificationAdapter-J0wSPLIC.d.cts} +26 -1
- package/dist/{IOperationMiddleware-CX7lo4lp.d.ts → IOperationMiddleware-B32a2dwP.d.ts} +15 -2
- package/dist/{IOperationMiddleware-BBLk8MIz.d.cts → IOperationMiddleware-UUKqztxM.d.cts} +15 -2
- package/dist/{ISchedulerAdapter-DKv_QjVN.d.cts → ISchedulerAdapter-CLMdBA-5.d.cts} +1 -0
- package/dist/{ISchedulerAdapter-DKv_QjVN.d.ts → ISchedulerAdapter-CLMdBA-5.d.ts} +1 -0
- package/dist/{IStorageAdapter-CdXMggPK.d.ts → IStorageAdapter-DSKJ1onF.d.ts} +14 -1
- package/dist/{IStorageAdapter-Cjw5zDwQ.d.cts → IStorageAdapter-Dhrc4ES6.d.cts} +14 -1
- package/dist/{Logger-BplhlU7l.d.cts → Logger-hqFbBCtB.d.cts} +7 -0
- package/dist/{Logger-BplhlU7l.d.ts → Logger-hqFbBCtB.d.ts} +7 -0
- package/dist/adapters/MemoryAdapter.cjs.map +1 -1
- package/dist/adapters/MemoryAdapter.d.cts +2 -2
- package/dist/adapters/MemoryAdapter.d.ts +2 -2
- package/dist/adapters/MemoryAdapter.js.map +1 -1
- package/dist/adapters/PostgresAdapter.cjs.map +1 -1
- package/dist/adapters/PostgresAdapter.d.cts +2 -2
- package/dist/adapters/PostgresAdapter.d.ts +2 -2
- package/dist/adapters/PostgresAdapter.js.map +1 -1
- package/dist/index.cjs +51 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.ts +14 -14
- package/dist/index.js +51 -8
- package/dist/index.js.map +1 -1
- package/dist/{instance-uUQh5XW3.d.cts → instance-CUZcHWK2.d.cts} +28 -0
- package/dist/{instance-uUQh5XW3.d.ts → instance-CUZcHWK2.d.ts} +28 -0
- package/dist/nestjs.cjs +61 -7
- package/dist/nestjs.cjs.map +1 -1
- package/dist/nestjs.d.cts +22 -11
- package/dist/nestjs.d.ts +22 -11
- package/dist/nestjs.js +61 -7
- package/dist/nestjs.js.map +1 -1
- package/dist/plugins/audit.cjs.map +1 -1
- package/dist/plugins/audit.d.cts +3 -3
- package/dist/plugins/audit.d.ts +3 -3
- package/dist/plugins/audit.js.map +1 -1
- package/dist/plugins/metrics.cjs.map +1 -1
- package/dist/plugins/metrics.d.cts +2 -2
- package/dist/plugins/metrics.d.ts +2 -2
- package/dist/plugins/metrics.js.map +1 -1
- package/dist/plugins/notify.cjs.map +1 -1
- package/dist/plugins/notify.d.cts +4 -4
- package/dist/plugins/notify.d.ts +4 -4
- package/dist/plugins/notify.js.map +1 -1
- package/dist/plugins/resilience.cjs.map +1 -1
- package/dist/plugins/resilience.d.cts +5 -5
- package/dist/plugins/resilience.d.ts +5 -5
- package/dist/plugins/resilience.js.map +1 -1
- package/dist/plugins/scheduler.cjs.map +1 -1
- package/dist/plugins/scheduler.d.cts +3 -3
- package/dist/plugins/scheduler.d.ts +3 -3
- package/dist/plugins/scheduler.js.map +1 -1
- package/dist/plugins/tracing.cjs.map +1 -1
- package/dist/plugins/tracing.d.cts +4 -2
- package/dist/plugins/tracing.d.ts +4 -2
- package/dist/plugins/tracing.js.map +1 -1
- package/dist/plugins/webhook.cjs.map +1 -1
- package/dist/plugins/webhook.d.cts +4 -4
- package/dist/plugins/webhook.d.ts +4 -4
- package/dist/plugins/webhook.js.map +1 -1
- package/dist/testing.cjs +50 -7
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +11 -11
- package/dist/testing.d.ts +11 -11
- package/dist/testing.js +50 -7
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
- package/dist/Clock-3FnOczFJ.d.cts +0 -6
- package/dist/Clock-3FnOczFJ.d.ts +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
## 4.0.2 - 2026-09-20
|
|
2
|
-
|
|
3
|
-
- fix(notify): name the offending value in DigestNotificationAdapter's error
|
|
4
|
-
- fix(engine): stop leaking a listener when on() double-registers it
|
|
5
|
-
- fix(webhook): give the real-timer sleep test slack for CI jitter
|
|
6
|
-
|
|
7
1
|
# Changelog
|
|
8
2
|
|
|
9
3
|
All notable changes to `hierarchical-approval` are documented here. This project
|
|
@@ -11,6 +5,23 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
11
5
|
|
|
12
6
|
## [Unreleased]
|
|
13
7
|
|
|
8
|
+
## [4.0.4] - 2026-09-24
|
|
9
|
+
|
|
10
|
+
## [4.0.3] - 2026-09-22
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- `assertStatus`'s `INVALID_STATUS` error now names the instance that failed
|
|
15
|
+
the check, instead of a message that gave no clue which instance it was.
|
|
16
|
+
- `businessHoursCalendar`'s "no working day found" error now names the start
|
|
17
|
+
date that triggered it, instead of a message that gave no clue which call
|
|
18
|
+
misconfigured the calendar.
|
|
19
|
+
- `assertApproverOnLevel`'s forbidden-approver error now names the level,
|
|
20
|
+
matching every sibling guard in `StateMachine.ts`, instead of a bare level
|
|
21
|
+
number with no human-readable name.
|
|
22
|
+
|
|
23
|
+
## [4.0.2] - 2026-09-20
|
|
24
|
+
|
|
14
25
|
### Fixed
|
|
15
26
|
|
|
16
27
|
- `EventBus` (and therefore `engine.on()`/`off()`) no longer leaks a listener
|
|
@@ -20,6 +31,9 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
20
31
|
attached.
|
|
21
32
|
- `DigestNotificationAdapter`'s `intervalMs` validation error now names the
|
|
22
33
|
offending value, instead of a message that gave no clue which value failed.
|
|
34
|
+
- The default-sleep regression test for `WebhookNotificationAdapter` no longer
|
|
35
|
+
flakes under CI's timer coalescing, which could report elapsed time a
|
|
36
|
+
millisecond or two short of the asserted floor.
|
|
23
37
|
|
|
24
38
|
## [4.0.1] - 2026-09-14
|
|
25
39
|
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Multi-tenant · audit-ready · fully pluggable · zero runtime dependencies you
|
|
|
11
11
|
[](https://www.typescriptlang.org/)
|
|
12
12
|
[](https://bundlephobia.com/package/hierarchical-approval)
|
|
13
13
|
[](./LICENSE)
|
|
14
|
-
[](./tests)
|
|
15
15
|
|
|
16
16
|
[**Documentation**](https://hierarchical-approval.matthewswong.com) ·
|
|
17
17
|
[**npm**](https://www.npmjs.com/package/hierarchical-approval) ·
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-
|
|
2
|
-
import { m as ConditionExpression, r as ResolverFn, g as ApprovalTemplateConfig, A as ApprovalTemplate, k as AuditContext, a as ApprovalInstance, C as Comment, e as ApprovalMode, f as ApprovalStatus, L as LevelStatus, b as AuditEntry } from './instance-
|
|
3
|
-
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-
|
|
1
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-Dhrc4ES6.cjs';
|
|
2
|
+
import { m as ConditionExpression, r as ResolverFn, g as ApprovalTemplateConfig, A as ApprovalTemplate, k as AuditContext, a as ApprovalInstance, C as Comment, e as ApprovalMode, f as ApprovalStatus, L as LevelStatus, b as AuditEntry } from './instance-CUZcHWK2.cjs';
|
|
3
|
+
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-J0wSPLIC.cjs';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { L as Logger } from './Logger-
|
|
6
|
-
import { C as Clock } from './Clock-
|
|
7
|
-
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-
|
|
8
|
-
import { I as IAuditAdapter } from './IAuditAdapter-
|
|
9
|
-
import { I as IMetricsAdapter } from './IMetricsAdapter-
|
|
10
|
-
import { I as ISchedulerAdapter } from './ISchedulerAdapter-
|
|
11
|
-
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-
|
|
5
|
+
import { L as Logger } from './Logger-hqFbBCtB.cjs';
|
|
6
|
+
import { C as Clock } from './Clock-D8Qp39q_.cjs';
|
|
7
|
+
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-UUKqztxM.cjs';
|
|
8
|
+
import { I as IAuditAdapter } from './IAuditAdapter-D9WE0t7A.cjs';
|
|
9
|
+
import { I as IMetricsAdapter } from './IMetricsAdapter-WROxYSXd.cjs';
|
|
10
|
+
import { I as ISchedulerAdapter } from './ISchedulerAdapter-CLMdBA-5.cjs';
|
|
11
|
+
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-DDmjeYV-.cjs';
|
|
12
12
|
|
|
13
13
|
declare const SubmitOptionsSchema: z.ZodObject<{
|
|
14
14
|
templateName: z.ZodString;
|
|
@@ -201,11 +201,16 @@ interface BusinessHoursCalendarOptions extends WeekendCalendarOptions {
|
|
|
201
201
|
*/
|
|
202
202
|
declare function businessHoursCalendar(options?: BusinessHoursCalendarOptions): Required<Pick<BusinessCalendar, 'addBusinessDays' | 'addBusinessHours'>>;
|
|
203
203
|
|
|
204
|
+
/** Entity kind an id is generated for: instance, template, attachment, or comment. */
|
|
204
205
|
type IdGeneratorPrefix = 'inst' | 'tpl' | 'att' | 'cmt';
|
|
206
|
+
/** Produces a unique id for the given entity kind. */
|
|
205
207
|
type IdGeneratorFn = (prefix: IdGeneratorPrefix) => string;
|
|
208
|
+
/** {@link IdGeneratorFn} used when no custom generator is configured. */
|
|
206
209
|
declare const defaultIdGenerator: IdGeneratorFn;
|
|
207
210
|
|
|
211
|
+
/** Backs `{ type: 'role' }` approvers, so a level can name an org role instead of a fixed user id. */
|
|
208
212
|
interface OrgProvider {
|
|
213
|
+
/** Required: resolve users holding a named role. */
|
|
209
214
|
getUsersByRole(role: string, tenantId?: string): Promise<string[]> | string[];
|
|
210
215
|
/** Optional: resolve users by department name. */
|
|
211
216
|
getUsersByDepartment?(dept: string, tenantId?: string): Promise<string[]> | string[];
|
|
@@ -233,6 +238,11 @@ interface OutOfOfficeProvider {
|
|
|
233
238
|
*/
|
|
234
239
|
getDelegateFor(userId: string, at: Date): Promise<string | null | undefined> | string | null | undefined;
|
|
235
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Resolves a custom approver type's config to concrete user ids. Registered
|
|
243
|
+
* via {@link ApprovalEngine.registerApproverType} to back a level whose
|
|
244
|
+
* approver config carries an app-defined `type`.
|
|
245
|
+
*/
|
|
236
246
|
type ApproverResolverFn = (config: Record<string, unknown>, ctx: {
|
|
237
247
|
submittedBy: string;
|
|
238
248
|
data: Record<string, unknown>;
|
|
@@ -279,6 +289,7 @@ declare function validateConditionExpression(expression: ConditionExpression, pa
|
|
|
279
289
|
message: string;
|
|
280
290
|
}>;
|
|
281
291
|
|
|
292
|
+
/** Outcome of {@link ApprovalEngine.validateTemplate}. */
|
|
282
293
|
interface ValidationResult {
|
|
283
294
|
valid: boolean;
|
|
284
295
|
errors: Array<{
|
|
@@ -286,13 +297,16 @@ interface ValidationResult {
|
|
|
286
297
|
message: string;
|
|
287
298
|
}>;
|
|
288
299
|
}
|
|
300
|
+
/** Outcome of {@link ApprovalEngine.canApprove}. */
|
|
289
301
|
interface CanApproveResult {
|
|
290
302
|
eligible: boolean;
|
|
291
303
|
reason?: 'not_an_approver' | 'already_acted' | 'self_approval' | 'wrong_status' | 'delegated_away';
|
|
292
304
|
}
|
|
305
|
+
/** One entry in a {@link ApprovalEngine.preview} result, resolved against the given data without persisting anything. */
|
|
293
306
|
interface PreviewChainLevel {
|
|
294
307
|
level: number;
|
|
295
308
|
name: string;
|
|
309
|
+
/** Approver ids resolved as of preview time; dynamic/role approvers may resolve differently at submit time. */
|
|
296
310
|
resolvedApprovers: string[];
|
|
297
311
|
mode: ApprovalMode;
|
|
298
312
|
}
|
|
@@ -386,12 +400,16 @@ interface SimulationResult {
|
|
|
386
400
|
/** True when the script ran out before the approval finished. */
|
|
387
401
|
incomplete: boolean;
|
|
388
402
|
}
|
|
403
|
+
/** Outcome of a {@link ApprovalEngine.bulkApprove}/{@link ApprovalEngine.bulkReject} sweep. */
|
|
389
404
|
interface BulkResult {
|
|
405
|
+
/** Instances that reached the requested decision. */
|
|
390
406
|
succeeded: ApprovalInstance[];
|
|
407
|
+
/** Instances that could not be decided, with the reason. */
|
|
391
408
|
failed: Array<{
|
|
392
409
|
instanceId: string;
|
|
393
410
|
error: ApprovalError;
|
|
394
411
|
}>;
|
|
412
|
+
/** Number of instance ids passed in, equal to `succeeded.length + failed.length`. */
|
|
395
413
|
total: number;
|
|
396
414
|
}
|
|
397
415
|
/** Outcome of a {@link ApprovalEngine.transferApprovals} sweep. */
|
|
@@ -537,6 +555,7 @@ interface CycleTimeStats {
|
|
|
537
555
|
/** Largest observed time-to-decision. `0` when {@link count} is `0`. */
|
|
538
556
|
maxMs: number;
|
|
539
557
|
}
|
|
558
|
+
/** Outcome of {@link ApprovalEngine.healthCheck}. */
|
|
540
559
|
interface HealthResult {
|
|
541
560
|
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
542
561
|
adapter: 'connected' | 'error';
|
|
@@ -545,12 +564,18 @@ interface HealthResult {
|
|
|
545
564
|
escalationRunning: boolean;
|
|
546
565
|
lastTickAt?: Date;
|
|
547
566
|
}
|
|
567
|
+
/** Controls how {@link ApprovalEngine}'s optimistic-lock retry backs off on write conflicts. Defaults to 3 attempts with a 50ms base delay. */
|
|
548
568
|
interface RetryPolicy {
|
|
569
|
+
/** Number of attempts before giving up and rethrowing the conflict. */
|
|
549
570
|
maxAttempts: number;
|
|
571
|
+
/** Linear backoff unit; attempt N waits roughly `baseDelayMs * N` before retrying. */
|
|
550
572
|
baseDelayMs: number;
|
|
573
|
+
/** Upper bound on the computed delay. Defaults to unbounded. */
|
|
551
574
|
maxDelayMs?: number;
|
|
575
|
+
/** Adds up to one `baseDelayMs` of random jitter to each delay. Defaults to `true`. */
|
|
552
576
|
jitter?: boolean;
|
|
553
577
|
}
|
|
578
|
+
/** Derives the idempotency key used to dedupe a {@link ApprovalEngine.submit} call from its tenant and document identity. */
|
|
554
579
|
type IdempotencyKeyFn = (tenantId: string, documentType: string, documentId: string, templateName: string, data: Record<string, unknown>) => string;
|
|
555
580
|
interface ApprovalEngineOptions {
|
|
556
581
|
adapter: IStorageAdapter;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-
|
|
2
|
-
import { m as ConditionExpression, r as ResolverFn, g as ApprovalTemplateConfig, A as ApprovalTemplate, k as AuditContext, a as ApprovalInstance, C as Comment, e as ApprovalMode, f as ApprovalStatus, L as LevelStatus, b as AuditEntry } from './instance-
|
|
3
|
-
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-
|
|
1
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-DSKJ1onF.js';
|
|
2
|
+
import { m as ConditionExpression, r as ResolverFn, g as ApprovalTemplateConfig, A as ApprovalTemplate, k as AuditContext, a as ApprovalInstance, C as Comment, e as ApprovalMode, f as ApprovalStatus, L as LevelStatus, b as AuditEntry } from './instance-CUZcHWK2.js';
|
|
3
|
+
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-CLROEfRd.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { L as Logger } from './Logger-
|
|
6
|
-
import { C as Clock } from './Clock-
|
|
7
|
-
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-
|
|
8
|
-
import { I as IAuditAdapter } from './IAuditAdapter-
|
|
9
|
-
import { I as IMetricsAdapter } from './IMetricsAdapter-
|
|
10
|
-
import { I as ISchedulerAdapter } from './ISchedulerAdapter-
|
|
11
|
-
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-
|
|
5
|
+
import { L as Logger } from './Logger-hqFbBCtB.js';
|
|
6
|
+
import { C as Clock } from './Clock-D8Qp39q_.js';
|
|
7
|
+
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-B32a2dwP.js';
|
|
8
|
+
import { I as IAuditAdapter } from './IAuditAdapter-FI_RF_XU.js';
|
|
9
|
+
import { I as IMetricsAdapter } from './IMetricsAdapter-WROxYSXd.js';
|
|
10
|
+
import { I as ISchedulerAdapter } from './ISchedulerAdapter-CLMdBA-5.js';
|
|
11
|
+
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-BKKw7jGN.js';
|
|
12
12
|
|
|
13
13
|
declare const SubmitOptionsSchema: z.ZodObject<{
|
|
14
14
|
templateName: z.ZodString;
|
|
@@ -201,11 +201,16 @@ interface BusinessHoursCalendarOptions extends WeekendCalendarOptions {
|
|
|
201
201
|
*/
|
|
202
202
|
declare function businessHoursCalendar(options?: BusinessHoursCalendarOptions): Required<Pick<BusinessCalendar, 'addBusinessDays' | 'addBusinessHours'>>;
|
|
203
203
|
|
|
204
|
+
/** Entity kind an id is generated for: instance, template, attachment, or comment. */
|
|
204
205
|
type IdGeneratorPrefix = 'inst' | 'tpl' | 'att' | 'cmt';
|
|
206
|
+
/** Produces a unique id for the given entity kind. */
|
|
205
207
|
type IdGeneratorFn = (prefix: IdGeneratorPrefix) => string;
|
|
208
|
+
/** {@link IdGeneratorFn} used when no custom generator is configured. */
|
|
206
209
|
declare const defaultIdGenerator: IdGeneratorFn;
|
|
207
210
|
|
|
211
|
+
/** Backs `{ type: 'role' }` approvers, so a level can name an org role instead of a fixed user id. */
|
|
208
212
|
interface OrgProvider {
|
|
213
|
+
/** Required: resolve users holding a named role. */
|
|
209
214
|
getUsersByRole(role: string, tenantId?: string): Promise<string[]> | string[];
|
|
210
215
|
/** Optional: resolve users by department name. */
|
|
211
216
|
getUsersByDepartment?(dept: string, tenantId?: string): Promise<string[]> | string[];
|
|
@@ -233,6 +238,11 @@ interface OutOfOfficeProvider {
|
|
|
233
238
|
*/
|
|
234
239
|
getDelegateFor(userId: string, at: Date): Promise<string | null | undefined> | string | null | undefined;
|
|
235
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Resolves a custom approver type's config to concrete user ids. Registered
|
|
243
|
+
* via {@link ApprovalEngine.registerApproverType} to back a level whose
|
|
244
|
+
* approver config carries an app-defined `type`.
|
|
245
|
+
*/
|
|
236
246
|
type ApproverResolverFn = (config: Record<string, unknown>, ctx: {
|
|
237
247
|
submittedBy: string;
|
|
238
248
|
data: Record<string, unknown>;
|
|
@@ -279,6 +289,7 @@ declare function validateConditionExpression(expression: ConditionExpression, pa
|
|
|
279
289
|
message: string;
|
|
280
290
|
}>;
|
|
281
291
|
|
|
292
|
+
/** Outcome of {@link ApprovalEngine.validateTemplate}. */
|
|
282
293
|
interface ValidationResult {
|
|
283
294
|
valid: boolean;
|
|
284
295
|
errors: Array<{
|
|
@@ -286,13 +297,16 @@ interface ValidationResult {
|
|
|
286
297
|
message: string;
|
|
287
298
|
}>;
|
|
288
299
|
}
|
|
300
|
+
/** Outcome of {@link ApprovalEngine.canApprove}. */
|
|
289
301
|
interface CanApproveResult {
|
|
290
302
|
eligible: boolean;
|
|
291
303
|
reason?: 'not_an_approver' | 'already_acted' | 'self_approval' | 'wrong_status' | 'delegated_away';
|
|
292
304
|
}
|
|
305
|
+
/** One entry in a {@link ApprovalEngine.preview} result, resolved against the given data without persisting anything. */
|
|
293
306
|
interface PreviewChainLevel {
|
|
294
307
|
level: number;
|
|
295
308
|
name: string;
|
|
309
|
+
/** Approver ids resolved as of preview time; dynamic/role approvers may resolve differently at submit time. */
|
|
296
310
|
resolvedApprovers: string[];
|
|
297
311
|
mode: ApprovalMode;
|
|
298
312
|
}
|
|
@@ -386,12 +400,16 @@ interface SimulationResult {
|
|
|
386
400
|
/** True when the script ran out before the approval finished. */
|
|
387
401
|
incomplete: boolean;
|
|
388
402
|
}
|
|
403
|
+
/** Outcome of a {@link ApprovalEngine.bulkApprove}/{@link ApprovalEngine.bulkReject} sweep. */
|
|
389
404
|
interface BulkResult {
|
|
405
|
+
/** Instances that reached the requested decision. */
|
|
390
406
|
succeeded: ApprovalInstance[];
|
|
407
|
+
/** Instances that could not be decided, with the reason. */
|
|
391
408
|
failed: Array<{
|
|
392
409
|
instanceId: string;
|
|
393
410
|
error: ApprovalError;
|
|
394
411
|
}>;
|
|
412
|
+
/** Number of instance ids passed in, equal to `succeeded.length + failed.length`. */
|
|
395
413
|
total: number;
|
|
396
414
|
}
|
|
397
415
|
/** Outcome of a {@link ApprovalEngine.transferApprovals} sweep. */
|
|
@@ -537,6 +555,7 @@ interface CycleTimeStats {
|
|
|
537
555
|
/** Largest observed time-to-decision. `0` when {@link count} is `0`. */
|
|
538
556
|
maxMs: number;
|
|
539
557
|
}
|
|
558
|
+
/** Outcome of {@link ApprovalEngine.healthCheck}. */
|
|
540
559
|
interface HealthResult {
|
|
541
560
|
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
542
561
|
adapter: 'connected' | 'error';
|
|
@@ -545,12 +564,18 @@ interface HealthResult {
|
|
|
545
564
|
escalationRunning: boolean;
|
|
546
565
|
lastTickAt?: Date;
|
|
547
566
|
}
|
|
567
|
+
/** Controls how {@link ApprovalEngine}'s optimistic-lock retry backs off on write conflicts. Defaults to 3 attempts with a 50ms base delay. */
|
|
548
568
|
interface RetryPolicy {
|
|
569
|
+
/** Number of attempts before giving up and rethrowing the conflict. */
|
|
549
570
|
maxAttempts: number;
|
|
571
|
+
/** Linear backoff unit; attempt N waits roughly `baseDelayMs * N` before retrying. */
|
|
550
572
|
baseDelayMs: number;
|
|
573
|
+
/** Upper bound on the computed delay. Defaults to unbounded. */
|
|
551
574
|
maxDelayMs?: number;
|
|
575
|
+
/** Adds up to one `baseDelayMs` of random jitter to each delay. Defaults to `true`. */
|
|
552
576
|
jitter?: boolean;
|
|
553
577
|
}
|
|
578
|
+
/** Derives the idempotency key used to dedupe a {@link ApprovalEngine.submit} call from its tenant and document identity. */
|
|
554
579
|
type IdempotencyKeyFn = (tenantId: string, documentType: string, documentId: string, templateName: string, data: Record<string, unknown>) => string;
|
|
555
580
|
interface ApprovalEngineOptions {
|
|
556
581
|
adapter: IStorageAdapter;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Time source injected into engine and plugin components, so tests can control the clock. */
|
|
2
|
+
interface Clock {
|
|
3
|
+
now(): Date;
|
|
4
|
+
}
|
|
5
|
+
/** {@link Clock} backed by the real wall clock — the default when no clock is configured. */
|
|
6
|
+
declare const systemClock: Clock;
|
|
7
|
+
|
|
8
|
+
export { type Clock as C, systemClock as s };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Time source injected into engine and plugin components, so tests can control the clock. */
|
|
2
|
+
interface Clock {
|
|
3
|
+
now(): Date;
|
|
4
|
+
}
|
|
5
|
+
/** {@link Clock} backed by the real wall clock — the default when no clock is configured. */
|
|
6
|
+
declare const systemClock: Clock;
|
|
7
|
+
|
|
8
|
+
export { type Clock as C, systemClock as s };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { b as AuditEntry, a as ApprovalInstance } from './instance-
|
|
1
|
+
import { b as AuditEntry, a as ApprovalInstance } from './instance-CUZcHWK2.cjs';
|
|
2
2
|
|
|
3
|
+
/** Secondary write sink for audit entries, alongside the primary storage adapter. */
|
|
3
4
|
interface IAuditAdapter {
|
|
4
5
|
/**
|
|
5
6
|
* Called after every state-mutating operation, in addition to the primary storage adapter.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { b as AuditEntry, a as ApprovalInstance } from './instance-
|
|
1
|
+
import { b as AuditEntry, a as ApprovalInstance } from './instance-CUZcHWK2.js';
|
|
2
2
|
|
|
3
|
+
/** Secondary write sink for audit entries, alongside the primary storage adapter. */
|
|
3
4
|
interface IAuditAdapter {
|
|
4
5
|
/**
|
|
5
6
|
* Called after every state-mutating operation, in addition to the primary storage adapter.
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-
|
|
1
|
+
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-CUZcHWK2.js';
|
|
2
2
|
|
|
3
3
|
interface AuthorizationContext {
|
|
4
|
+
/** The engine method the actor is attempting to call. */
|
|
4
5
|
operation: 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'escalate' | 'override' | 'resubmit' | 'addComment' | 'updateData' | 'requestInfo' | 'provideInfo' | 'addAttachment' | 'removeAttachment';
|
|
6
|
+
/** Id of the user or system attempting the operation. */
|
|
5
7
|
actorId: string;
|
|
8
|
+
/** The instance the operation targets, as it stood before the operation ran. */
|
|
6
9
|
instance: Readonly<ApprovalInstance>;
|
|
10
|
+
/** The current level, for level-scoped operations (approve, reject, delegate, etc.); absent otherwise. */
|
|
7
11
|
level?: Readonly<ApprovalLevelInstance>;
|
|
12
|
+
/** The caller's own options object for this operation, passed through unmodified. */
|
|
8
13
|
opts: Record<string, unknown>;
|
|
9
14
|
}
|
|
10
15
|
interface IAuthorizationPolicy {
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-
|
|
1
|
+
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-CUZcHWK2.cjs';
|
|
2
2
|
|
|
3
3
|
interface AuthorizationContext {
|
|
4
|
+
/** The engine method the actor is attempting to call. */
|
|
4
5
|
operation: 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'escalate' | 'override' | 'resubmit' | 'addComment' | 'updateData' | 'requestInfo' | 'provideInfo' | 'addAttachment' | 'removeAttachment';
|
|
6
|
+
/** Id of the user or system attempting the operation. */
|
|
5
7
|
actorId: string;
|
|
8
|
+
/** The instance the operation targets, as it stood before the operation ran. */
|
|
6
9
|
instance: Readonly<ApprovalInstance>;
|
|
10
|
+
/** The current level, for level-scoped operations (approve, reject, delegate, etc.); absent otherwise. */
|
|
7
11
|
level?: Readonly<ApprovalLevelInstance>;
|
|
12
|
+
/** The caller's own options object for this operation, passed through unmodified. */
|
|
8
13
|
opts: Record<string, unknown>;
|
|
9
14
|
}
|
|
10
15
|
interface IAuthorizationPolicy {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Closed set of metric names an {@link IMetricsAdapter} may be called with, namespaced `approval.<verb>`. */
|
|
1
2
|
type MetricName = 'approval.submitted' | 'approval.approved' | 'approval.rejected' | 'approval.cancelled' | 'approval.expired' | 'approval.sla_breached' | 'approval.escalated' | 'approval.reassigned' | 'approval.overridden' | 'approval.data_updated' | 'approval.reminded' | 'approval.info_requested' | 'approval.info_provided' | 'approval.attachment_added' | 'approval.attachment_removed' | 'approval.conflict_retry' | 'approval.operation_duration_ms';
|
|
2
3
|
interface IMetricsAdapter {
|
|
3
4
|
/** Increment a counter. Synchronous — never awaited. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Closed set of metric names an {@link IMetricsAdapter} may be called with, namespaced `approval.<verb>`. */
|
|
1
2
|
type MetricName = 'approval.submitted' | 'approval.approved' | 'approval.rejected' | 'approval.cancelled' | 'approval.expired' | 'approval.sla_breached' | 'approval.escalated' | 'approval.reassigned' | 'approval.overridden' | 'approval.data_updated' | 'approval.reminded' | 'approval.info_requested' | 'approval.info_provided' | 'approval.attachment_added' | 'approval.attachment_removed' | 'approval.conflict_retry' | 'approval.operation_duration_ms';
|
|
2
3
|
interface IMetricsAdapter {
|
|
3
4
|
/** Increment a counter. Synchronous — never awaited. */
|
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
import { a as ApprovalInstance, b as AuditEntry } from './instance-
|
|
1
|
+
import { a as ApprovalInstance, b as AuditEntry } from './instance-CUZcHWK2.js';
|
|
2
2
|
|
|
3
|
+
/** Common fields carried by every lifecycle event emitted for an approval instance. */
|
|
3
4
|
interface ApprovalEvent {
|
|
5
|
+
/** The `ApprovalInstance.id` this event pertains to. */
|
|
4
6
|
instanceId: string;
|
|
7
|
+
/** The id of the business document the instance was raised against. */
|
|
5
8
|
documentId: string;
|
|
9
|
+
/** The document type, matching the template used to raise the instance. */
|
|
6
10
|
documentType: string;
|
|
11
|
+
/** When the event occurred. */
|
|
7
12
|
timestamp: Date;
|
|
8
13
|
}
|
|
14
|
+
/** Emitted as `approval:submitted` when a new instance is raised. */
|
|
9
15
|
interface SubmittedEvent extends ApprovalEvent {
|
|
10
16
|
submittedBy: string;
|
|
11
17
|
currentApprovers: string[];
|
|
12
18
|
}
|
|
19
|
+
/** Emitted as `approval:approved` when an approver accepts a level. */
|
|
13
20
|
interface ApprovedEvent extends ApprovalEvent {
|
|
14
21
|
approverId: string;
|
|
15
22
|
level: number;
|
|
16
23
|
comment?: string;
|
|
17
24
|
isFinal: boolean;
|
|
18
25
|
}
|
|
26
|
+
/** Emitted as `approval:rejected` when an approver rejects a level. */
|
|
19
27
|
interface RejectedEvent extends ApprovalEvent {
|
|
20
28
|
approverId: string;
|
|
21
29
|
level: number;
|
|
22
30
|
reason: string;
|
|
23
31
|
returnTo: 'originator' | 'previous' | null;
|
|
24
32
|
}
|
|
33
|
+
/** Emitted as `approval:delegated` when an approver hands their decision to someone else. */
|
|
25
34
|
interface DelegatedEvent extends ApprovalEvent {
|
|
26
35
|
fromApprover: string;
|
|
27
36
|
toApprover: string;
|
|
28
37
|
level: number;
|
|
29
38
|
reason: string;
|
|
30
39
|
}
|
|
40
|
+
/** Emitted as `approval:reassigned` when an admin moves a level to a different approver. */
|
|
31
41
|
interface ReassignedEvent extends ApprovalEvent {
|
|
32
42
|
reassignedBy: string;
|
|
33
43
|
fromApprover: string;
|
|
@@ -35,30 +45,37 @@ interface ReassignedEvent extends ApprovalEvent {
|
|
|
35
45
|
level: number;
|
|
36
46
|
reason: string;
|
|
37
47
|
}
|
|
48
|
+
/** Emitted as `approval:escalated` when a level's SLA rung hands off to a new approver. */
|
|
38
49
|
interface EscalatedEvent extends ApprovalEvent {
|
|
39
50
|
level: number;
|
|
40
51
|
escalatedTo: string;
|
|
41
52
|
}
|
|
53
|
+
/** Emitted as `approval:cancelled` when the instance is withdrawn before completion. */
|
|
42
54
|
interface CancelledEvent extends ApprovalEvent {
|
|
43
55
|
cancelledBy: string;
|
|
44
56
|
reason: string;
|
|
45
57
|
}
|
|
58
|
+
/** Emitted as `approval:level_advanced` when the chain moves to its next open level. */
|
|
46
59
|
interface LevelAdvancedEvent extends ApprovalEvent {
|
|
47
60
|
fromLevel: number;
|
|
48
61
|
toLevel: number;
|
|
49
62
|
newApprovers: string[];
|
|
50
63
|
}
|
|
64
|
+
/** Emitted as `approval:resubmitted` when a rejected instance is raised again. */
|
|
51
65
|
interface ResubmittedEvent extends ApprovalEvent {
|
|
52
66
|
resubmittedBy: string;
|
|
53
67
|
originalInstanceId: string;
|
|
54
68
|
}
|
|
69
|
+
/** Emitted as `approval:overridden` when an admin force-approves past the normal chain. */
|
|
55
70
|
interface OverriddenEvent extends ApprovalEvent {
|
|
56
71
|
overriddenBy: string;
|
|
57
72
|
justification: string;
|
|
58
73
|
}
|
|
74
|
+
/** Emitted as `approval:expired` when the instance's deadline passes unresolved. */
|
|
59
75
|
interface ExpiredEvent extends ApprovalEvent {
|
|
60
76
|
deadlineAction: 'cancel' | 'reject';
|
|
61
77
|
}
|
|
78
|
+
/** Emitted as `approval:sla_breached` when a level's deadline passes without expiring the instance. */
|
|
62
79
|
interface SlaBreachedEvent extends ApprovalEvent {
|
|
63
80
|
slaDeadlineAt: Date;
|
|
64
81
|
}
|
|
@@ -160,15 +177,23 @@ interface HistoryEntry extends AuditEntry {
|
|
|
160
177
|
}
|
|
161
178
|
|
|
162
179
|
interface NotificationEvent {
|
|
180
|
+
/** The event that fired, e.g. `'submitted'`, `'approved'`, `'escalated'`. */
|
|
163
181
|
type: ApprovalEventName;
|
|
182
|
+
/** Id of the approval instance the event fired for. */
|
|
164
183
|
instanceId: string;
|
|
184
|
+
/** Id of the document under approval, as submitted by the caller. */
|
|
165
185
|
documentId: string;
|
|
186
|
+
/** Caller-defined document category (e.g. `'purchase_order'`). */
|
|
166
187
|
documentType: string;
|
|
188
|
+
/** When the underlying transition happened. */
|
|
167
189
|
timestamp: Date;
|
|
168
190
|
/** Current-level approver IDs; empty for non-level events (cancelled, expired, etc.). */
|
|
169
191
|
recipients: string[];
|
|
192
|
+
/** Name of the template governing the instance. */
|
|
170
193
|
templateName: string;
|
|
194
|
+
/** Tenant the instance belongs to, for multi-tenant deployments. */
|
|
171
195
|
tenantId: string;
|
|
196
|
+
/** Event-specific detail, shaped by {@link type}. */
|
|
172
197
|
payload: ApprovalEventMap[ApprovalEventName];
|
|
173
198
|
}
|
|
174
199
|
interface INotificationAdapter {
|
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
import { a as ApprovalInstance, b as AuditEntry } from './instance-
|
|
1
|
+
import { a as ApprovalInstance, b as AuditEntry } from './instance-CUZcHWK2.cjs';
|
|
2
2
|
|
|
3
|
+
/** Common fields carried by every lifecycle event emitted for an approval instance. */
|
|
3
4
|
interface ApprovalEvent {
|
|
5
|
+
/** The `ApprovalInstance.id` this event pertains to. */
|
|
4
6
|
instanceId: string;
|
|
7
|
+
/** The id of the business document the instance was raised against. */
|
|
5
8
|
documentId: string;
|
|
9
|
+
/** The document type, matching the template used to raise the instance. */
|
|
6
10
|
documentType: string;
|
|
11
|
+
/** When the event occurred. */
|
|
7
12
|
timestamp: Date;
|
|
8
13
|
}
|
|
14
|
+
/** Emitted as `approval:submitted` when a new instance is raised. */
|
|
9
15
|
interface SubmittedEvent extends ApprovalEvent {
|
|
10
16
|
submittedBy: string;
|
|
11
17
|
currentApprovers: string[];
|
|
12
18
|
}
|
|
19
|
+
/** Emitted as `approval:approved` when an approver accepts a level. */
|
|
13
20
|
interface ApprovedEvent extends ApprovalEvent {
|
|
14
21
|
approverId: string;
|
|
15
22
|
level: number;
|
|
16
23
|
comment?: string;
|
|
17
24
|
isFinal: boolean;
|
|
18
25
|
}
|
|
26
|
+
/** Emitted as `approval:rejected` when an approver rejects a level. */
|
|
19
27
|
interface RejectedEvent extends ApprovalEvent {
|
|
20
28
|
approverId: string;
|
|
21
29
|
level: number;
|
|
22
30
|
reason: string;
|
|
23
31
|
returnTo: 'originator' | 'previous' | null;
|
|
24
32
|
}
|
|
33
|
+
/** Emitted as `approval:delegated` when an approver hands their decision to someone else. */
|
|
25
34
|
interface DelegatedEvent extends ApprovalEvent {
|
|
26
35
|
fromApprover: string;
|
|
27
36
|
toApprover: string;
|
|
28
37
|
level: number;
|
|
29
38
|
reason: string;
|
|
30
39
|
}
|
|
40
|
+
/** Emitted as `approval:reassigned` when an admin moves a level to a different approver. */
|
|
31
41
|
interface ReassignedEvent extends ApprovalEvent {
|
|
32
42
|
reassignedBy: string;
|
|
33
43
|
fromApprover: string;
|
|
@@ -35,30 +45,37 @@ interface ReassignedEvent extends ApprovalEvent {
|
|
|
35
45
|
level: number;
|
|
36
46
|
reason: string;
|
|
37
47
|
}
|
|
48
|
+
/** Emitted as `approval:escalated` when a level's SLA rung hands off to a new approver. */
|
|
38
49
|
interface EscalatedEvent extends ApprovalEvent {
|
|
39
50
|
level: number;
|
|
40
51
|
escalatedTo: string;
|
|
41
52
|
}
|
|
53
|
+
/** Emitted as `approval:cancelled` when the instance is withdrawn before completion. */
|
|
42
54
|
interface CancelledEvent extends ApprovalEvent {
|
|
43
55
|
cancelledBy: string;
|
|
44
56
|
reason: string;
|
|
45
57
|
}
|
|
58
|
+
/** Emitted as `approval:level_advanced` when the chain moves to its next open level. */
|
|
46
59
|
interface LevelAdvancedEvent extends ApprovalEvent {
|
|
47
60
|
fromLevel: number;
|
|
48
61
|
toLevel: number;
|
|
49
62
|
newApprovers: string[];
|
|
50
63
|
}
|
|
64
|
+
/** Emitted as `approval:resubmitted` when a rejected instance is raised again. */
|
|
51
65
|
interface ResubmittedEvent extends ApprovalEvent {
|
|
52
66
|
resubmittedBy: string;
|
|
53
67
|
originalInstanceId: string;
|
|
54
68
|
}
|
|
69
|
+
/** Emitted as `approval:overridden` when an admin force-approves past the normal chain. */
|
|
55
70
|
interface OverriddenEvent extends ApprovalEvent {
|
|
56
71
|
overriddenBy: string;
|
|
57
72
|
justification: string;
|
|
58
73
|
}
|
|
74
|
+
/** Emitted as `approval:expired` when the instance's deadline passes unresolved. */
|
|
59
75
|
interface ExpiredEvent extends ApprovalEvent {
|
|
60
76
|
deadlineAction: 'cancel' | 'reject';
|
|
61
77
|
}
|
|
78
|
+
/** Emitted as `approval:sla_breached` when a level's deadline passes without expiring the instance. */
|
|
62
79
|
interface SlaBreachedEvent extends ApprovalEvent {
|
|
63
80
|
slaDeadlineAt: Date;
|
|
64
81
|
}
|
|
@@ -160,15 +177,23 @@ interface HistoryEntry extends AuditEntry {
|
|
|
160
177
|
}
|
|
161
178
|
|
|
162
179
|
interface NotificationEvent {
|
|
180
|
+
/** The event that fired, e.g. `'submitted'`, `'approved'`, `'escalated'`. */
|
|
163
181
|
type: ApprovalEventName;
|
|
182
|
+
/** Id of the approval instance the event fired for. */
|
|
164
183
|
instanceId: string;
|
|
184
|
+
/** Id of the document under approval, as submitted by the caller. */
|
|
165
185
|
documentId: string;
|
|
186
|
+
/** Caller-defined document category (e.g. `'purchase_order'`). */
|
|
166
187
|
documentType: string;
|
|
188
|
+
/** When the underlying transition happened. */
|
|
167
189
|
timestamp: Date;
|
|
168
190
|
/** Current-level approver IDs; empty for non-level events (cancelled, expired, etc.). */
|
|
169
191
|
recipients: string[];
|
|
192
|
+
/** Name of the template governing the instance. */
|
|
170
193
|
templateName: string;
|
|
194
|
+
/** Tenant the instance belongs to, for multi-tenant deployments. */
|
|
171
195
|
tenantId: string;
|
|
196
|
+
/** Event-specific detail, shaped by {@link type}. */
|
|
172
197
|
payload: ApprovalEventMap[ApprovalEventName];
|
|
173
198
|
}
|
|
174
199
|
interface INotificationAdapter {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as ApprovalInstance } from './instance-
|
|
1
|
+
import { a as ApprovalInstance } from './instance-CUZcHWK2.js';
|
|
2
2
|
|
|
3
|
+
/** Base class for all errors thrown by this library; carries a stable machine-readable `code`. */
|
|
3
4
|
declare class ApprovalError extends Error {
|
|
4
5
|
readonly code: string;
|
|
5
6
|
constructor(message: string, code: string);
|
|
@@ -10,28 +11,40 @@ declare class ApprovalError extends Error {
|
|
|
10
11
|
};
|
|
11
12
|
toHttpStatus(): number;
|
|
12
13
|
}
|
|
14
|
+
/** Thrown when a requested resource (instance, template, etc.) does not exist. */
|
|
13
15
|
declare class ApprovalNotFoundError extends ApprovalError {
|
|
14
16
|
constructor(resource: string, id: string);
|
|
15
17
|
}
|
|
18
|
+
/** Thrown when an instance was modified by another process since it was last read. */
|
|
16
19
|
declare class ApprovalConflictError extends ApprovalError {
|
|
17
20
|
constructor(instanceId: string);
|
|
18
21
|
}
|
|
22
|
+
/** Thrown when the caller is not authorized to perform the requested action. */
|
|
19
23
|
declare class ApprovalForbiddenError extends ApprovalError {
|
|
20
24
|
constructor(message: string);
|
|
21
25
|
}
|
|
26
|
+
/** Thrown when input or configuration fails validation; `cause` may hold the originating error. */
|
|
22
27
|
declare class ApprovalValidationError extends ApprovalError {
|
|
23
28
|
readonly cause?: unknown | undefined;
|
|
24
29
|
constructor(message: string, cause?: unknown | undefined);
|
|
25
30
|
}
|
|
31
|
+
/** Thrown when a template lookup by name finds no registered template. */
|
|
26
32
|
declare class ApprovalTemplateNotFoundError extends ApprovalError {
|
|
27
33
|
constructor(name: string);
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
/** The engine method a middleware hook is running around. */
|
|
37
|
+
type EngineOperation = 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'updateData' | 'requestInfo' | 'provideInfo' | 'addAttachment' | 'removeAttachment' | 'addComment' | 'resubmit' | 'override';
|
|
38
|
+
/** Context passed to an {@link IOperationMiddleware} hook for one engine call. */
|
|
30
39
|
interface OperationContext<T = unknown> {
|
|
31
|
-
operation:
|
|
40
|
+
operation: EngineOperation;
|
|
41
|
+
/** The target instance's id, for operations that act on an existing instance. */
|
|
32
42
|
instanceId?: string;
|
|
43
|
+
/** Id of the user or system performing the operation, when known. */
|
|
33
44
|
actorId?: string;
|
|
45
|
+
/** The engine's configured tenant id (defaults to `'default'`). */
|
|
34
46
|
tenantId: string;
|
|
47
|
+
/** The caller's own input for this operation, e.g. the submit payload or decision comment. */
|
|
35
48
|
input: T;
|
|
36
49
|
}
|
|
37
50
|
interface IOperationMiddleware {
|