hierarchical-approval 2.1.0 → 2.2.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 +37 -0
- package/README.md +26 -0
- package/dist/{ApprovalEngine-CJwnpnpL.d.ts → ApprovalEngine-B3ChZxS7.d.ts} +57 -1
- package/dist/{ApprovalEngine-DqRIadYg.d.cts → ApprovalEngine-CbFBAMlO.d.cts} +57 -1
- package/dist/index.cjs +114 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +114 -1
- package/dist/index.js.map +1 -1
- package/dist/nestjs.cjs +113 -0
- package/dist/nestjs.cjs.map +1 -1
- package/dist/nestjs.d.cts +1 -1
- package/dist/nestjs.d.ts +1 -1
- package/dist/nestjs.js +113 -0
- package/dist/nestjs.js.map +1 -1
- package/dist/testing.cjs +113 -0
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +113 -0
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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, O as OrgProvider,
|
|
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, q as RejectOptions, r as RequestInfoOptions, s as ResubmitOptions, t as RetryPolicy, S as SubmitOptions, T as TEMPLATE_BUNDLE_VERSION, u as TemplateBundle, v as TransferResult, U as UpdateDataOptions, V as ValidationResult, W as WeekendCalendarOptions, w as defaultIdGenerator, x as toComparableNumber, y as validateConditionExpression, z as weekendCalendar } from './ApprovalEngine-CbFBAMlO.cjs';
|
|
2
2
|
import { I as IStorageAdapter } from './IStorageAdapter-Bk7ybd3z.cjs';
|
|
3
3
|
export { c as CursorPaginatedResult, C as CursorPaginationOpts, b as InstanceFilter, a as PaginatedResult, P as PaginationOpts } from './IStorageAdapter-Bk7ybd3z.cjs';
|
|
4
4
|
import { L as Logger } from './Logger-BplhlU7l.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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, O as OrgProvider,
|
|
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, q as RejectOptions, r as RequestInfoOptions, s as ResubmitOptions, t as RetryPolicy, S as SubmitOptions, T as TEMPLATE_BUNDLE_VERSION, u as TemplateBundle, v as TransferResult, U as UpdateDataOptions, V as ValidationResult, W as WeekendCalendarOptions, w as defaultIdGenerator, x as toComparableNumber, y as validateConditionExpression, z as weekendCalendar } from './ApprovalEngine-B3ChZxS7.js';
|
|
2
2
|
import { I as IStorageAdapter } from './IStorageAdapter-DjRvHUF0.js';
|
|
3
3
|
export { c as CursorPaginatedResult, C as CursorPaginationOpts, b as InstanceFilter, a as PaginatedResult, P as PaginationOpts } from './IStorageAdapter-DjRvHUF0.js';
|
|
4
4
|
import { L as Logger } from './Logger-BplhlU7l.js';
|
package/dist/index.js
CHANGED
|
@@ -920,6 +920,7 @@ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
|
920
920
|
]);
|
|
921
921
|
var CYCLE_TIME_STATUSES = ["approved", "rejected", "cancelled"];
|
|
922
922
|
var CYCLE_TIME_FETCH_BATCH_SIZE = 500;
|
|
923
|
+
var TEMPLATE_BUNDLE_VERSION = 1;
|
|
923
924
|
var ApprovalEngine = class _ApprovalEngine {
|
|
924
925
|
constructor(opts) {
|
|
925
926
|
this.opts = opts;
|
|
@@ -3001,6 +3002,118 @@ var ApprovalEngine = class _ApprovalEngine {
|
|
|
3001
3002
|
oldestAgeMs: Number.isFinite(row.oldest) ? now.getTime() - row.oldest : 0
|
|
3002
3003
|
})).sort((a, b) => b.pending - a.pending || a.approverId.localeCompare(b.approverId));
|
|
3003
3004
|
}
|
|
3005
|
+
/**
|
|
3006
|
+
* Export templates as a portable bundle.
|
|
3007
|
+
*
|
|
3008
|
+
* Approval configuration is written once and then has to travel — authored in
|
|
3009
|
+
* a sandbox, reviewed, promoted to production. Reading `listTemplates()` and
|
|
3010
|
+
* re-posting the rows carried each environment's own `id`, `tenantId` and
|
|
3011
|
+
* version lineage with it, which either collided on arrival or silently
|
|
3012
|
+
* claimed a history the target never had. This strips all of it.
|
|
3013
|
+
*
|
|
3014
|
+
* @param names - Templates to include; omit for all of them.
|
|
3015
|
+
*/
|
|
3016
|
+
async exportTemplates(names) {
|
|
3017
|
+
const all = await this.registry.list();
|
|
3018
|
+
const wanted = names ? all.filter((t) => names.includes(t.name)) : all;
|
|
3019
|
+
if (names) {
|
|
3020
|
+
const missing = names.filter((n) => !all.some((t) => t.name === n));
|
|
3021
|
+
if (missing.length > 0) {
|
|
3022
|
+
throw new ApprovalTemplateNotFoundError(missing.join(", "));
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
return {
|
|
3026
|
+
bundleVersion: TEMPLATE_BUNDLE_VERSION,
|
|
3027
|
+
exportedAt: this.clock.now(),
|
|
3028
|
+
templates: wanted.map((t) => {
|
|
3029
|
+
const {
|
|
3030
|
+
id: _id,
|
|
3031
|
+
tenantId: _tenantId,
|
|
3032
|
+
createdAt: _createdAt,
|
|
3033
|
+
version: _version,
|
|
3034
|
+
previousVersionId: _previousVersionId,
|
|
3035
|
+
...config
|
|
3036
|
+
} = t;
|
|
3037
|
+
return config;
|
|
3038
|
+
})
|
|
3039
|
+
};
|
|
3040
|
+
}
|
|
3041
|
+
/**
|
|
3042
|
+
* Import a bundle produced by {@link exportTemplates}.
|
|
3043
|
+
*
|
|
3044
|
+
* **Every template is validated before any is written.** A bundle that is
|
|
3045
|
+
* half-applied is worse than one rejected outright: the tenant is left in a
|
|
3046
|
+
* state matching neither environment, and the operator has no way to tell
|
|
3047
|
+
* which half landed. Per-template failures during the write phase are still
|
|
3048
|
+
* reported individually, since a storage error can occur after validation
|
|
3049
|
+
* passes.
|
|
3050
|
+
*
|
|
3051
|
+
* @param bundle - The bundle to apply.
|
|
3052
|
+
* @param opts - `mode: 'create'` (default) refuses to touch existing
|
|
3053
|
+
* templates; `'upsert'` updates them. `dryRun` reports without writing.
|
|
3054
|
+
*/
|
|
3055
|
+
async importTemplates(bundle, opts = {}) {
|
|
3056
|
+
const mode = opts.mode ?? "create";
|
|
3057
|
+
const dryRun = opts.dryRun ?? false;
|
|
3058
|
+
if (bundle.bundleVersion !== TEMPLATE_BUNDLE_VERSION) {
|
|
3059
|
+
throw new ApprovalValidationError(
|
|
3060
|
+
`Unsupported template bundle version ${bundle.bundleVersion}; this engine reads version ${TEMPLATE_BUNDLE_VERSION}.`
|
|
3061
|
+
);
|
|
3062
|
+
}
|
|
3063
|
+
if (!Array.isArray(bundle.templates) || bundle.templates.length === 0) {
|
|
3064
|
+
throw new ApprovalValidationError("Template bundle contains no templates.");
|
|
3065
|
+
}
|
|
3066
|
+
const duplicates = bundle.templates.map((t) => t.name).filter((name, i, all) => all.indexOf(name) !== i);
|
|
3067
|
+
if (duplicates.length > 0) {
|
|
3068
|
+
throw new ApprovalValidationError(
|
|
3069
|
+
`Template bundle contains duplicate names: ${[...new Set(duplicates)].join(", ")}.`
|
|
3070
|
+
);
|
|
3071
|
+
}
|
|
3072
|
+
const invalid = [];
|
|
3073
|
+
for (const config of bundle.templates) {
|
|
3074
|
+
const result2 = this.validateTemplate(config);
|
|
3075
|
+
if (!result2.valid) {
|
|
3076
|
+
invalid.push({
|
|
3077
|
+
name: config.name,
|
|
3078
|
+
message: result2.errors[0]?.message ?? "unknown validation error"
|
|
3079
|
+
});
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
if (invalid.length > 0) {
|
|
3083
|
+
throw new ApprovalValidationError(
|
|
3084
|
+
`Template bundle failed validation and was not applied: ${invalid.map((e) => `${e.name}: ${e.message}`).join("; ")}`
|
|
3085
|
+
);
|
|
3086
|
+
}
|
|
3087
|
+
const result = { created: [], updated: [], skipped: [], errors: [], dryRun };
|
|
3088
|
+
for (const config of bundle.templates) {
|
|
3089
|
+
const existing = await this.opts.adapter.getTemplate(this.tenantId, config.name);
|
|
3090
|
+
try {
|
|
3091
|
+
if (existing && mode === "create") {
|
|
3092
|
+
result.skipped.push(config.name);
|
|
3093
|
+
continue;
|
|
3094
|
+
}
|
|
3095
|
+
if (existing) {
|
|
3096
|
+
if (!dryRun) await this.registry.update(config);
|
|
3097
|
+
result.updated.push(config.name);
|
|
3098
|
+
} else {
|
|
3099
|
+
if (!dryRun) await this.registry.define(config);
|
|
3100
|
+
result.created.push(config.name);
|
|
3101
|
+
}
|
|
3102
|
+
} catch (err) {
|
|
3103
|
+
result.errors.push({ name: config.name, message: err.message });
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
this.logger.info("importTemplates: bundle applied", {
|
|
3107
|
+
tenantId: this.tenantId,
|
|
3108
|
+
mode,
|
|
3109
|
+
dryRun,
|
|
3110
|
+
created: result.created.length,
|
|
3111
|
+
updated: result.updated.length,
|
|
3112
|
+
skipped: result.skipped.length,
|
|
3113
|
+
errors: result.errors.length
|
|
3114
|
+
});
|
|
3115
|
+
return result;
|
|
3116
|
+
}
|
|
3004
3117
|
async getStatistics(filter = {}) {
|
|
3005
3118
|
const statuses = [
|
|
3006
3119
|
"pending",
|
|
@@ -4091,6 +4204,6 @@ function weekendCalendar(options = {}) {
|
|
|
4091
4204
|
};
|
|
4092
4205
|
}
|
|
4093
4206
|
|
|
4094
|
-
export { ApprovalConflictError, ApprovalEngine, ApprovalError, ApprovalForbiddenError, ApprovalNotFoundError, ApprovalTemplateNotFoundError, ApprovalValidationError, EscalationScheduler, MemoryAdapter, defaultIdGenerator, noopLogger, systemClock, toComparableNumber, validateConditionExpression, weekendCalendar };
|
|
4207
|
+
export { ApprovalConflictError, ApprovalEngine, ApprovalError, ApprovalForbiddenError, ApprovalNotFoundError, ApprovalTemplateNotFoundError, ApprovalValidationError, EscalationScheduler, MemoryAdapter, TEMPLATE_BUNDLE_VERSION, defaultIdGenerator, noopLogger, systemClock, toComparableNumber, validateConditionExpression, weekendCalendar };
|
|
4095
4208
|
//# sourceMappingURL=index.js.map
|
|
4096
4209
|
//# sourceMappingURL=index.js.map
|