hierarchical-approval 0.2.0 → 0.3.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 (65) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +232 -0
  3. package/dist/{ApprovalEngine-DICBgdIp.d.ts → ApprovalEngine-Bmg1bbrd.d.cts} +9 -190
  4. package/dist/{ApprovalEngine-CSxLWZ5h.d.cts → ApprovalEngine-DLyhejR-.d.ts} +9 -190
  5. package/dist/Clock-3FnOczFJ.d.cts +6 -0
  6. package/dist/Clock-3FnOczFJ.d.ts +6 -0
  7. package/dist/IAuditAdapter-B3vvU09m.d.ts +12 -0
  8. package/dist/IAuditAdapter-B_DhuPsU.d.cts +12 -0
  9. package/dist/IMetricsAdapter-D9PUz4tM.d.cts +9 -0
  10. package/dist/IMetricsAdapter-D9PUz4tM.d.ts +9 -0
  11. package/dist/INotificationAdapter-BdfVjYa8.d.ts +102 -0
  12. package/dist/INotificationAdapter-DVVmXU6a.d.cts +102 -0
  13. package/dist/IOperationMiddleware-CkRh93Wf.d.cts +62 -0
  14. package/dist/IOperationMiddleware-Dk_xOKxR.d.ts +62 -0
  15. package/dist/IStorageAdapter-DbeWhtCG.d.cts +47 -0
  16. package/dist/IStorageAdapter-EdwtErKD.d.ts +47 -0
  17. package/dist/Logger-CIzvalFc.d.cts +9 -0
  18. package/dist/Logger-CIzvalFc.d.ts +9 -0
  19. package/dist/adapters/MemoryAdapter.cjs +1 -6
  20. package/dist/adapters/MemoryAdapter.cjs.map +1 -1
  21. package/dist/adapters/MemoryAdapter.d.cts +3 -2
  22. package/dist/adapters/MemoryAdapter.d.ts +3 -2
  23. package/dist/adapters/MemoryAdapter.js +1 -6
  24. package/dist/adapters/MemoryAdapter.js.map +1 -1
  25. package/dist/adapters/PostgresAdapter.d.cts +2 -1
  26. package/dist/adapters/PostgresAdapter.d.ts +2 -1
  27. package/dist/index.cjs +1 -6
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +12 -4
  30. package/dist/index.d.ts +12 -4
  31. package/dist/index.js +1 -6
  32. package/dist/index.js.map +1 -1
  33. package/dist/{IStorageAdapter-B2xGuaKi.d.cts → instance-D8D7b07N.d.cts} +1 -45
  34. package/dist/{IStorageAdapter-B2xGuaKi.d.ts → instance-D8D7b07N.d.ts} +1 -45
  35. package/dist/plugins/audit.cjs +370 -0
  36. package/dist/plugins/audit.cjs.map +1 -0
  37. package/dist/plugins/audit.d.cts +292 -0
  38. package/dist/plugins/audit.d.ts +292 -0
  39. package/dist/plugins/audit.js +362 -0
  40. package/dist/plugins/audit.js.map +1 -0
  41. package/dist/plugins/metrics.cjs +406 -0
  42. package/dist/plugins/metrics.cjs.map +1 -0
  43. package/dist/plugins/metrics.d.cts +282 -0
  44. package/dist/plugins/metrics.d.ts +282 -0
  45. package/dist/plugins/metrics.js +399 -0
  46. package/dist/plugins/metrics.js.map +1 -0
  47. package/dist/plugins/notify.cjs +373 -0
  48. package/dist/plugins/notify.cjs.map +1 -0
  49. package/dist/plugins/notify.d.cts +349 -0
  50. package/dist/plugins/notify.d.ts +349 -0
  51. package/dist/plugins/notify.js +368 -0
  52. package/dist/plugins/notify.js.map +1 -0
  53. package/dist/plugins/resilience.cjs +328 -0
  54. package/dist/plugins/resilience.cjs.map +1 -0
  55. package/dist/plugins/resilience.d.cts +310 -0
  56. package/dist/plugins/resilience.d.ts +310 -0
  57. package/dist/plugins/resilience.js +321 -0
  58. package/dist/plugins/resilience.js.map +1 -0
  59. package/dist/testing.cjs +1 -6
  60. package/dist/testing.cjs.map +1 -1
  61. package/dist/testing.d.cts +9 -2
  62. package/dist/testing.d.ts +9 -2
  63. package/dist/testing.js +1 -6
  64. package/dist/testing.js.map +1 -1
  65. package/package.json +22 -1
@@ -1,87 +1,12 @@
1
- import { a as ApprovalInstance, d as AuditEntry, g as ApprovalLevelInstance, I as IStorageAdapter, q as ResolverFn, j as ApprovalTemplateConfig, A as ApprovalTemplate, m as AuditContext, h as ApprovalMode, P as PaginationOpts, b as PaginatedResult, c as InstanceFilter, C as CursorPaginationOpts, e as CursorPaginatedResult } from './IStorageAdapter-B2xGuaKi.cjs';
1
+ import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-EdwtErKD.js';
2
+ import { m as ResolverFn, g as ApprovalTemplateConfig, A as ApprovalTemplate, j as AuditContext, a as ApprovalInstance, e as ApprovalMode, b as AuditEntry } from './instance-D8D7b07N.js';
3
+ import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-BdfVjYa8.js';
2
4
  import { z } from 'zod';
3
-
4
- interface ApprovalEvent {
5
- instanceId: string;
6
- documentId: string;
7
- documentType: string;
8
- timestamp: Date;
9
- }
10
- interface SubmittedEvent extends ApprovalEvent {
11
- submittedBy: string;
12
- currentApprovers: string[];
13
- }
14
- interface ApprovedEvent extends ApprovalEvent {
15
- approverId: string;
16
- level: number;
17
- comment?: string;
18
- isFinal: boolean;
19
- }
20
- interface RejectedEvent extends ApprovalEvent {
21
- approverId: string;
22
- level: number;
23
- reason: string;
24
- returnTo: 'originator' | 'previous' | null;
25
- }
26
- interface DelegatedEvent extends ApprovalEvent {
27
- fromApprover: string;
28
- toApprover: string;
29
- level: number;
30
- reason: string;
31
- }
32
- interface ReassignedEvent extends ApprovalEvent {
33
- reassignedBy: string;
34
- fromApprover: string;
35
- toApprover: string;
36
- level: number;
37
- reason: string;
38
- }
39
- interface EscalatedEvent extends ApprovalEvent {
40
- level: number;
41
- escalatedTo: string;
42
- }
43
- interface CancelledEvent extends ApprovalEvent {
44
- cancelledBy: string;
45
- reason: string;
46
- }
47
- interface LevelAdvancedEvent extends ApprovalEvent {
48
- fromLevel: number;
49
- toLevel: number;
50
- newApprovers: string[];
51
- }
52
- interface ResubmittedEvent extends ApprovalEvent {
53
- resubmittedBy: string;
54
- originalInstanceId: string;
55
- }
56
- interface OverriddenEvent extends ApprovalEvent {
57
- overriddenBy: string;
58
- justification: string;
59
- }
60
- interface ExpiredEvent extends ApprovalEvent {
61
- deadlineAction: 'cancel' | 'reject';
62
- }
63
- interface SlaBreachedEvent extends ApprovalEvent {
64
- slaDeadlineAt: Date;
65
- }
66
- interface ApprovalEventMap {
67
- 'approval:submitted': SubmittedEvent;
68
- 'approval:approved': ApprovedEvent;
69
- 'approval:rejected': RejectedEvent;
70
- 'approval:delegated': DelegatedEvent;
71
- 'approval:reassigned': ReassignedEvent;
72
- 'approval:escalated': EscalatedEvent;
73
- 'approval:cancelled': CancelledEvent;
74
- 'approval:completed': ApprovalInstance;
75
- 'approval:level_advanced': LevelAdvancedEvent;
76
- 'approval:resubmitted': ResubmittedEvent;
77
- 'approval:overridden': OverriddenEvent;
78
- 'approval:expired': ExpiredEvent;
79
- 'approval:sla_breached': SlaBreachedEvent;
80
- }
81
- type ApprovalEventName = keyof ApprovalEventMap;
82
- interface HistoryEntry extends AuditEntry {
83
- instanceId: string;
84
- }
5
+ import { L as Logger } from './Logger-CIzvalFc.js';
6
+ import { C as Clock } from './Clock-3FnOczFJ.js';
7
+ import { I as IAuthorizationPolicy, g as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-Dk_xOKxR.js';
8
+ import { I as IAuditAdapter } from './IAuditAdapter-B3vvU09m.js';
9
+ import { I as IMetricsAdapter } from './IMetricsAdapter-D9PUz4tM.js';
85
10
 
86
11
  declare const SubmitOptionsSchema: z.ZodObject<{
87
12
  templateName: z.ZodString;
@@ -151,19 +76,6 @@ type ResubmitOptions = z.infer<typeof ResubmitOptionsSchema>;
151
76
  type AddCommentOptions = z.infer<typeof AddCommentOptionsSchema>;
152
77
  type OverrideOptions = z.infer<typeof OverrideOptionsSchema>;
153
78
 
154
- interface Logger {
155
- info(msg: string, context?: Record<string, unknown>): void;
156
- warn(msg: string, context?: Record<string, unknown>): void;
157
- error(msg: string, err?: unknown, context?: Record<string, unknown>): void;
158
- debug(msg: string, context?: Record<string, unknown>): void;
159
- }
160
- declare const noopLogger: Logger;
161
-
162
- interface Clock {
163
- now(): Date;
164
- }
165
- declare const systemClock: Clock;
166
-
167
79
  /**
168
80
  * Computes deadline dates from a number of days. The default engine behaviour
169
81
  * treats day offsets (escalationAfterDays, slaDeadlineDays) as plain calendar
@@ -216,67 +128,6 @@ type ApproverResolverFn = (config: Record<string, unknown>, ctx: {
216
128
 
217
129
  type ConditionOperatorFn = (actual: unknown, expected: unknown) => boolean;
218
130
 
219
- declare class ApprovalError extends Error {
220
- readonly code: string;
221
- constructor(message: string, code: string);
222
- toJSON(): {
223
- code: string;
224
- message: string;
225
- name: string;
226
- };
227
- toHttpStatus(): number;
228
- }
229
- declare class ApprovalNotFoundError extends ApprovalError {
230
- constructor(resource: string, id: string);
231
- }
232
- declare class ApprovalConflictError extends ApprovalError {
233
- constructor(instanceId: string);
234
- }
235
- declare class ApprovalForbiddenError extends ApprovalError {
236
- constructor(message: string);
237
- }
238
- declare class ApprovalValidationError extends ApprovalError {
239
- readonly cause?: unknown | undefined;
240
- constructor(message: string, cause?: unknown | undefined);
241
- }
242
- declare class ApprovalTemplateNotFoundError extends ApprovalError {
243
- constructor(name: string);
244
- }
245
-
246
- interface NotificationEvent {
247
- type: ApprovalEventName;
248
- instanceId: string;
249
- documentId: string;
250
- documentType: string;
251
- timestamp: Date;
252
- /** Current-level approver IDs; empty for non-level events (cancelled, expired, etc.). */
253
- recipients: string[];
254
- templateName: string;
255
- tenantId: string;
256
- payload: ApprovalEventMap[ApprovalEventName];
257
- }
258
- interface INotificationAdapter {
259
- /** Called after every emitted approval event. Must not throw — errors are logged and swallowed. */
260
- notify(event: NotificationEvent): Promise<void>;
261
- }
262
-
263
- interface IAuditAdapter {
264
- /**
265
- * Called after every state-mutating operation, in addition to the primary storage adapter.
266
- * Intended for write-once sinks: Kafka, S3, CloudTrail, WORM stores.
267
- * Must not throw — errors are logged and swallowed.
268
- */
269
- append(tenantId: string, instanceId: string, entry: AuditEntry, instance: Readonly<ApprovalInstance>): Promise<void>;
270
- }
271
-
272
- type MetricName = 'approval.submitted' | 'approval.approved' | 'approval.rejected' | 'approval.cancelled' | 'approval.expired' | 'approval.sla_breached' | 'approval.escalated' | 'approval.reassigned' | 'approval.overridden' | 'approval.conflict_retry' | 'approval.operation_duration_ms';
273
- interface IMetricsAdapter {
274
- /** Increment a counter. Synchronous — never awaited. */
275
- increment(metric: MetricName, labels?: Record<string, string>): void;
276
- /** Record a timing measurement in milliseconds. Synchronous — never awaited. */
277
- timing(metric: MetricName, durationMs: number, labels?: Record<string, string>): void;
278
- }
279
-
280
131
  interface ISchedulerAdapter {
281
132
  /**
282
133
  * Schedule a one-shot callback to run at the given date.
@@ -289,38 +140,6 @@ interface ISchedulerAdapter {
289
140
  shutdown(): Promise<void>;
290
141
  }
291
142
 
292
- interface AuthorizationContext {
293
- operation: 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'escalate' | 'override' | 'resubmit' | 'addComment';
294
- actorId: string;
295
- instance: Readonly<ApprovalInstance>;
296
- level?: Readonly<ApprovalLevelInstance>;
297
- opts: Record<string, unknown>;
298
- }
299
- interface IAuthorizationPolicy {
300
- /**
301
- * Return undefined to allow the operation.
302
- * Return a non-empty string to deny — the engine throws ApprovalForbiddenError(message).
303
- * Throwing ApprovalForbiddenError directly is also permitted.
304
- */
305
- authorize(ctx: AuthorizationContext): Promise<string | undefined> | string | undefined;
306
- }
307
-
308
- interface OperationContext<T = unknown> {
309
- operation: string;
310
- instanceId?: string;
311
- actorId?: string;
312
- tenantId: string;
313
- input: T;
314
- }
315
- interface IOperationMiddleware {
316
- /** Runs after authorization and input validation, before state mutations. */
317
- before?(ctx: OperationContext): Promise<void> | void;
318
- /** Runs after successful completion of the operation. */
319
- after?(ctx: OperationContext, result: ApprovalInstance | void): Promise<void> | void;
320
- /** Runs when an ApprovalError is thrown. Does not suppress the error. */
321
- onError?(ctx: OperationContext, error: ApprovalError): Promise<void> | void;
322
- }
323
-
324
143
  interface ValidationResult {
325
144
  valid: boolean;
326
145
  errors: Array<{
@@ -501,4 +320,4 @@ declare class ApprovalEngine {
501
320
  private runExternalAudit;
502
321
  }
503
322
 
504
- export { type ResubmitOptions as $, type AddCommentOptions as A, type BulkResult as B, type Clock as C, type DelegateOptions as D, type EscalateOptions as E, type IMetricsAdapter as F, type INotificationAdapter as G, type HealthResult as H, type IAuditAdapter as I, type IOperationMiddleware as J, type ISchedulerAdapter as K, type Logger as L, type IdGeneratorFn as M, type IdempotencyKeyFn as N, type LevelAdvancedEvent as O, type MetricName as P, type NotificationEvent as Q, type OperationContext as R, type OrgProvider as S, type OverriddenEvent as T, type OverrideOptions as U, type PreviewChainLevel as V, type PreviewResult as W, type ReassignOptions as X, type ReassignedEvent as Y, type RejectOptions as Z, type RejectedEvent as _, ApprovalConflictError as a, type ResubmittedEvent as a0, type RetryPolicy as a1, type SlaBreachedEvent as a2, type SubmitOptions as a3, type SubmittedEvent as a4, type ValidationResult as a5, type WeekendCalendarOptions as a6, defaultIdGenerator as a7, noopLogger as a8, systemClock as a9, weekendCalendar as aa, ApprovalEngine as b, type ApprovalEngineOptions as c, ApprovalError as d, type ApprovalEvent as e, type ApprovalEventMap as f, type ApprovalEventName as g, ApprovalForbiddenError as h, ApprovalNotFoundError as i, type ApprovalStatistics as j, ApprovalTemplateNotFoundError as k, ApprovalValidationError as l, type ApproveOptions as m, type ApprovedEvent as n, type ApproverResolverFn as o, type AuthorizationContext as p, type BusinessCalendar as q, type CanApproveResult as r, type CancelOptions as s, type CancelledEvent as t, type ConditionOperatorFn as u, type DelegatedEvent as v, type EscalatedEvent as w, type ExpiredEvent as x, type HistoryEntry as y, type IAuthorizationPolicy as z };
323
+ export { type AddCommentOptions as A, type BulkResult as B, type CanApproveResult as C, type DelegateOptions as D, type EscalateOptions as E, type HealthResult as H, type ISchedulerAdapter as I, type OrgProvider as O, type PreviewChainLevel as P, type ReassignOptions as R, type SubmitOptions as S, type ValidationResult as V, type WeekendCalendarOptions as W, ApprovalEngine as a, type ApprovalEngineOptions as b, type ApprovalStatistics as c, type ApproveOptions as d, type ApproverResolverFn as e, type BusinessCalendar as f, type CancelOptions as g, type ConditionOperatorFn as h, type IdGeneratorFn as i, type IdempotencyKeyFn as j, type OverrideOptions as k, type PreviewResult as l, type RejectOptions as m, type ResubmitOptions as n, type RetryPolicy as o, defaultIdGenerator as p, weekendCalendar as w };
@@ -0,0 +1,6 @@
1
+ interface Clock {
2
+ now(): Date;
3
+ }
4
+ declare const systemClock: Clock;
5
+
6
+ export { type Clock as C, systemClock as s };
@@ -0,0 +1,6 @@
1
+ interface Clock {
2
+ now(): Date;
3
+ }
4
+ declare const systemClock: Clock;
5
+
6
+ export { type Clock as C, systemClock as s };
@@ -0,0 +1,12 @@
1
+ import { b as AuditEntry, a as ApprovalInstance } from './instance-D8D7b07N.js';
2
+
3
+ interface IAuditAdapter {
4
+ /**
5
+ * Called after every state-mutating operation, in addition to the primary storage adapter.
6
+ * Intended for write-once sinks: Kafka, S3, CloudTrail, WORM stores.
7
+ * Must not throw — errors are logged and swallowed.
8
+ */
9
+ append(tenantId: string, instanceId: string, entry: AuditEntry, instance: Readonly<ApprovalInstance>): Promise<void>;
10
+ }
11
+
12
+ export type { IAuditAdapter as I };
@@ -0,0 +1,12 @@
1
+ import { b as AuditEntry, a as ApprovalInstance } from './instance-D8D7b07N.cjs';
2
+
3
+ interface IAuditAdapter {
4
+ /**
5
+ * Called after every state-mutating operation, in addition to the primary storage adapter.
6
+ * Intended for write-once sinks: Kafka, S3, CloudTrail, WORM stores.
7
+ * Must not throw — errors are logged and swallowed.
8
+ */
9
+ append(tenantId: string, instanceId: string, entry: AuditEntry, instance: Readonly<ApprovalInstance>): Promise<void>;
10
+ }
11
+
12
+ export type { IAuditAdapter as I };
@@ -0,0 +1,9 @@
1
+ type MetricName = 'approval.submitted' | 'approval.approved' | 'approval.rejected' | 'approval.cancelled' | 'approval.expired' | 'approval.sla_breached' | 'approval.escalated' | 'approval.reassigned' | 'approval.overridden' | 'approval.conflict_retry' | 'approval.operation_duration_ms';
2
+ interface IMetricsAdapter {
3
+ /** Increment a counter. Synchronous — never awaited. */
4
+ increment(metric: MetricName, labels?: Record<string, string>): void;
5
+ /** Record a timing measurement in milliseconds. Synchronous — never awaited. */
6
+ timing(metric: MetricName, durationMs: number, labels?: Record<string, string>): void;
7
+ }
8
+
9
+ export type { IMetricsAdapter as I, MetricName as M };
@@ -0,0 +1,9 @@
1
+ type MetricName = 'approval.submitted' | 'approval.approved' | 'approval.rejected' | 'approval.cancelled' | 'approval.expired' | 'approval.sla_breached' | 'approval.escalated' | 'approval.reassigned' | 'approval.overridden' | 'approval.conflict_retry' | 'approval.operation_duration_ms';
2
+ interface IMetricsAdapter {
3
+ /** Increment a counter. Synchronous — never awaited. */
4
+ increment(metric: MetricName, labels?: Record<string, string>): void;
5
+ /** Record a timing measurement in milliseconds. Synchronous — never awaited. */
6
+ timing(metric: MetricName, durationMs: number, labels?: Record<string, string>): void;
7
+ }
8
+
9
+ export type { IMetricsAdapter as I, MetricName as M };
@@ -0,0 +1,102 @@
1
+ import { a as ApprovalInstance, b as AuditEntry } from './instance-D8D7b07N.js';
2
+
3
+ interface ApprovalEvent {
4
+ instanceId: string;
5
+ documentId: string;
6
+ documentType: string;
7
+ timestamp: Date;
8
+ }
9
+ interface SubmittedEvent extends ApprovalEvent {
10
+ submittedBy: string;
11
+ currentApprovers: string[];
12
+ }
13
+ interface ApprovedEvent extends ApprovalEvent {
14
+ approverId: string;
15
+ level: number;
16
+ comment?: string;
17
+ isFinal: boolean;
18
+ }
19
+ interface RejectedEvent extends ApprovalEvent {
20
+ approverId: string;
21
+ level: number;
22
+ reason: string;
23
+ returnTo: 'originator' | 'previous' | null;
24
+ }
25
+ interface DelegatedEvent extends ApprovalEvent {
26
+ fromApprover: string;
27
+ toApprover: string;
28
+ level: number;
29
+ reason: string;
30
+ }
31
+ interface ReassignedEvent extends ApprovalEvent {
32
+ reassignedBy: string;
33
+ fromApprover: string;
34
+ toApprover: string;
35
+ level: number;
36
+ reason: string;
37
+ }
38
+ interface EscalatedEvent extends ApprovalEvent {
39
+ level: number;
40
+ escalatedTo: string;
41
+ }
42
+ interface CancelledEvent extends ApprovalEvent {
43
+ cancelledBy: string;
44
+ reason: string;
45
+ }
46
+ interface LevelAdvancedEvent extends ApprovalEvent {
47
+ fromLevel: number;
48
+ toLevel: number;
49
+ newApprovers: string[];
50
+ }
51
+ interface ResubmittedEvent extends ApprovalEvent {
52
+ resubmittedBy: string;
53
+ originalInstanceId: string;
54
+ }
55
+ interface OverriddenEvent extends ApprovalEvent {
56
+ overriddenBy: string;
57
+ justification: string;
58
+ }
59
+ interface ExpiredEvent extends ApprovalEvent {
60
+ deadlineAction: 'cancel' | 'reject';
61
+ }
62
+ interface SlaBreachedEvent extends ApprovalEvent {
63
+ slaDeadlineAt: Date;
64
+ }
65
+ interface ApprovalEventMap {
66
+ 'approval:submitted': SubmittedEvent;
67
+ 'approval:approved': ApprovedEvent;
68
+ 'approval:rejected': RejectedEvent;
69
+ 'approval:delegated': DelegatedEvent;
70
+ 'approval:reassigned': ReassignedEvent;
71
+ 'approval:escalated': EscalatedEvent;
72
+ 'approval:cancelled': CancelledEvent;
73
+ 'approval:completed': ApprovalInstance;
74
+ 'approval:level_advanced': LevelAdvancedEvent;
75
+ 'approval:resubmitted': ResubmittedEvent;
76
+ 'approval:overridden': OverriddenEvent;
77
+ 'approval:expired': ExpiredEvent;
78
+ 'approval:sla_breached': SlaBreachedEvent;
79
+ }
80
+ type ApprovalEventName = keyof ApprovalEventMap;
81
+ interface HistoryEntry extends AuditEntry {
82
+ instanceId: string;
83
+ }
84
+
85
+ interface NotificationEvent {
86
+ type: ApprovalEventName;
87
+ instanceId: string;
88
+ documentId: string;
89
+ documentType: string;
90
+ timestamp: Date;
91
+ /** Current-level approver IDs; empty for non-level events (cancelled, expired, etc.). */
92
+ recipients: string[];
93
+ templateName: string;
94
+ tenantId: string;
95
+ payload: ApprovalEventMap[ApprovalEventName];
96
+ }
97
+ interface INotificationAdapter {
98
+ /** Called after every emitted approval event. Must not throw — errors are logged and swallowed. */
99
+ notify(event: NotificationEvent): Promise<void>;
100
+ }
101
+
102
+ export type { ApprovalEvent as A, CancelledEvent as C, DelegatedEvent as D, EscalatedEvent as E, HistoryEntry as H, INotificationAdapter as I, LevelAdvancedEvent as L, NotificationEvent as N, OverriddenEvent as O, ReassignedEvent as R, SlaBreachedEvent as S, ApprovalEventMap as a, ApprovalEventName as b, ApprovedEvent as c, ExpiredEvent as d, RejectedEvent as e, ResubmittedEvent as f, SubmittedEvent as g };
@@ -0,0 +1,102 @@
1
+ import { a as ApprovalInstance, b as AuditEntry } from './instance-D8D7b07N.cjs';
2
+
3
+ interface ApprovalEvent {
4
+ instanceId: string;
5
+ documentId: string;
6
+ documentType: string;
7
+ timestamp: Date;
8
+ }
9
+ interface SubmittedEvent extends ApprovalEvent {
10
+ submittedBy: string;
11
+ currentApprovers: string[];
12
+ }
13
+ interface ApprovedEvent extends ApprovalEvent {
14
+ approverId: string;
15
+ level: number;
16
+ comment?: string;
17
+ isFinal: boolean;
18
+ }
19
+ interface RejectedEvent extends ApprovalEvent {
20
+ approverId: string;
21
+ level: number;
22
+ reason: string;
23
+ returnTo: 'originator' | 'previous' | null;
24
+ }
25
+ interface DelegatedEvent extends ApprovalEvent {
26
+ fromApprover: string;
27
+ toApprover: string;
28
+ level: number;
29
+ reason: string;
30
+ }
31
+ interface ReassignedEvent extends ApprovalEvent {
32
+ reassignedBy: string;
33
+ fromApprover: string;
34
+ toApprover: string;
35
+ level: number;
36
+ reason: string;
37
+ }
38
+ interface EscalatedEvent extends ApprovalEvent {
39
+ level: number;
40
+ escalatedTo: string;
41
+ }
42
+ interface CancelledEvent extends ApprovalEvent {
43
+ cancelledBy: string;
44
+ reason: string;
45
+ }
46
+ interface LevelAdvancedEvent extends ApprovalEvent {
47
+ fromLevel: number;
48
+ toLevel: number;
49
+ newApprovers: string[];
50
+ }
51
+ interface ResubmittedEvent extends ApprovalEvent {
52
+ resubmittedBy: string;
53
+ originalInstanceId: string;
54
+ }
55
+ interface OverriddenEvent extends ApprovalEvent {
56
+ overriddenBy: string;
57
+ justification: string;
58
+ }
59
+ interface ExpiredEvent extends ApprovalEvent {
60
+ deadlineAction: 'cancel' | 'reject';
61
+ }
62
+ interface SlaBreachedEvent extends ApprovalEvent {
63
+ slaDeadlineAt: Date;
64
+ }
65
+ interface ApprovalEventMap {
66
+ 'approval:submitted': SubmittedEvent;
67
+ 'approval:approved': ApprovedEvent;
68
+ 'approval:rejected': RejectedEvent;
69
+ 'approval:delegated': DelegatedEvent;
70
+ 'approval:reassigned': ReassignedEvent;
71
+ 'approval:escalated': EscalatedEvent;
72
+ 'approval:cancelled': CancelledEvent;
73
+ 'approval:completed': ApprovalInstance;
74
+ 'approval:level_advanced': LevelAdvancedEvent;
75
+ 'approval:resubmitted': ResubmittedEvent;
76
+ 'approval:overridden': OverriddenEvent;
77
+ 'approval:expired': ExpiredEvent;
78
+ 'approval:sla_breached': SlaBreachedEvent;
79
+ }
80
+ type ApprovalEventName = keyof ApprovalEventMap;
81
+ interface HistoryEntry extends AuditEntry {
82
+ instanceId: string;
83
+ }
84
+
85
+ interface NotificationEvent {
86
+ type: ApprovalEventName;
87
+ instanceId: string;
88
+ documentId: string;
89
+ documentType: string;
90
+ timestamp: Date;
91
+ /** Current-level approver IDs; empty for non-level events (cancelled, expired, etc.). */
92
+ recipients: string[];
93
+ templateName: string;
94
+ tenantId: string;
95
+ payload: ApprovalEventMap[ApprovalEventName];
96
+ }
97
+ interface INotificationAdapter {
98
+ /** Called after every emitted approval event. Must not throw — errors are logged and swallowed. */
99
+ notify(event: NotificationEvent): Promise<void>;
100
+ }
101
+
102
+ export type { ApprovalEvent as A, CancelledEvent as C, DelegatedEvent as D, EscalatedEvent as E, HistoryEntry as H, INotificationAdapter as I, LevelAdvancedEvent as L, NotificationEvent as N, OverriddenEvent as O, ReassignedEvent as R, SlaBreachedEvent as S, ApprovalEventMap as a, ApprovalEventName as b, ApprovedEvent as c, ExpiredEvent as d, RejectedEvent as e, ResubmittedEvent as f, SubmittedEvent as g };
@@ -0,0 +1,62 @@
1
+ import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-D8D7b07N.cjs';
2
+
3
+ declare class ApprovalError extends Error {
4
+ readonly code: string;
5
+ constructor(message: string, code: string);
6
+ toJSON(): {
7
+ code: string;
8
+ message: string;
9
+ name: string;
10
+ };
11
+ toHttpStatus(): number;
12
+ }
13
+ declare class ApprovalNotFoundError extends ApprovalError {
14
+ constructor(resource: string, id: string);
15
+ }
16
+ declare class ApprovalConflictError extends ApprovalError {
17
+ constructor(instanceId: string);
18
+ }
19
+ declare class ApprovalForbiddenError extends ApprovalError {
20
+ constructor(message: string);
21
+ }
22
+ declare class ApprovalValidationError extends ApprovalError {
23
+ readonly cause?: unknown | undefined;
24
+ constructor(message: string, cause?: unknown | undefined);
25
+ }
26
+ declare class ApprovalTemplateNotFoundError extends ApprovalError {
27
+ constructor(name: string);
28
+ }
29
+
30
+ interface AuthorizationContext {
31
+ operation: 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'escalate' | 'override' | 'resubmit' | 'addComment';
32
+ actorId: string;
33
+ instance: Readonly<ApprovalInstance>;
34
+ level?: Readonly<ApprovalLevelInstance>;
35
+ opts: Record<string, unknown>;
36
+ }
37
+ interface IAuthorizationPolicy {
38
+ /**
39
+ * Return undefined to allow the operation.
40
+ * Return a non-empty string to deny — the engine throws ApprovalForbiddenError(message).
41
+ * Throwing ApprovalForbiddenError directly is also permitted.
42
+ */
43
+ authorize(ctx: AuthorizationContext): Promise<string | undefined> | string | undefined;
44
+ }
45
+
46
+ interface OperationContext<T = unknown> {
47
+ operation: string;
48
+ instanceId?: string;
49
+ actorId?: string;
50
+ tenantId: string;
51
+ input: T;
52
+ }
53
+ interface IOperationMiddleware {
54
+ /** Runs after authorization and input validation, before state mutations. */
55
+ before?(ctx: OperationContext): Promise<void> | void;
56
+ /** Runs after successful completion of the operation. */
57
+ after?(ctx: OperationContext, result: ApprovalInstance | void): Promise<void> | void;
58
+ /** Runs when an ApprovalError is thrown. Does not suppress the error. */
59
+ onError?(ctx: OperationContext, error: ApprovalError): Promise<void> | void;
60
+ }
61
+
62
+ export { ApprovalConflictError as A, type IAuthorizationPolicy as I, type OperationContext as O, ApprovalError as a, ApprovalForbiddenError as b, ApprovalNotFoundError as c, ApprovalTemplateNotFoundError as d, ApprovalValidationError as e, type AuthorizationContext as f, type IOperationMiddleware as g };
@@ -0,0 +1,62 @@
1
+ import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-D8D7b07N.js';
2
+
3
+ declare class ApprovalError extends Error {
4
+ readonly code: string;
5
+ constructor(message: string, code: string);
6
+ toJSON(): {
7
+ code: string;
8
+ message: string;
9
+ name: string;
10
+ };
11
+ toHttpStatus(): number;
12
+ }
13
+ declare class ApprovalNotFoundError extends ApprovalError {
14
+ constructor(resource: string, id: string);
15
+ }
16
+ declare class ApprovalConflictError extends ApprovalError {
17
+ constructor(instanceId: string);
18
+ }
19
+ declare class ApprovalForbiddenError extends ApprovalError {
20
+ constructor(message: string);
21
+ }
22
+ declare class ApprovalValidationError extends ApprovalError {
23
+ readonly cause?: unknown | undefined;
24
+ constructor(message: string, cause?: unknown | undefined);
25
+ }
26
+ declare class ApprovalTemplateNotFoundError extends ApprovalError {
27
+ constructor(name: string);
28
+ }
29
+
30
+ interface AuthorizationContext {
31
+ operation: 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'escalate' | 'override' | 'resubmit' | 'addComment';
32
+ actorId: string;
33
+ instance: Readonly<ApprovalInstance>;
34
+ level?: Readonly<ApprovalLevelInstance>;
35
+ opts: Record<string, unknown>;
36
+ }
37
+ interface IAuthorizationPolicy {
38
+ /**
39
+ * Return undefined to allow the operation.
40
+ * Return a non-empty string to deny — the engine throws ApprovalForbiddenError(message).
41
+ * Throwing ApprovalForbiddenError directly is also permitted.
42
+ */
43
+ authorize(ctx: AuthorizationContext): Promise<string | undefined> | string | undefined;
44
+ }
45
+
46
+ interface OperationContext<T = unknown> {
47
+ operation: string;
48
+ instanceId?: string;
49
+ actorId?: string;
50
+ tenantId: string;
51
+ input: T;
52
+ }
53
+ interface IOperationMiddleware {
54
+ /** Runs after authorization and input validation, before state mutations. */
55
+ before?(ctx: OperationContext): Promise<void> | void;
56
+ /** Runs after successful completion of the operation. */
57
+ after?(ctx: OperationContext, result: ApprovalInstance | void): Promise<void> | void;
58
+ /** Runs when an ApprovalError is thrown. Does not suppress the error. */
59
+ onError?(ctx: OperationContext, error: ApprovalError): Promise<void> | void;
60
+ }
61
+
62
+ export { ApprovalConflictError as A, type IAuthorizationPolicy as I, type OperationContext as O, ApprovalError as a, ApprovalForbiddenError as b, ApprovalNotFoundError as c, ApprovalTemplateNotFoundError as d, ApprovalValidationError as e, type AuthorizationContext as f, type IOperationMiddleware as g };
@@ -0,0 +1,47 @@
1
+ import { A as ApprovalTemplate, a as ApprovalInstance, f as ApprovalStatus, b as AuditEntry } from './instance-D8D7b07N.cjs';
2
+
3
+ interface PaginationOpts {
4
+ limit: number;
5
+ offset: number;
6
+ }
7
+ interface PaginatedResult<T> {
8
+ items: T[];
9
+ total: number;
10
+ }
11
+ /** Opaque cursor: base64(updatedAt_iso:id). Use the value from nextCursor/prevCursor. */
12
+ interface CursorPaginationOpts {
13
+ cursor?: string;
14
+ limit: number;
15
+ direction?: 'forward' | 'backward';
16
+ }
17
+ interface CursorPaginatedResult<T> {
18
+ items: T[];
19
+ nextCursor?: string;
20
+ prevCursor?: string;
21
+ hasMore: boolean;
22
+ }
23
+ interface InstanceFilter {
24
+ status?: ApprovalStatus;
25
+ documentType?: string;
26
+ submittedBy?: string;
27
+ fromDate?: Date;
28
+ toDate?: Date;
29
+ }
30
+ interface IStorageAdapter {
31
+ saveTemplate(template: ApprovalTemplate): Promise<void>;
32
+ getTemplate(tenantId: string, name: string): Promise<ApprovalTemplate | null>;
33
+ listTemplates(tenantId: string): Promise<ApprovalTemplate[]>;
34
+ saveInstance(instance: ApprovalInstance): Promise<void>;
35
+ /** Conditional update — throws ApprovalConflictError if stored version !== expectedVersion. */
36
+ updateInstance(instance: ApprovalInstance, expectedVersion: number): Promise<void>;
37
+ getInstance(tenantId: string, id: string): Promise<ApprovalInstance | null>;
38
+ getInstancesByApprover(tenantId: string, approverId: string, opts?: PaginationOpts): Promise<PaginatedResult<ApprovalInstance>>;
39
+ getInstancesByFilter(tenantId: string, filter: InstanceFilter, opts?: PaginationOpts): Promise<PaginatedResult<ApprovalInstance>>;
40
+ /** Optional cursor-based pagination — more efficient than offset at scale. */
41
+ getInstancesByCursor?(tenantId: string, filter: InstanceFilter, opts: CursorPaginationOpts): Promise<CursorPaginatedResult<ApprovalInstance>>;
42
+ getOverdueInstances(tenantId: string, asOf: Date): Promise<ApprovalInstance[]>;
43
+ getIdempotentInstance(tenantId: string, idempotencyKey: string): Promise<ApprovalInstance | null>;
44
+ appendAuditEntry(tenantId: string, instanceId: string, entry: AuditEntry): Promise<void>;
45
+ }
46
+
47
+ export type { CursorPaginationOpts as C, IStorageAdapter as I, PaginationOpts as P, PaginatedResult as a, InstanceFilter as b, CursorPaginatedResult as c };