All matches and the first handled result
The policy implementation follows.
ts
export function definePolicySet<Input, Kind extends string>(
definitions: readonly PolicyDefinition<Input, Kind>[],
) {
const catalog = registerPolicies(definitions, 'when');
return Object.freeze({
...readonlyCatalog(catalog, (id) => new TypeError(`Unknown policy: ${id}`)),
assess(input: Input) {
const matched = catalog.filter((policy) => booleanMatch(policy.when(input)));
return {
required: matched.length > 0,
reasons: matched.map((policy) => policy.id),
kinds: [...new Set(matched.map((policy) => policy.kind))],
};
},
});
}
export function defineRecoveryChain<Input, Result>(
definitions: readonly RecoveryDefinition<Input, Result>[],
) {
const catalog = registerPolicies(definitions, 'tryRecover').map((definition) => {
return Object.freeze({
id: definition.id,
description: definition.description,
tryRecover(input: Input): RecoveryResult<Result> {
const value = synchronous(
definition.tryRecover(input),
'Recovery handlers must be synchronous',
);
const result = value as RecoveryResult<Result>;
if (
!result ||
typeof result !== 'object' ||
typeof result.handled !== 'boolean' ||
(result.handled && !('value' in result))
)
throw new TypeError('Invalid recovery outcome');
return result;
},
});
});
const tryRecover = (
input: Input,
execution: Partial<import('../structs/common.js').ExecutionContext> = {},
): RecoveryResult<Result> => {
for (const policy of catalog) {
const result = nativeSubFlowSync(execution, 'recovery', policy.id, () =>
policy.tryRecover(input),
);
if (result.handled) return result;
}
return { handled: false };
};
return Object.freeze({
...readonlyCatalog(catalog, (id) => new TypeError(`Unknown recovery policy: ${id}`)),
tryRecover,
});
}