Portal Community

The Six Hook Types

Hook TypeDefault PriorityWhen It FiresCan Abort?
NormalizationHook110After security, before processingNo (non-fatal)
Pre-Pipeline Hooks120–199After normalization, before processingYes
Processing Hooks200–299Core transformation stageYes
Post-Pipeline Hooks300+After processing, before deliveryDiscouraged
HookActivityLogger5First — captures timing for all hooksNo
Incoming/Outgoing HooksAnyIncoming: transport→app; Outgoing: app→transportYes

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):

InterfaceName ConstantPurpose
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
Hooks Must Be Registered Before start() All hooks should be added to the pipeline before calling edgeStream.start(). Adding hooks after start is technically possible but may cause race conditions on high-throughput servers.