Skip to main content

Type Reference

All TypeScript types exported from @elcto/api.

Configuration

ApiClientConfig

The config-first object that every transport (apiRequest, graphqlRequest, gql, createWebSocket, useWebSocket) and every route helper takes as its first argument. The library itself reads no environment variables.

interface ApiClientConfig {
/** Base URL of the Heimdall API, e.g. "http://localhost:3000" (NO trailing /v1). */
baseUrl: string;
/** WebSocket URL, e.g. "ws://localhost:3000/v1/ws". Optional; derived from baseUrl if absent. */
wsUrl?: string;
/** System API key for service-to-service / SSR calls. Optional. */
systemApiKey?: string;
}

Each app builds this from its own src/lib/config.ts (which resolves HEIMDALL_* → NEXT_PUBLIC_* → localhost default) and exposes a getApiConfig() helper via @/lib/api:

// platform/<app>/src/lib/api/index.ts
import type { ApiClientConfig } from "@elcto/api";
import { getApiUrl, getWsUrl, getSystemApiKey } from "@/lib/config";

export function getApiConfig(): ApiClientConfig {
return {
baseUrl: getApiUrl(),
wsUrl: getWsUrl(),
systemApiKey: getSystemApiKey() || undefined,
};
}

Then pass getApiConfig() as the first argument everywhere:

import { getApiConfig, gql } from "@/lib/api";

const data = await gql<{ user: User }>(getApiConfig(), query, { id: "123" });

REST Types

ApiResponse

Response wrapper for REST API calls.

interface ApiResponse<T> {
data?: T;
error?: string;
status: number;
}

ApiRequestOptions

Options for REST API requests.

interface ApiRequestOptions {
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
body?: unknown;
headers?: Record<string, string>;
/** Override auth - use specific token instead of config.systemApiKey */
accessToken?: string;
/** Original User-Agent from the client browser (forwarded as X-Original-User-Agent) */
userAgent?: string;
/** Original IP address from the client (forwarded as X-Forwarded-For) */
clientIp?: string;
/** Source service making the request (e.g., "id", "backend"). Sent as X-Source-Service header. */
sourceService?: string;
}

GraphQL Types

GraphQLResponse

Response wrapper for GraphQL queries.

interface GraphQLResponse<T> {
data?: T;
errors?: Array<{ message: string; path?: string[] }>;
}

GraphQLRequestOptions

Options for GraphQL requests.

interface GraphQLRequestOptions {
/** OAuth access token for user context */
accessToken?: string;
/** Custom headers */
headers?: Record<string, string>;
/** Original User-Agent from the client browser (forwarded as X-Original-User-Agent) */
userAgent?: string;
/** Original IP address from the client (forwarded as X-Forwarded-For) */
clientIp?: string;
/** Source service making the request (e.g., "id", "backend"). Sent as X-Source-Service header. */
sourceService?: string;
/** User ID from the authenticated session (sent as X-User-Id for audit logging) */
userId?: string;
}

WebSocket Types

WebSocketConfig

Configuration for WebSocket connections.

interface WebSocketConfig {
accessToken?: string;
autoReconnect?: boolean;
reconnectDelay?: number;
maxReconnectAttempts?: number;
}

WebSocketClient

WebSocket client interface.

interface WebSocketClient {
socket: WebSocket;
send: (data: unknown) => boolean;
readonly isOpen: boolean;
close: () => void;
onOpen: (handler: () => void) => void;
onMessage: (handler: WebSocketMessageHandler) => void;
onError: (handler: WebSocketErrorHandler) => void;
onClose: (handler: WebSocketCloseHandler) => void;
}

Handler Types

type WebSocketMessageHandler = (data: unknown) => void;
type WebSocketErrorHandler = (error: Event) => void;
type WebSocketCloseHandler = (event: CloseEvent) => void;

Server Message Types

// User status
type UserStatusMessageType = "accountDeleted" | "accountBanned" | "sessionRevoked" | "forceLogout";
type UserStatusMessage = AccountDeletedMessage | AccountBannedMessage | SessionRevokedMessage | ForceLogoutMessage;

// Permissions
type PermissionMessageType = "rolesUpdated" | "permissionsUpdated" | "rolePermissionsChanged";
type PermissionMessage = RolesUpdatedMessage | PermissionsUpdatedMessage | RolePermissionsChangedMessage;

// Account linking
type AccountLinkMessageType = "emailLinkVerified" | "emailChangeVerified";
type AccountLinkMessage = EmailLinkVerifiedMessage | EmailChangeVerifiedMessage;

// OAuth consent
type OAuthConsentRevokedMessage = { type: "oAuthConsentRevoked"; /* ... */ };

// GPS / AIS / geofence
type GpsMessage = GpsUpdateMessage | VesselsUpdateMessage | GeofenceEventMessage;

// All server messages
type ServerMessage =
| UserStatusMessage
| PermissionMessage
| AccountLinkMessage
| OAuthConsentRevokedMessage
| GpsMessage;
note

ServerMessage and OAuthConsentRevokedMessage are exported from @elcto/api. The GPS variants (GpsMessage, GpsUpdateMessage, VesselsUpdateMessage, GeofenceEventMessage) are not exported as standalone names — narrow them out of the ServerMessage union by switching on the type discriminator.

User Types

UserProfile

User profile information.

interface UserProfile {
name: string | null;
picture: string | null;
provider: string | null;
primary_provider: string | null;
last_login_at: string | null;
created_at: string | null;
}

UserPermissions

User permissions and roles.

interface UserPermissions {
/** Role names (e.g., "Admin", "Developer") - for display */
roles: string[];
/** Role IDs (e.g., "role_admin", "role_developer") - for programmatic checks */
role_ids: string[];
permissions: string[];
is_super_admin: boolean;
}
tip

Use role_ids instead of roles for programmatic role checks. Role IDs are immutable and won't change if role names are renamed.

PlatformAccount

Connected platform account.

interface PlatformAccount {
id: string;
platform_id: string;
platform_name: string;
platform_slug: string;
is_oauth: boolean;
is_primary: boolean;
username: string;
email: string | null;
avatar_url: string | null;
created_at: string;
}

ActiveSession

Active login session information.

interface ActiveSession {
id: string;
ipAddress: string | null;
userAgent: string | null;
deviceType: string | null;
browserName: string | null;
osName: string | null;
/** Auth provider slug used for this session (twitch, discord, email, etc.) */
provider: string | null;
/** Auth provider display name (Twitch, Discord, Email, etc.) */
providerName: string | null;
lastActivityAt: string | null;
createdAt: string;
expiresAt: string;
isCurrent: boolean;
}

ActiveSessionsResponse

Response from active sessions API.

interface ActiveSessionsResponse {
sessions: ActiveSession[];
currentSessionId: string | null;
}

RevokeSessionResponse

Response from revoking a single session.

interface RevokeSessionResponse {
success: boolean;
message: string;
}

RevokeAllSessionsResponse

Response from revoking all other sessions.

interface RevokeAllSessionsResponse {
success: boolean;
revokedCount: number;
message: string;
}

Audit Types

AuditEvent

Audit event record from the activity log.

interface AuditUser {
id: string;
username?: string;
avatarUrl?: string;
}

interface AuditEvent {
id: string;
/** Heimdall user ID, external service user ID, or null for system events */
userId?: string | null;
eventType: string;
resourceType?: string;
resourceId?: string;
actorId?: string;
ipAddress?: string;
userAgent?: string;
description?: string;
metadata?: Record<string, unknown>;
status: "success" | "failure";
errorMessage?: string;
countryCode?: string;
countryName?: string;
city?: string;
region?: string;
sourceService?: string;
createdAt: string;
/** Whether this event has been reported by the user */
isReported?: boolean;
/** User information (username, avatar) - only when user_id is a valid Heimdall user */
user?: AuditUser;
/** Actor information (username, avatar) - the user who performed the action */
actor?: AuditUser;
}

sourceService Values:

ValueDescription
apiDirect API calls
idHeimdall ID app (account management)
backendHeimdall Backend (admin console)
policiesPolicies app
discord_botDiscord bot
twitch_botTwitch bot

AuditEventPage

Paginated audit event response.

interface AuditEventPage {
events: AuditEvent[];
totalCount: number;
page: number;
limit: number;
totalPages: number;
}

AuditEventQuery

Query parameters for filtering audit events.

interface AuditEventQuery {
page?: number;
limit?: number;
/** Single event type filter */
eventType?: string;
/** Multiple event types (comma-separated string) */
eventTypes?: string;
/** Exact user ID filter (admin only) */
userId?: string;
/** Search users by ID, username, or email (partial match) */
userSearch?: string;
resourceType?: string;
status?: string;
/** Filter by source service (e.g., "api", "id", "backend") */
sourceService?: string;
/** Filter by start date (ISO 8601 format) */
startDate?: string;
/** Filter by end date (ISO 8601 format) */
endDate?: string;
/** Sort field (event_type, user_id, status, created_at, date) */
sortField?: string;
/** Sort direction (asc or desc) */
sortDirection?: string;
/** Filter to show only reported events (admin only) */
isReported?: boolean;
}

AuditEventReport

Report submitted for suspicious activity.

interface AuditEventReport {
id: string;
auditEventId: string;
userId: string;
reason: string;
description?: string;
status: "pending" | "reviewed" | "resolved" | "dismissed";
reviewedBy?: string;
reviewedAt?: string;
resolutionNotes?: string;
createdAt: string;
updatedAt: string;
/** Reviewer info (username, avatar) when the report has been reviewed */
reviewer?: {
id: string;
username?: string;
avatarUrl?: string;
};
}

ReportAuditEventInput

Input for reporting an audit event.

interface ReportAuditEventInput {
auditEventId: string;
reason: "not_me" | "suspicious" | "unknown_device" | "unknown_location" | "other";
description?: string;
}

ReportAuditEventResponse

Response from reporting an audit event.

interface ReportAuditEventResponse {
success: boolean;
report?: AuditEventReport;
error?: string;
}

AuditReportPage (Admin)

Paginated audit reports response for admins.

interface AuditReportPage {
reports: AuditEventReport[];
totalCount: number;
page: number;
limit: number;
totalPages: number;
}

UpdateAuditReportInput (Admin)

Input for updating an audit report status.

interface UpdateAuditReportInput {
reportId: string;
status: "reviewed" | "resolved" | "dismissed";
resolutionNotes?: string;
}

UpdateAuditReportResponse (Admin)

Response from updating an audit report.

interface UpdateAuditReportResponse {
success: boolean;
report?: AuditEventReport;
error?: string;
}

Audit Event Constants & Utilities

The library provides constants and helper functions for working with audit events.

AuditEventTypes

Type-safe constants for all audit event types:

import { AuditEventTypes } from "@elcto/api";

AuditEventTypes.LOGIN // "login"
AuditEventTypes.LOGIN_FAILED // "login_failed"
AuditEventTypes.LOGOUT // "logout"
AuditEventTypes.TWO_FA_ENABLED // "2fa_enabled"
AuditEventTypes.PASSWORD_CHANGED // "password_changed"
// ... and more

AuditEventLabels

Human-readable labels for event types:

import { AuditEventLabels, getAuditEventLabel } from "@elcto/api";

// Direct lookup
AuditEventLabels["login"] // "Signed in"

// Helper function (with fallback)
getAuditEventLabel("login") // "Signed in"
getAuditEventLabel("unknown_type") // "unknown_type" (fallback)

Event Categories

Categorize events for filtering and display:

import {
AuditEventCategories,
getAuditEventCategory,
type AuditEventCategory,
} from "@elcto/api";

// Categories: "auth" | "security" | "account" | "oauth" | "link" | "data"
// | "bot" | "integration" | "storage" | "admin" | "modules" | "other"
getAuditEventCategory("login") // "auth"
getAuditEventCategory("user_updated") // "account"
getAuditEventCategory("session_created") // "account"
getAuditEventCategory("consent_granted") // "oauth"
getAuditEventCategory("user_banned") // "admin"

Event Icons

Icon names for rendering audit event icons:

import {
AuditEventIcons,
getAuditEventIconName,
type AuditIconName,
} from "@elcto/api";

// Icon names: "LogIn" | "LogOut" | "Shield" | "Key" | "User" | ...
getAuditEventIconName("login") // "LogIn"
getAuditEventIconName("2fa_enabled") // "Shield"
getAuditEventIconName("password_changed") // "Lock"
tip

Use the AuditIcon component from @elcto/ui to render these icons:

import { AuditIcon } from "@elcto/ui";
<AuditIcon eventType="login" className="w-4 h-4" />

Event Colors

Get colors for event categories and failure states:

import {
AuditCategoryColors,
AuditFailureColor,
getAuditEventColor,
} from "@elcto/api";

// Tailwind class strings (bg + text + border) keyed by category
AuditCategoryColors.auth // "bg-blue-500/10 text-blue-500 border-blue-500/20"
AuditCategoryColors.security // "bg-amber-500/10 text-amber-500 border-amber-500/20"
AuditCategoryColors.account // "bg-purple-500/10 text-purple-500 border-purple-500/20"
AuditCategoryColors.oauth // "bg-green-500/10 text-green-500 border-green-500/20"

// Failure color
AuditFailureColor // "bg-[var(--error-bg)] text-[var(--error)] border-[var(--error)]/20"

// Get color for a specific event — signature: (eventType, status)
// Failures always return AuditFailureColor; otherwise the category color is used.
getAuditEventColor("login", "success") // auth category color (blue)
getAuditEventColor("login", "failure") // AuditFailureColor

Filter Options

Pre-built filter options for activity log dropdowns:

import { AuditFilterOptions, getAuditFilterEventTypes } from "@elcto/api";

// Use in a select/dropdown
<select>
{AuditFilterOptions.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>

// Get event types for a filter category
getAuditFilterEventTypes("auth")
// Returns: ["login", "login_failed", "logout"]
getAuditFilterEventTypes("security")
// Returns: ["2fa_enabled", "2fa_disabled", "2fa_verified", ...]

Common Types

PaginationParams

Pagination parameters for list requests.

interface PaginationParams {
page?: number;
limit?: number;
offset?: number;
}

PaginatedResponse

Paginated response wrapper.

interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
limit: number;
hasMore: boolean;
}

ApiConfig

Legacy descriptor type (kept for backwards compatibility). Not the config you pass to transports — use ApiClientConfig for that.

interface ApiConfig {
apiUrl: string;
wsUrl: string;
hasSystemKey: boolean;
}

Hook Types

UseWebSocketOptions

Options for the useWebSocket hook.

interface UseWebSocketOptions extends WebSocketConfig {
immediate?: boolean;
}

UseWebSocketReturn

Return value from useWebSocket hook.

interface UseWebSocketReturn {
isConnected: boolean;
lastMessage: unknown;
send: (data: unknown) => void;
connect: () => void;
disconnect: () => void;
}

Role Constants

The library exports role ID constants for type-safe role checks:

import {
ROLE_SUPER_ADMIN, // "role_super_admin"
ROLE_ADMIN, // "role_admin"
ROLE_MODERATOR, // "role_moderator"
ROLE_DEVELOPER, // "role_developer"
ROLE_USER, // "role_user"
PRIVILEGED_ROLE_IDS, // Array of admin/mod/dev role IDs
} from "@/lib/api";

Helper Functions

import {
hasPrivilegedRole, // Check if user has admin/mod/dev role
hasRole, // Check if user has specific role
hasAnyRole, // Check if user has any of specified roles
hasAllRoles, // Check if user has all specified roles
} from "@/lib/api";

// Usage
const { roleIds, isSuperAdmin } = usePermissions();

if (isSuperAdmin || hasPrivilegedRole(roleIds)) {
// User can access admin features
}

if (hasRole(roleIds, ROLE_DEVELOPER)) {
// User has developer role
}

Importing Types

All types can be imported from @/lib/api:

import type {
// Config
ApiClientConfig,

// REST
ApiResponse,
ApiRequestOptions,

// GraphQL
GraphQLResponse,
GraphQLRequestOptions,

// WebSocket
WebSocketConfig,
WebSocketClient,
ServerMessage,
UserStatusMessage,
PermissionMessage,
OAuthConsentRevokedMessage,

// User
UserProfile,
UserPermissions,
PlatformAccount,
ActiveSession,
ActiveSessionsResponse,
RevokeSessionResponse,
RevokeAllSessionsResponse,

// Audit
AuditEvent,
AuditEventPage,
AuditEventQuery,
AuditEventReport,
ReportAuditEventInput,
ReportAuditEventResponse,
AuditReportPage,
UpdateAuditReportInput,
UpdateAuditReportResponse,

// Common
PaginationParams,
PaginatedResponse,
ApiConfig,

// Hooks
UseWebSocketOptions,
UseWebSocketReturn,
} from "@/lib/api";

// Role constants and helpers (not types)
import {
ROLE_SUPER_ADMIN,
ROLE_ADMIN,
ROLE_MODERATOR,
ROLE_DEVELOPER,
ROLE_USER,
PRIVILEGED_ROLE_IDS,
hasPrivilegedRole,
hasRole,
hasAnyRole,
hasAllRoles,
} from "@/lib/api";