import type { CommonLogger } from '@goatlab/js-utils'; import type { BuiltRouter } from '@trpc/server/unstable-core-do-not-import'; import type { Request, RequestHandler, Router } from 'express'; import type { RequestLoggerOptions, RequestLogPrefixFn } from '../middleware/logs.middleware'; import type { SentryService } from '../sentry/sentry.service'; import type { Environment } from '../types/Envinronment'; /** * Validated user from Better Auth or other auth provider */ export interface ValidatedAuthUser { /** User's unique ID */ id: string; /** User's email address */ email: string; /** Whether email has been verified */ emailVerified?: boolean; /** User's display name */ name?: string; /** User's profile image URL */ image?: string; /** Session ID if using session-based auth */ sessionId?: string; /** Additional metadata */ metadata?: Record; } /** * Result of token validation */ export interface AuthValidationResult { /** Whether the token is valid */ valid: boolean; /** Validated user info (only present if valid) */ user?: ValidatedAuthUser; /** Error message (only present if invalid) */ error?: string; } /** * Auth configuration for Better Auth integration */ export interface AuthConfig { /** * Validate a token and return the authenticated user. * This callback is called for each request with a Bearer token. * * @param token - The token from Authorization header (without "Bearer " prefix) * @param req - The Express request object (for accessing headers, tenant info, etc.) * @returns Validation result with user info or error * * @example * ```typescript * validateToken: async (token, req) => { * const tenantId = req.headers['x-tenant-id'] as string * const auth = await getBetterAuthForTenant(tenantId) * const session = await auth.api.getSession({ * headers: new Headers({ authorization: `Bearer ${token}` }) * }) * if (!session?.user) { * return { valid: false, error: 'Invalid session' } * } * return { * valid: true, * user: { * id: session.user.id, * email: session.user.email, * emailVerified: session.user.emailVerified, * name: session.user.name, * } * } * } * ``` */ validateToken?: (token: string, req: Request) => Promise; } export interface RequiredExpressTrpcAppConfig { trpcRouter: BuiltRouter; } export interface OptionalExpressTrpcAppConfig { appName?: string; appVersion?: string; port?: number; baseUrl?: string; environment?: Environment; sentryService?: SentryService; logger?: CommonLogger; expressResources?: Router[] | readonly Router[]; customHandlers?: RequestHandler[]; /** * Optional function to extract a prefix for request log lines. * Called on each request's `finish` event. * Useful for multi-tenant apps to prepend tenant ID. * * @example * ```typescript * requestLogPrefix: (req) => req.headers['x-tenant-id'] as string * ``` */ requestLogPrefix?: RequestLogPrefixFn; /** * Logging configuration for request logs. * Passed through to the Express request logger middleware. */ logging?: RequestLoggerOptions; auth?: AuthConfig; features?: { openApiDocs?: boolean; sentry?: boolean; trustProxy?: boolean; etag?: 'weak' | 'strong' | boolean; }; security?: { cors?: { allowedOrigins?: string[]; credentials?: boolean; maxAge?: number; }; helmet?: { contentSecurityPolicy?: boolean | object; crossOriginEmbedderPolicy?: boolean; }; rateLimit?: { global?: { windowMs?: number; max?: number; }; auth?: { windowMs?: number; max?: number; }; api?: { windowMs?: number; max?: number; }; }; requestTimeout?: number; }; bodyParsing?: { json?: { limit?: string; type?: string[]; }; urlencoded?: { limit?: string; extended?: boolean; }; raw?: { limit?: string; inflate?: boolean; }; }; performance?: { compression?: { enabled?: boolean; level?: number; threshold?: number; chunkSize?: number; memLevel?: number; }; memoryMonitoring?: { enabled?: boolean; warningThreshold?: number; criticalThreshold?: number; monitorInterval?: number; enableGarbageCollection?: boolean; addHeaders?: boolean; }; caching?: { staticAssets?: { maxAge?: number; }; }; }; server?: { viewEngine?: string; viewPaths?: string[]; }; healthCheck?: { path?: string; customChecks?: () => Promise; }; readyCheck?: { path?: string; customChecks?: () => Promise; }; processManagement?: { gracefulShutdown?: { enabled?: boolean; timeout?: number; onShutdown?: () => Promise; }; uncaughtException?: { handler?: (error: Error) => void; }; unhandledRejection?: { handler?: (reason: any, promise: Promise) => void; }; }; } export type ExpressTrpcAppConfig = RequiredExpressTrpcAppConfig & Required; export type ExpressTrpcAppConfigInput = RequiredExpressTrpcAppConfig & Partial; /** * Get complete default configuration */ export declare function getDefaultConfig(userConfig: ExpressTrpcAppConfigInput): ExpressTrpcAppConfig;