d0523fcc2d
- P0: CLI verify now honors test budget with seeded multi-sample - P0: Observe sampling enforced via Math.random() gate in hook-validator - P1: Remove misleading undici-mock-agent isolation option - P1: Qualify reuses shared discoverRouteDetails() with warnings - P1: Chaos/scenario config exposed via preset schema - P1: README/docs limitations updated to current state - P2: Nested response annotations prefer 2xx deterministically - P2: --changed documented as heuristic in verify.md - Add observe sink tests (sampling 0/1, sink failure non-interference) - Add verify runs regression tests (scale, determinism, variants) - Add configured-scenario qualify test (independent of OAuth fixture) - Add coverageBreakdown to qualify artifacts (per-gate route coverage) - Add production-style observe example with real sink in docs/observe.md - Add nightly/staging vs PR gating guidance to docs/qualify.md - Enrich VerifyFailure with formula-aware diagnostics: status:201 => 'HTTP 200', body field checks => actual values - Remove stale observe CLI activation message - Document outbound mocks as process-global in getting-started.md - Refresh APOPHIS_ADOPTION_AUDIT.md with current state 903 tests pass, build clean, typecheck clean.
40 lines
975 B
TypeScript
40 lines
975 B
TypeScript
/**
|
|
* Hook Timeout Utility
|
|
*
|
|
* Wraps async operations with a timeout to prevent indefinite hangs.
|
|
*/
|
|
|
|
class HookTimeoutError extends Error {
|
|
constructor(extensionName: string, hookName: string, timeoutMs: number) {
|
|
super(
|
|
`Extension '${extensionName}' ${hookName} timed out after ${timeoutMs}ms. ` +
|
|
`Consider increasing hookTimeoutMs or investigating the extension for blocking operations.`
|
|
)
|
|
this.name = 'HookTimeoutError'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wrap a promise with a timeout.
|
|
* @returns Promise that rejects with HookTimeoutError if deadline exceeded
|
|
*/
|
|
export function withTimeout<T>(
|
|
promise: Promise<T>,
|
|
timeoutMs: number,
|
|
extensionName: string,
|
|
hookName: string
|
|
): Promise<T> {
|
|
if (timeoutMs <= 0) {
|
|
return promise
|
|
}
|
|
|
|
return Promise.race([
|
|
promise,
|
|
new Promise<never>((_, reject) => {
|
|
setTimeout(() => {
|
|
reject(new HookTimeoutError(extensionName, hookName, timeoutMs))
|
|
}, timeoutMs)
|
|
}),
|
|
])
|
|
}
|