Files
iios/packages/iios-service/src/adapters/adapter.registry.ts
T
maaz519 29b64c3c4e feat(service): P5.3 inbound adapter pipeline (ACK-fast webhook + RawEventProjector) + traceId
POST /v1/adapters/:type/webhook verifies HMAC (fail-closed) -> stores raw ->
emits raw.received -> 202. RawEventProjector consumes it off the relay, normalizes
via the adapter, reuses IngestService (traceId threaded raw->interaction).
Deduped on (channelType, externalEventId). rawBody enabled. 48 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 13:44:23 +05:30

43 lines
1.4 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import type { ScopeVector } from '@insignia/iios-contracts';
import { WebhookAdapter, type ChannelAdapter } from '@insignia/iios-adapter-sdk';
export interface AdapterConfig {
secret: string;
scope: ScopeVector;
}
/**
* Registers channel adapters + their per-channel config (secret + scope). In P5
* one reference WebhookAdapter backs several channelTypes (WEBHOOK/EMAIL/WHATSAPP)
* so the fixtures exercise the same anti-corruption pipeline. Secrets come from
* ADAPTER_SECRETS (JSON map); scope defaults to the demo scope.
*/
@Injectable()
export class AdapterRegistry {
private readonly adapters = new Map<string, { adapter: ChannelAdapter; config: AdapterConfig }>();
constructor() {
let secrets: Record<string, string> = {};
try {
secrets = JSON.parse(process.env.ADAPTER_SECRETS ?? '{}');
} catch {
secrets = {};
}
const scope: ScopeVector = {
orgId: process.env.ADAPTER_ORG ?? 'org_portal-demo',
appId: process.env.ADAPTER_APP ?? 'portal-demo',
};
for (const channelType of ['WEBHOOK', 'EMAIL', 'WHATSAPP']) {
this.adapters.set(channelType, {
adapter: new WebhookAdapter(channelType),
config: { secret: secrets[channelType] ?? 'dev-adapter-secret', scope },
});
}
}
get(channelType: string): { adapter: ChannelAdapter; config: AdapterConfig } | undefined {
return this.adapters.get(channelType);
}
}