# Class BaseEPClient

Base class for European Parliament API sub-clients.

Holds the shared HTTP machinery: LRU cache, token-bucket rate limiter, timeout/abort controller, and retry logic. Sub-clients extend this class and call the protected `get()` helper for all HTTP requests.

#### Hierarchy (View Summary)

- BaseEPClient
  - CommitteeClient
  - DocumentClient
  - LegislativeClient
  - MEPClient
  - PlenaryClient
  - QuestionClient
  - VocabularyClient
  - VotingClient

- Defined in clients/ep/baseClient.ts:213

##### Index

### Constructors

constructor

### Properties

baseURL
cache
cacheCounters
enableRetry
maxResponseBytes
maxRetries
rateLimiter
timeoutMs
EMPTY_JSONLD

### Methods

buildRequestUrl
clearCache
evictFromCache
fetchWithRetry
fetchWithTimeout
get
getCacheKey
getCacheStats
parseByContentLength
readStreamedBody
shouldRetryRequest
toAPIError
parseJsonLdBytes
parseResponseJson
resolveConfig
validateContentType

## Constructors

### constructor

- new BaseEPClient(
  config?: EPClientConfig,
  shared?: EPSharedResources,
  ): BaseEPClient

  Creates a BaseEPClient.

  When `shared` is provided the constructor reuses those pre-built resources instead of allocating new ones; this is the mechanism used by the facade to ensure all sub-clients share one cache and one rate-limiter.

  #### Parameters

  - config: EPClientConfig = {}

    Client configuration (used when `shared` is absent)

  - `Optional` shared: EPSharedResources

    Pre-built shared resources (passed by facade to sub-clients)

  #### Returns BaseEPClient

  - Defined in clients/ep/baseClient.ts:276

## Properties

### `Protected` `Readonly` baseURL

baseURL: string

European Parliament API base URL.

- Defined in clients/ep/baseClient.ts:217

### `Protected` `Readonly` cache

cache: LRUCache<string, Record<string, unknown>>

LRU cache for API responses.

- Defined in clients/ep/baseClient.ts:215

### `Private` `Readonly` cacheCounters

cacheCounters: { hits: number; misses: number }

Shared cache hit/miss counters (shared via EPSharedResources when used as sub-client).

- Defined in clients/ep/baseClient.ts:229

### `Protected` `Readonly` enableRetry

enableRetry: boolean

Enable automatic retry on transient failures.

- Defined in clients/ep/baseClient.ts:223

### `Protected` `Readonly` maxResponseBytes

maxResponseBytes: number

Maximum allowed response body size in bytes.

- Defined in clients/ep/baseClient.ts:227

### `Protected` `Readonly` maxRetries

maxRetries: number

Maximum number of retry attempts.

- Defined in clients/ep/baseClient.ts:225

### `Protected` `Readonly` rateLimiter

rateLimiter: RateLimiter

Token bucket rate limiter.

- Defined in clients/ep/baseClient.ts:219

### `Protected` `Readonly` timeoutMs

timeoutMs: number

Request timeout in milliseconds.

- Defined in clients/ep/baseClient.ts:221

### `Private` `Static` `Readonly` EMPTY_JSONLD

EMPTY_JSONLD: Readonly<{ "@context": never[]; data: never[] }> = ...

Empty JSON-LD shape returned for bodyless responses (HTTP 204, content-length: 0).

#### Private

- Defined in clients/ep/baseClient.ts:462

## Methods

### `Private` buildRequestUrl

- buildRequestUrl(endpoint: string, params?: Record<string, unknown>): URL

  Builds the full request URL from endpoint + optional params.

  #### Parameters

  - endpoint: string
  - `Optional` params: Record<string, unknown>

  #### Returns URL

  #### Private

  - Defined in clients/ep/baseClient.ts:308

### clearCache

- clearCache(): void

  Clears all entries from the LRU cache.

  #### Returns void

  - Defined in clients/ep/baseClient.ts:666

### `Protected` evictFromCache

- evictFromCache(endpoint: string, params?: Record<string, unknown>): void

  Evicts a single cache entry matching the given endpoint and params. Sub-clients use this when they detect that a successfully-fetched payload is a content-pending sentinel that must not be served from cache for the remainder of the TTL — eviction lets availability recover as soon as the upstream document is enriched.

  #### Parameters

  - endpoint: string

    API endpoint path (same value passed to get)

  - `Optional` params: Record<string, unknown>

    Optional query parameters (same value passed to get)

  #### Returns void

  #### Protected

  - Defined in clients/ep/baseClient.ts:681

### `Private` fetchWithRetry

- fetchWithRetry<T>(
  url: URL,
  endpoint: string,
  minimumTimeoutMs?: number,
  ): Promise<T>

  Wraps a fetch call with the configured retry policy.

  #### Type Parameters

  - T

  #### Parameters

  - url: URL

    Fully resolved request URL

  - endpoint: string

    Relative endpoint path (for error messages)

  - `Optional` minimumTimeoutMs: number

    Optional per-request minimum timeout (ms)

  #### Returns Promise<T>

  #### Private

  - Defined in clients/ep/baseClient.ts:552

### `Private` fetchWithTimeout

- fetchWithTimeout<T>(
  url: URL,
  endpoint: string,
  minimumTimeoutMs?: number,
  ): Promise<T>

  Executes the HTTP fetch with timeout/abort support and response size guard.

  #### Type Parameters

  - T

  #### Parameters

  - url: URL

    Fully resolved request URL

  - endpoint: string

    Relative endpoint path (for error messages)

  - `Optional` minimumTimeoutMs: number

    Optional per-request minimum timeout (ms). When provided, the effective timeout is `Math.max(minimumTimeoutMs, this.timeoutMs)`, so it acts as a floor that the global timeout can still extend. Use for known slow EP API endpoints (e.g. `procedures/feed`).

  #### Returns Promise<T>

  #### Private

  - Defined in clients/ep/baseClient.ts:501

### `Protected` get

- get<T extends Record<string, unknown>>(
  endpoint: string,
  params?: Record<string, unknown>,
  minimumTimeoutMs?: number,
  ): Promise<T>

  Executes a cached, rate-limited GET request to the EP API.

  #### Type Parameters

  - T extends Record<string, unknown>

    Expected response type (extends `Record<string, unknown>`)

  #### Parameters

  - endpoint: string

    API endpoint path (relative to `baseURL`)

  - `Optional` params: Record<string, unknown>

    Optional query parameters

  - `Optional` minimumTimeoutMs: number

    Optional per-request minimum timeout in milliseconds. When provided, the effective timeout is `Math.max(minimumTimeoutMs, this.timeoutMs)`, so the global timeout (set via `--timeout` or `EP_REQUEST_TIMEOUT_MS`) can still extend it beyond the per-endpoint minimum. Use for known slow EP API endpoints such as `procedures/feed`.

  #### Returns Promise<T>

  Promise resolving to the typed API response

  #### Throws

  On HTTP errors, network failures, or parse failures

  #### Protected

  - Defined in clients/ep/baseClient.ts:606

### `Private` getCacheKey

- getCacheKey(endpoint: string, params?: Record<string, unknown>): string

  Generates a deterministic cache key.

  #### Parameters

  - endpoint: string

    API endpoint path

  - `Optional` params: Record<string, unknown>

    Optional query parameters

  #### Returns string

  JSON string used as cache key

  #### Private

  - Defined in clients/ep/baseClient.ts:652

### getCacheStats

- getCacheStats(): {
  hitRate: number;
  hits: number;
  maxSize: number;
  misses: number;
  size: number;
  }

  Returns cache statistics for monitoring and debugging.

  #### Returns { hitRate: number; hits: number; maxSize: number; misses: number; size: number }

  `{ size, maxSize, hitRate, hits, misses }`

  - Defined in clients/ep/baseClient.ts:690

### `Private` parseByContentLength

- parseByContentLength<T>(response: Response): Promise<T | undefined>

  Parses the response body based on content-length header. Returns `undefined` when content-length is absent or non-finite (caller should fall through to streamed-body parsing).

  #### Type Parameters

  - T

  #### Parameters

  - response: Response

  #### Returns Promise<T | undefined>

  #### Private

  - Defined in clients/ep/baseClient.ts:470

### `Private` readStreamedBody

- readStreamedBody<T>(response: Response): Promise<T>

  Reads the response body as a stream, enforcing the response size cap. Used as a fallback when the `content-length` header is absent (e.g. chunked transfer encoding). Accumulates all chunks and parses the result as JSON.

  #### Type Parameters

  - T

  #### Parameters

  - response: Response

  #### Returns Promise<T>

  #### Private

  - Defined in clients/ep/baseClient.ts:375

### `Private` shouldRetryRequest

- shouldRetryRequest(error: unknown): boolean

  Returns true when an error should trigger a retry.

  Retries on:

  - 429 Too Many Requests (rate-limited by EP API; exponential backoff applied)
  - 5xx Server Errors (transient server failures)
  - Network / unknown errors

  Does NOT retry on 4xx client errors (except 429).

  #### Parameters

  - error: unknown

  #### Returns boolean

  #### Private

  - Defined in clients/ep/baseClient.ts:342

### `Private` toAPIError

- toAPIError(error: unknown, endpoint: string): APIError

  Converts a caught error to a typed APIError. For timeout errors, the actual timeout value is read from the TimeoutError instance (which carries the effective value used by `withTimeoutAndAbort`), avoiding the need to re-validate or recompute the per-endpoint minimum here.

  #### Parameters

  - error: unknown

    The caught error

  - endpoint: string

    Relative endpoint path (for error messages)

  #### Returns APIError

  #### Private

  - Defined in clients/ep/baseClient.ts:574

### `Private` `Static` parseJsonLdBytes

- parseJsonLdBytes(bytes: Uint8Array): JSONLDResponse

  Parses a byte buffer as JSON-LD. Returns an empty JSON-LD shape for zero-byte bodies (the EP API sends these for out-of-range offsets). Non-empty bodies must contain valid JSON; any `SyntaxError` is allowed to propagate so callers (including single-entity endpoints) fail fast instead of receiving a misleading empty-list shape.

  #### Parameters

  - bytes: Uint8Array

  #### Returns JSONLDResponse

  #### Private

  - Defined in clients/ep/baseClient.ts:362

### `Private` `Static` parseResponseJson

- parseResponseJson<T>(response: Response): Promise<T>

  Treats a truly empty body as an empty JSON-LD shape; invalid JSON for non-empty bodies is surfaced as an error.

  #### Type Parameters

  - T

  #### Parameters

  - response: Response

  #### Returns Promise<T>

  #### Private

  - Defined in clients/ep/baseClient.ts:421

### `Private` `Static` resolveConfig

- resolveConfig(
  config: EPClientConfig,
  ): {
  baseURL: string;
  cacheTTL: number;
  enableRetry: boolean;
  maxCacheSize: number;
  maxResponseBytes: number;
  maxRetries: number;
  rateLimiter: RateLimiter;
  timeoutMs: number;
  }

  Resolves all EPClientConfig options to their final values with defaults applied. Extracted to keep constructor complexity within limits.

  #### Parameters

  - config: EPClientConfig

  #### Returns {
  baseURL: string;
  cacheTTL: number;
  enableRetry: boolean;
  maxCacheSize: number;
  maxResponseBytes: number;
  maxRetries: number;
  rateLimiter: RateLimiter;
  timeoutMs: number;
  }

  #### Private

  - Defined in clients/ep/baseClient.ts:236

### `Private` `Static` validateContentType

- validateContentType(response: Response): void

  Validates the Content-Type header of an API response. Throws if the response is not JSON (e.g. HTML error pages from reverse proxies). Cancels the response body before throwing to allow connection reuse.

  A missing or empty Content-Type header is treated as acceptable because the EP API occasionally omits it on valid JSON responses, and rejecting those would cause false-negative failures.

  #### Parameters

  - response: Response

  #### Returns void

  #### Private

  - Defined in clients/ep/baseClient.ts:441