Hooks Overview
EdgeStream hooks are composable, priority-ordered message processors that intercept the pipeline at defined stages. There are six hook types — each fires at a specific moment in the message lifecycle.
The Six Hook Types
| Hook Type | Default Priority | When It Fires | Can Abort? |
|---|---|---|---|
NormalizationHook | 110 | After security, before processing | No (non-fatal) |
| Pre-Pipeline Hooks | 120–199 | After normalization, before processing | Yes |
| Processing Hooks | 200–299 | Core transformation stage | Yes |
| Post-Pipeline Hooks | 300+ | After processing, before delivery | Discouraged |
HookActivityLogger | 5 | First — captures timing for all hooks | No |
| Incoming/Outgoing Hooks | Any | Incoming: transport→app; Outgoing: app→transport | Yes |
Hook Interface
All hooks implement IHook. The priority field determines execution order within a pipeline — lower number executes first.
export interface IHook<TContext extends IPipelineContext = IPipelineContext> {
readonly name: string; // display name for logging + HooksMonitor
readonly priority: number; // lower = runs first
execute(context: TContext): Promise<HookResult>;
}
export interface HookResult {
continue: boolean; // false = abort pipeline (message dropped)
paused?: boolean; // true = pipeline paused for user input
error?: string; // error message for observability
}
Hook Type Reference
NormalizationHook
Converts raw message body to CloudEvents format. Runs at priority 110. Optional — normalization failure is non-fatal. Never modifies business data.
Pre-Pipeline (120–199)
Enrichment, routing decisions, rate limiting, deduplication. Runs on normalized envelope. Can abort pipeline cleanly.
Processing (200–299)
Content transformation, business logic, HIL pause. Where the core message handling happens.
Post-Pipeline (300+)
Audit logging, metrics emission, acknowledgment, caching. Runs after processing, before subscriber delivery.
HookActivityLogger
Priority 5 — runs before all others. Captures start/success/error/skip events with timing. Feeds HooksMonitor React component.
Incoming / Outgoing
Transport-level interceptors. Incoming fires when raw bytes arrive. Outgoing fires when send() is called. Used for signing, compression, auth headers.
Built-in Hook Types (Interfaces Only)
EdgeStream defines interface types for common hook patterns. These are contracts you implement — not built-in implementations (except NormalizationHook and HookActivityLogger):
| Interface | Name Constant | Purpose |
|---|---|---|
ILogHook | 'LogHook' | Logging/diagnostics hook |
IFilterHook | 'FilterHook' | Predicate-based message filtering |
IValidationHook | 'ValidationHook' | Schema validation, abort on failure |
IDecryptHook | 'DecryptHook' | Decrypt encrypted message body |
IVerifySignatureHook | 'VerifySignatureHook' | HMAC/signature verification |
IAcknowledgeHook | 'AcknowledgeHook' | Send ACK to message broker |
IRenderToFormHook | 'RenderToFormHook' | Render form, pause for user input |
IPublishToSubscribersHook | 'PublishToSubscribersHook' | Terminal hook — deliver to subscribers |
ISignMessageHook | 'SignMessageHook' | Sign outgoing messages |
IEncryptMessageHook | 'EncryptMessageHook' | Encrypt outgoing messages |
IRetryHook | 'RetryHook' | Retry failed message sends |
IUiQueryHook | 'UiQueryHook' | Query UI, await user response |
Hook Registration
import { createEdgeStream, NormalizationHook } from 'edge-stream-js';
import { HookActivityLogger } from 'observability-hooks-js';
const stream = createEdgeStream();
stream.registerServer({ id: 'bas', ... });
const server = stream.server('bas')!;
// Add to incoming pipeline — hooks are sorted by priority automatically
server.incomingPipeline.addHook(new HookActivityLogger()); // priority 5
server.incomingPipeline.addHook(new NormalizationHook()); // priority 110
server.incomingPipeline.addHook(new TenantFilterHook()); // priority 130
server.incomingPipeline.addHook(new AuditLogHook()); // priority 300
// Add to outgoing pipeline
server.outgoingPipeline.addHook(new SignMessageHook()); // priority 50
edgeStream.start(). Adding hooks after start is technically possible but may cause race conditions on high-throughput servers.