import type { TRegistryProtocol } from '../core/interfaces.core.js'; /** * Scope rule for routing requests to specific upstreams. * Uses glob patterns for flexible matching. */ export interface IUpstreamScopeRule { /** Glob pattern (e.g., "@company/*", "com.example.*", "library/*") */ pattern: string; /** Whether matching resources should be included or excluded */ action: 'include' | 'exclude'; } /** * Authentication configuration for an upstream registry. * Supports multiple auth strategies. */ export interface IUpstreamAuthConfig { /** Authentication type */ type: 'none' | 'basic' | 'bearer' | 'api-key'; /** Username for basic auth */ username?: string; /** Password for basic auth */ password?: string; /** Token for bearer or api-key auth */ token?: string; /** Custom header name for api-key auth (default: 'Authorization') */ headerName?: string; } /** * Cache configuration for upstream content. */ export interface IUpstreamCacheConfig { /** Whether caching is enabled */ enabled: boolean; /** Default TTL in seconds for mutable content (default: 300 = 5 min) */ defaultTtlSeconds: number; /** TTL in seconds for immutable/content-addressable content (default: 2592000 = 30 days) */ immutableTtlSeconds: number; /** Whether to serve stale content while revalidating in background */ staleWhileRevalidate: boolean; /** Maximum age in seconds for stale content (default: 3600 = 1 hour) */ staleMaxAgeSeconds: number; /** TTL in seconds for negative cache entries (404s) (default: 60 = 1 min) */ negativeCacheTtlSeconds: number; } /** * Resilience configuration for upstream requests. */ export interface IUpstreamResilienceConfig { /** Request timeout in milliseconds (default: 30000) */ timeoutMs: number; /** Maximum number of retry attempts (default: 3) */ maxRetries: number; /** Initial retry delay in milliseconds (default: 1000) */ retryDelayMs: number; /** Maximum retry delay in milliseconds (default: 30000) */ retryMaxDelayMs: number; /** Number of failures before circuit breaker opens (default: 5) */ circuitBreakerThreshold: number; /** Time in milliseconds before circuit breaker attempts reset (default: 30000) */ circuitBreakerResetMs: number; } /** * Configuration for a single upstream registry. */ export interface IUpstreamRegistryConfig { /** Unique identifier for this upstream */ id: string; /** Human-readable name */ name: string; /** Base URL of the upstream registry (e.g., "https://registry.npmjs.org") */ url: string; /** Priority for routing (lower = higher priority, 1 = first) */ priority: number; /** Whether this upstream is enabled */ enabled: boolean; /** Scope rules for routing (empty = match all) */ scopeRules?: IUpstreamScopeRule[]; /** Authentication configuration */ auth: IUpstreamAuthConfig; /** Cache configuration overrides */ cache?: Partial; /** Resilience configuration overrides */ resilience?: Partial; } /** * Protocol-level upstream configuration. * Configures upstream behavior for a specific protocol (npm, oci, etc.) */ export interface IProtocolUpstreamConfig { /** Whether upstream is enabled for this protocol */ enabled: boolean; /** List of upstream registries, ordered by priority */ upstreams: IUpstreamRegistryConfig[]; /** Protocol-level cache configuration defaults */ cache?: Partial; /** Protocol-level resilience configuration defaults */ resilience?: Partial; } /** * Result of an upstream fetch operation. */ export interface IUpstreamResult { /** Whether the fetch was successful (2xx status) */ success: boolean; /** HTTP status code */ status: number; /** Response headers */ headers: Record; /** Response body (Buffer for binary, object for JSON) */ body?: Buffer | any; /** ID of the upstream that served the request */ upstreamId: string; /** Whether the response was served from cache */ fromCache: boolean; /** Request latency in milliseconds */ latencyMs: number; } /** * Circuit breaker state. */ export type TCircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN'; /** * Context for an upstream fetch request. */ export interface IUpstreamFetchContext { /** Protocol type */ protocol: TRegistryProtocol; /** Resource identifier (package name, artifact name, etc.) */ resource: string; /** Type of resource being fetched (packument, tarball, manifest, blob, etc.) */ resourceType: string; /** Original request path */ path: string; /** HTTP method */ method: string; /** Request headers */ headers: Record; /** Query parameters */ query: Record; } /** * Cache entry stored in the upstream cache. */ export interface ICacheEntry { /** Cached data */ data: Buffer; /** Content type of the cached data */ contentType: string; /** Original response headers */ headers: Record; /** When the entry was cached */ cachedAt: Date; /** When the entry expires */ expiresAt?: Date; /** ETag for conditional requests */ etag?: string; /** ID of the upstream that provided the data */ upstreamId: string; /** Whether the entry is stale but still usable */ stale?: boolean; } /** * Default cache configuration values. */ export const DEFAULT_CACHE_CONFIG: IUpstreamCacheConfig = { enabled: true, defaultTtlSeconds: 300, // 5 minutes immutableTtlSeconds: 2592000, // 30 days staleWhileRevalidate: true, staleMaxAgeSeconds: 3600, // 1 hour negativeCacheTtlSeconds: 60, // 1 minute }; /** * Default resilience configuration values. */ export const DEFAULT_RESILIENCE_CONFIG: IUpstreamResilienceConfig = { timeoutMs: 30000, maxRetries: 3, retryDelayMs: 1000, retryMaxDelayMs: 30000, circuitBreakerThreshold: 5, circuitBreakerResetMs: 30000, };