hierarchical-approval 2.2.0 → 2.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.
- package/CHANGELOG.md +36 -0
- package/README.md +25 -0
- package/dist/{ApprovalEngine-CbFBAMlO.d.cts → ApprovalEngine-C1dUPnLM.d.cts} +45 -2
- package/dist/{ApprovalEngine-B3ChZxS7.d.ts → ApprovalEngine-Ci9urTDI.d.ts} +45 -2
- package/dist/{IStorageAdapter-DjRvHUF0.d.ts → IStorageAdapter-BU3sau5W.d.ts} +14 -0
- package/dist/{IStorageAdapter-Bk7ybd3z.d.cts → IStorageAdapter-DdHO4Rf1.d.cts} +14 -0
- package/dist/adapters/MemoryAdapter.cjs +4 -0
- package/dist/adapters/MemoryAdapter.cjs.map +1 -1
- package/dist/adapters/MemoryAdapter.d.cts +2 -1
- package/dist/adapters/MemoryAdapter.d.ts +2 -1
- package/dist/adapters/MemoryAdapter.js +4 -0
- package/dist/adapters/MemoryAdapter.js.map +1 -1
- package/dist/adapters/PostgresAdapter.cjs +12 -0
- package/dist/adapters/PostgresAdapter.cjs.map +1 -1
- package/dist/adapters/PostgresAdapter.d.cts +2 -1
- package/dist/adapters/PostgresAdapter.d.ts +2 -1
- package/dist/adapters/PostgresAdapter.js +12 -0
- package/dist/adapters/PostgresAdapter.js.map +1 -1
- package/dist/index.cjs +81 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +81 -0
- package/dist/index.js.map +1 -1
- package/dist/nestjs.cjs +77 -0
- package/dist/nestjs.cjs.map +1 -1
- package/dist/nestjs.d.cts +2 -2
- package/dist/nestjs.d.ts +2 -2
- package/dist/nestjs.js +77 -0
- package/dist/nestjs.js.map +1 -1
- package/dist/testing.cjs +81 -0
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +81 -0
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { A as AddCommentOptions, a as ApprovalEngine, b as ApprovalEngineOptions, c as ApprovalStatistics, d as ApproveOptions, e as ApproverResolverFn, f as ApproverWorkload, B as BulkResult, g as BusinessCalendar, C as CanApproveResult, h as CancelOptions, i as ConditionOperatorFn, j as CycleTimeStats, D as DelegateOptions, E as EscalateOptions, H as HealthResult, I as IdGeneratorFn, k as IdempotencyKeyFn, l as ImportResult, O as OrgProvider, m as OutOfOfficeProvider, n as OverrideOptions, P as PreviewChainLevel, o as PreviewResult, p as ProvideInfoOptions, R as ReassignOptions,
|
|
2
|
-
import { I as IStorageAdapter } from './IStorageAdapter-
|
|
3
|
-
export { c as CursorPaginatedResult, C as CursorPaginationOpts, b as InstanceFilter, a as PaginatedResult, P as PaginationOpts } from './IStorageAdapter-
|
|
1
|
+
export { A as AddCommentOptions, a as ApprovalEngine, b as ApprovalEngineOptions, c as ApprovalStatistics, d as ApproveOptions, e as ApproverResolverFn, f as ApproverWorkload, B as BulkResult, g as BusinessCalendar, C as CanApproveResult, h as CancelOptions, i as ConditionOperatorFn, j as CycleTimeStats, D as DelegateOptions, E as EscalateOptions, H as HealthResult, I as IdGeneratorFn, k as IdempotencyKeyFn, l as ImportResult, O as OrgProvider, m as OutOfOfficeProvider, n as OverrideOptions, P as PreviewChainLevel, o as PreviewResult, p as ProvideInfoOptions, q as PurgeResult, R as ReassignOptions, r as RejectOptions, s as RequestInfoOptions, t as ResubmitOptions, u as RetryPolicy, S as SubmitOptions, T as TEMPLATE_BUNDLE_VERSION, v as TemplateBundle, w as TransferResult, U as UpdateDataOptions, V as ValidationResult, W as WeekendCalendarOptions, x as defaultIdGenerator, y as toComparableNumber, z as validateConditionExpression, F as weekendCalendar } from './ApprovalEngine-C1dUPnLM.cjs';
|
|
2
|
+
import { I as IStorageAdapter } from './IStorageAdapter-DdHO4Rf1.cjs';
|
|
3
|
+
export { c as CursorPaginatedResult, C as CursorPaginationOpts, b as InstanceFilter, a as PaginatedResult, P as PaginationOpts } from './IStorageAdapter-DdHO4Rf1.cjs';
|
|
4
4
|
import { L as Logger } from './Logger-BplhlU7l.cjs';
|
|
5
5
|
export { n as noopLogger } from './Logger-BplhlU7l.cjs';
|
|
6
6
|
import { C as Clock } from './Clock-3FnOczFJ.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { A as AddCommentOptions, a as ApprovalEngine, b as ApprovalEngineOptions, c as ApprovalStatistics, d as ApproveOptions, e as ApproverResolverFn, f as ApproverWorkload, B as BulkResult, g as BusinessCalendar, C as CanApproveResult, h as CancelOptions, i as ConditionOperatorFn, j as CycleTimeStats, D as DelegateOptions, E as EscalateOptions, H as HealthResult, I as IdGeneratorFn, k as IdempotencyKeyFn, l as ImportResult, O as OrgProvider, m as OutOfOfficeProvider, n as OverrideOptions, P as PreviewChainLevel, o as PreviewResult, p as ProvideInfoOptions, R as ReassignOptions,
|
|
2
|
-
import { I as IStorageAdapter } from './IStorageAdapter-
|
|
3
|
-
export { c as CursorPaginatedResult, C as CursorPaginationOpts, b as InstanceFilter, a as PaginatedResult, P as PaginationOpts } from './IStorageAdapter-
|
|
1
|
+
export { A as AddCommentOptions, a as ApprovalEngine, b as ApprovalEngineOptions, c as ApprovalStatistics, d as ApproveOptions, e as ApproverResolverFn, f as ApproverWorkload, B as BulkResult, g as BusinessCalendar, C as CanApproveResult, h as CancelOptions, i as ConditionOperatorFn, j as CycleTimeStats, D as DelegateOptions, E as EscalateOptions, H as HealthResult, I as IdGeneratorFn, k as IdempotencyKeyFn, l as ImportResult, O as OrgProvider, m as OutOfOfficeProvider, n as OverrideOptions, P as PreviewChainLevel, o as PreviewResult, p as ProvideInfoOptions, q as PurgeResult, R as ReassignOptions, r as RejectOptions, s as RequestInfoOptions, t as ResubmitOptions, u as RetryPolicy, S as SubmitOptions, T as TEMPLATE_BUNDLE_VERSION, v as TemplateBundle, w as TransferResult, U as UpdateDataOptions, V as ValidationResult, W as WeekendCalendarOptions, x as defaultIdGenerator, y as toComparableNumber, z as validateConditionExpression, F as weekendCalendar } from './ApprovalEngine-Ci9urTDI.js';
|
|
2
|
+
import { I as IStorageAdapter } from './IStorageAdapter-BU3sau5W.js';
|
|
3
|
+
export { c as CursorPaginatedResult, C as CursorPaginationOpts, b as InstanceFilter, a as PaginatedResult, P as PaginationOpts } from './IStorageAdapter-BU3sau5W.js';
|
|
4
4
|
import { L as Logger } from './Logger-BplhlU7l.js';
|
|
5
5
|
export { n as noopLogger } from './Logger-BplhlU7l.js';
|
|
6
6
|
import { C as Clock } from './Clock-3FnOczFJ.js';
|
package/dist/index.js
CHANGED
|
@@ -909,6 +909,7 @@ function computeTimingStats(samples) {
|
|
|
909
909
|
|
|
910
910
|
// src/engine/ApprovalEngine.ts
|
|
911
911
|
var MAX_SUBWORKFLOW_DEPTH = 5;
|
|
912
|
+
var DEFAULT_PURGE_LIMIT = 1e3;
|
|
912
913
|
var DEFAULT_MAX_REMINDERS = 3;
|
|
913
914
|
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
914
915
|
var DEFAULT_BASE_DELAY_MS = 50;
|
|
@@ -3114,6 +3115,82 @@ var ApprovalEngine = class _ApprovalEngine {
|
|
|
3114
3115
|
});
|
|
3115
3116
|
return result;
|
|
3116
3117
|
}
|
|
3118
|
+
/**
|
|
3119
|
+
* Permanently remove finished approvals older than a cut-off.
|
|
3120
|
+
*
|
|
3121
|
+
* Approval tables only grow, and data-minimisation rules eventually require
|
|
3122
|
+
* old records to go. There was no way to remove one, so operators reached
|
|
3123
|
+
* around the library and deleted rows directly — which is exactly where
|
|
3124
|
+
* orphaned audit rows and half-deleted instances come from.
|
|
3125
|
+
*
|
|
3126
|
+
* **Only terminal instances are eligible.** A pending approval is live work;
|
|
3127
|
+
* deleting one would strand a document with no way to finish and no record of
|
|
3128
|
+
* why. Passing a non-terminal status is rejected rather than quietly ignored,
|
|
3129
|
+
* because a caller who asked to purge pending work has misunderstood
|
|
3130
|
+
* something and should hear about it.
|
|
3131
|
+
*
|
|
3132
|
+
* This is irreversible and removes the audit trail with the instance. In many
|
|
3133
|
+
* deployments that trail *is* the compliance record, which is why the
|
|
3134
|
+
* underlying `deleteInstance` is an optional adapter method: an adapter that
|
|
3135
|
+
* does not implement it makes the whole operation unavailable, and this
|
|
3136
|
+
* throws rather than reporting a successful purge of nothing.
|
|
3137
|
+
*
|
|
3138
|
+
* @param opts - Cut-off, optional status/type scoping, safety limit, dry run.
|
|
3139
|
+
* @returns What was removed, or would be under `dryRun`.
|
|
3140
|
+
*/
|
|
3141
|
+
async purgeInstances(opts) {
|
|
3142
|
+
const dryRun = opts.dryRun ?? false;
|
|
3143
|
+
const limit = opts.limit ?? DEFAULT_PURGE_LIMIT;
|
|
3144
|
+
if (!(opts.olderThan instanceof Date) || Number.isNaN(opts.olderThan.getTime())) {
|
|
3145
|
+
throw new ApprovalValidationError("purgeInstances requires a valid olderThan date.");
|
|
3146
|
+
}
|
|
3147
|
+
const requested = opts.statuses ?? [...TERMINAL_STATUSES];
|
|
3148
|
+
const nonTerminal = requested.filter((st) => !TERMINAL_STATUSES.has(st));
|
|
3149
|
+
if (nonTerminal.length > 0) {
|
|
3150
|
+
throw new ApprovalValidationError(
|
|
3151
|
+
`purgeInstances refuses non-terminal statuses (${nonTerminal.join(", ")}): a pending approval is live work, and removing it would strand the document it belongs to.`
|
|
3152
|
+
);
|
|
3153
|
+
}
|
|
3154
|
+
const deleteInstance = this.opts.adapter.deleteInstance?.bind(this.opts.adapter);
|
|
3155
|
+
if (!deleteInstance && !dryRun) {
|
|
3156
|
+
throw new ApprovalValidationError(
|
|
3157
|
+
"The configured storage adapter does not implement deleteInstance(), so instances cannot be purged."
|
|
3158
|
+
);
|
|
3159
|
+
}
|
|
3160
|
+
const result = { purged: [], scanned: 0, dryRun };
|
|
3161
|
+
for (const status of requested) {
|
|
3162
|
+
if (result.purged.length >= limit) break;
|
|
3163
|
+
const page = await this.opts.adapter.getInstancesByFilter(
|
|
3164
|
+
this.tenantId,
|
|
3165
|
+
{
|
|
3166
|
+
status,
|
|
3167
|
+
toDate: opts.olderThan,
|
|
3168
|
+
...opts.documentType ? { documentType: opts.documentType } : {}
|
|
3169
|
+
},
|
|
3170
|
+
{ limit, offset: 0 }
|
|
3171
|
+
);
|
|
3172
|
+
for (const instance of page.items) {
|
|
3173
|
+
if (result.purged.length >= limit) break;
|
|
3174
|
+
result.scanned++;
|
|
3175
|
+
if (!TERMINAL_STATUSES.has(instance.status)) continue;
|
|
3176
|
+
if (new Date(instance.createdAt) > opts.olderThan) continue;
|
|
3177
|
+
if (!dryRun) await deleteInstance(this.tenantId, instance.id);
|
|
3178
|
+
result.purged.push({
|
|
3179
|
+
instanceId: instance.id,
|
|
3180
|
+
documentId: instance.documentId,
|
|
3181
|
+
status: instance.status
|
|
3182
|
+
});
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
this.logger.info("purgeInstances: sweep complete", {
|
|
3186
|
+
tenantId: this.tenantId,
|
|
3187
|
+
olderThan: opts.olderThan.toISOString(),
|
|
3188
|
+
scanned: result.scanned,
|
|
3189
|
+
purged: result.purged.length,
|
|
3190
|
+
dryRun
|
|
3191
|
+
});
|
|
3192
|
+
return result;
|
|
3193
|
+
}
|
|
3117
3194
|
async getStatistics(filter = {}) {
|
|
3118
3195
|
const statuses = [
|
|
3119
3196
|
"pending",
|
|
@@ -4116,6 +4193,10 @@ var MemoryAdapter = class {
|
|
|
4116
4193
|
return hasOverdueEscalation || isExpired || hasSLABreach || hasDelegationExpiry || hasDueReminder;
|
|
4117
4194
|
}).map((i) => reviveDates(deepClone(i)));
|
|
4118
4195
|
}
|
|
4196
|
+
async deleteInstance(tenantId, id) {
|
|
4197
|
+
const key = `${tenantId}:${id}`;
|
|
4198
|
+
return this.instances.delete(key);
|
|
4199
|
+
}
|
|
4119
4200
|
async countInstances(tenantId, filter) {
|
|
4120
4201
|
let count = 0;
|
|
4121
4202
|
for (const instance of this.instances.values()) {
|