{"version":3,"file":"EndpointRegistry.mjs","sources":["../../../../../src/lib/core/config/registry/EndpointRegistry.ts"],"sourcesContent":["/**\n * @fileoverview REST API Endpoint Registry with dynamic discovery and health tracking.\n *\n * The EndpointRegistry provides:\n * - Centralized endpoint registration and lookup\n * - Dynamic endpoint discovery at runtime\n * - Endpoint health tracking\n * - URL building with path params and query strings\n * - Change subscription for endpoint updates\n *\n * @module core/config/registry/EndpointRegistry\n */\n\nimport { z } from 'zod';\n\nimport type {\n  EndpointChangeEvent,\n  EndpointChangeListener,\n  EndpointDefinition,\n  EndpointHealth,\n  EndpointHealthStatus,\n  HttpMethod,\n  IEndpointRegistry,\n  Milliseconds,\n  Unsubscribe,\n} from '../types';\n\nimport { DEFAULT_MAX_RETRY_ATTEMPTS, DEFAULT_TIMEOUT } from '../constants';\n\n// =============================================================================\n// Zod Schemas for JSON Validation\n// =============================================================================\n\n/**\n * Zod schema for HTTP method validation\n */\nconst HttpMethodSchema = z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']);\n\n/**\n * Zod schema for cache strategy validation\n */\nconst CacheStrategySchema = z.enum([\n  'no-cache',\n  'cache-first',\n  'network-first',\n  'stale-while-revalidate',\n]);\n\n/**\n * Zod schema for endpoint cache configuration\n */\nconst EndpointCacheConfigSchema = z\n  .object({\n    strategy: CacheStrategySchema,\n    ttl: z.number().positive(),\n    tags: z.array(z.string()).optional(),\n    varyByUser: z.boolean().optional(),\n  })\n  .strict();\n\n/**\n * Zod schema for endpoint rate limit configuration\n */\nconst EndpointRateLimitSchema = z\n  .object({\n    requests: z.number().positive().int(),\n    window: z.number().positive(),\n    scope: z.enum(['user', 'global']),\n  })\n  .strict();\n\n/**\n * Zod schema for endpoint definition validation.\n * Validates imported JSON before processing.\n */\nconst EndpointDefinitionSchema = z\n  .object({\n    name: z.string().min(1),\n    path: z.string().min(1),\n    method: HttpMethodSchema,\n    description: z.string().optional(),\n    version: z.string().optional(),\n    auth: z.boolean(),\n    timeout: z.number().positive().optional(),\n    retries: z.number().int().min(0).optional(),\n    cache: EndpointCacheConfigSchema.optional(),\n    rateLimit: EndpointRateLimitSchema.optional(),\n    tags: z.array(z.string()).optional(),\n    baseUrl: z.string().url().optional(),\n    headers: z.record(z.string(), z.string()).optional(),\n    requestSchema: z.unknown().optional(),\n    responseSchema: z.unknown().optional(),\n    deprecated: z.boolean().optional(),\n    deprecationMessage: z.string().optional(),\n    replacedBy: z.string().optional(),\n  })\n  .strict();\n\n/**\n * Zod schema for endpoint health status\n */\nconst EndpointHealthStatusSchema = z.enum(['healthy', 'degraded', 'unhealthy', 'unknown']);\n\n/**\n * Zod schema for endpoint health validation\n */\nconst EndpointHealthSchema = z\n  .object({\n    status: EndpointHealthStatusSchema,\n    lastSuccess: z\n      .string()\n      .datetime()\n      .optional()\n      .transform((val) =>\n        val !== undefined && val !== null && val !== '' ? new Date(val) : undefined\n      ),\n    lastFailure: z\n      .string()\n      .datetime()\n      .optional()\n      .transform((val) =>\n        val !== undefined && val !== null && val !== '' ? new Date(val) : undefined\n      ),\n    failureCount: z.number().int().min(0),\n    avgResponseTime: z.number().positive().optional(),\n    errorMessage: z.string().optional(),\n  })\n  .strict();\n\n/**\n * Zod schema for the complete JSON import structure\n */\nconst EndpointRegistryImportSchema = z\n  .object({\n    endpoints: z.array(EndpointDefinitionSchema),\n    health: z.record(z.string(), EndpointHealthSchema).optional(),\n  })\n  .strict();\n\n// =============================================================================\n// Default Endpoint Configuration\n// =============================================================================\n\nconst DEFAULT_ENDPOINT_HEALTH: EndpointHealth = {\n  status: 'unknown',\n  failureCount: 0,\n};\n\nconst UNHEALTHY_THRESHOLD = 5; // Failures before marking unhealthy\nconst DEGRADED_THRESHOLD = 2; // Failures before marking degraded\nconst HEALTH_RECOVERY_THRESHOLD = 3; // Successes to recover from unhealthy\n\n// =============================================================================\n// EndpointRegistry Implementation\n// =============================================================================\n\n/**\n * Centralized registry for REST API endpoints.\n *\n * Provides comprehensive endpoint management including:\n * - Registration and lookup\n * - Health tracking\n * - Dynamic URL building\n * - Change subscriptions\n *\n * @example\n * ```typescript\n * const registry = EndpointRegistry.getInstance();\n *\n * // Register an endpoint\n * registry.register({\n *   name: 'users.list',\n *   path: '/users',\n *   method: 'GET',\n *   auth: true,\n *   cache: { strategy: 'cache-first', ttl: 300000 },\n * });\n *\n * // Build URL with params\n * const url = registry.buildUrl('users.detail', { id: '123' });\n * // Result: '/users/123'\n *\n * // Track health\n * registry.markHealthy('users.list', 150); // 150ms response time\n * registry.markUnhealthy('users.list', 'Connection timeout');\n * ```\n */\nexport class EndpointRegistry implements IEndpointRegistry {\n  private static instance: EndpointRegistry | null = null;\n\n  private endpoints: Map<string, EndpointDefinition> = new Map();\n  private health: Map<string, EndpointHealth> = new Map();\n  private successCounts: Map<string, number> = new Map();\n  private responseTimes: Map<string, number[]> = new Map();\n  private listeners: Set<EndpointChangeListener> = new Set();\n  private baseUrl = '';\n\n  private constructor() {}\n\n  /**\n   * Get the singleton instance.\n   */\n  static getInstance(): EndpointRegistry {\n    EndpointRegistry.instance ??= new EndpointRegistry();\n    return EndpointRegistry.instance;\n  }\n\n  /**\n   * Reset the singleton instance (for testing).\n   */\n  static resetInstance(): void {\n    EndpointRegistry.instance = null;\n  }\n\n  // ===========================================================================\n  // Configuration\n  // ===========================================================================\n\n  /**\n   * Set the base URL for all endpoints.\n   */\n  setBaseUrl(url: string): void {\n    this.baseUrl = url.replace(/\\/$/, ''); // Remove trailing slash\n  }\n\n  /**\n   * Get the current base URL.\n   */\n  getBaseUrl(): string {\n    return this.baseUrl;\n  }\n\n  // ===========================================================================\n  // Registration\n  // ===========================================================================\n\n  /**\n   * Register a new endpoint.\n   */\n  register(definition: EndpointDefinition): void {\n    const existing = this.endpoints.get(definition.name);\n\n    // Apply defaults\n    const endpoint: EndpointDefinition = {\n      ...definition,\n      timeout: definition.timeout ?? DEFAULT_TIMEOUT,\n      retries: definition.retries ?? DEFAULT_MAX_RETRY_ATTEMPTS,\n      auth: definition.auth ?? true,\n    };\n\n    this.endpoints.set(definition.name, endpoint);\n    this.health.set(definition.name, { ...DEFAULT_ENDPOINT_HEALTH });\n\n    this.emitEvent({\n      type: existing ? 'updated' : 'registered',\n      name: definition.name,\n      endpoint,\n      timestamp: new Date(),\n    });\n\n    // Log deprecation warning\n    if (definition.deprecated === true) {\n      console.warn(\n        `[EndpointRegistry] Endpoint \"${definition.name}\" is deprecated.`,\n        definition.deprecationMessage ?? '',\n        definition.replacedBy != null && definition.replacedBy !== ''\n          ? `Use \"${definition.replacedBy}\" instead.`\n          : ''\n      );\n    }\n  }\n\n  /**\n   * Register multiple endpoints at once.\n   */\n  registerBatch(definitions: readonly EndpointDefinition[]): void {\n    for (const definition of definitions) {\n      this.register(definition);\n    }\n  }\n\n  /**\n   * Register endpoints from an object (for easy migration from existing patterns).\n   */\n  registerFromObject(\n    obj: Record<string, string | ((id: string) => string)>,\n    options: {\n      method?: HttpMethod;\n      auth?: boolean;\n      prefix?: string;\n      tags?: string[];\n    } = {}\n  ): void {\n    const { method = 'GET', auth = true, prefix = '', tags = [] } = options;\n\n    for (const [name, pathOrFn] of Object.entries(obj)) {\n      const isFunction = typeof pathOrFn === 'function';\n      const path = isFunction ? pathOrFn(':id') : pathOrFn;\n\n      this.register({\n        name: prefix ? `${prefix}.${name}` : name,\n        path,\n        method,\n        auth,\n        tags,\n      });\n    }\n  }\n\n  // ===========================================================================\n  // Lookup\n  // ===========================================================================\n\n  /**\n   * Get an endpoint by name.\n   */\n  get(name: string): EndpointDefinition | undefined {\n    return this.endpoints.get(name);\n  }\n\n  /**\n   * Get all endpoints matching a tag.\n   */\n  getByTag(tag: string): readonly EndpointDefinition[] {\n    return Array.from(this.endpoints.values()).filter(\n      (endpoint) => endpoint.tags?.includes(tag) ?? false\n    );\n  }\n\n  /**\n   * Get all endpoints matching a path pattern.\n   */\n  getByPath(pathPattern: string): readonly EndpointDefinition[] {\n    const regex = new RegExp(pathPattern.replace(/:[^/]+/g, '[^/]+'));\n    return Array.from(this.endpoints.values()).filter((endpoint) => regex.test(endpoint.path));\n  }\n\n  /**\n   * Get all registered endpoints.\n   */\n  getAll(): readonly EndpointDefinition[] {\n    return Array.from(this.endpoints.values());\n  }\n\n  /**\n   * Check if an endpoint exists.\n   */\n  has(name: string): boolean {\n    return this.endpoints.has(name);\n  }\n\n  // ===========================================================================\n  // Modification\n  // ===========================================================================\n\n  /**\n   * Update an existing endpoint.\n   */\n  update(name: string, updates: Partial<EndpointDefinition>): void {\n    const existing = this.endpoints.get(name);\n    if (!existing) {\n      console.warn(`[EndpointRegistry] Endpoint \"${name}\" not found`);\n      return;\n    }\n\n    const updated: EndpointDefinition = {\n      ...existing,\n      ...updates,\n      name: existing.name, // Name cannot be changed\n    };\n\n    this.endpoints.set(name, updated);\n\n    this.emitEvent({\n      type: 'updated',\n      name,\n      endpoint: updated,\n      timestamp: new Date(),\n    });\n  }\n\n  /**\n   * Remove an endpoint.\n   */\n  remove(name: string): void {\n    if (!this.endpoints.has(name)) {\n      return;\n    }\n\n    this.endpoints.delete(name);\n    this.health.delete(name);\n    this.responseTimes.delete(name);\n    this.successCounts.delete(name);\n\n    this.emitEvent({\n      type: 'removed',\n      name,\n      timestamp: new Date(),\n    });\n  }\n\n  /**\n   * Clear all endpoints.\n   */\n  clear(): void {\n    this.endpoints.clear();\n    this.health.clear();\n    this.responseTimes.clear();\n    this.successCounts.clear();\n  }\n\n  // ===========================================================================\n  // Health Tracking\n  // ===========================================================================\n\n  /**\n   * Mark an endpoint as healthy after a successful request.\n   */\n  markHealthy(name: string, responseTime?: Milliseconds): void {\n    const currentHealth = this.health.get(name) ?? { ...DEFAULT_ENDPOINT_HEALTH };\n    const successCount = (this.successCounts.get(name) ?? 0) + 1;\n    this.successCounts.set(name, successCount);\n\n    // Track response time\n    if (responseTime !== undefined) {\n      const times = this.responseTimes.get(name) ?? [];\n      times.push(responseTime);\n      // Keep last 100 response times\n      if (times.length > 100) {\n        times.shift();\n      }\n      this.responseTimes.set(name, times);\n    }\n\n    // Calculate new health status\n    let newStatus: EndpointHealthStatus = 'healthy';\n\n    if (currentHealth.status === 'unhealthy' && successCount < HEALTH_RECOVERY_THRESHOLD) {\n      newStatus = 'degraded';\n    } else if (currentHealth.status === 'degraded' && successCount >= HEALTH_RECOVERY_THRESHOLD) {\n      newStatus = 'healthy';\n      this.successCounts.set(name, 0); // Reset counter\n    }\n\n    const newHealth: EndpointHealth = {\n      status: newStatus,\n      lastSuccess: new Date(),\n      lastFailure: currentHealth.lastFailure,\n      failureCount: 0,\n      avgResponseTime: this.calculateAvgResponseTime(name),\n    };\n\n    this.health.set(name, newHealth);\n\n    if (currentHealth.status !== newStatus) {\n      this.emitEvent({\n        type: 'health-changed',\n        name,\n        previousHealth: currentHealth,\n        newHealth,\n        timestamp: new Date(),\n      });\n    }\n  }\n\n  /**\n   * Mark an endpoint as unhealthy after a failed request.\n   */\n  markUnhealthy(name: string, reason: string): void {\n    const currentHealth = this.health.get(name) ?? { ...DEFAULT_ENDPOINT_HEALTH };\n    const failureCount = currentHealth.failureCount + 1;\n    this.successCounts.set(name, 0); // Reset success counter\n\n    // Determine new status based on failure count\n    let newStatus: EndpointHealthStatus = currentHealth.status;\n    if (failureCount >= UNHEALTHY_THRESHOLD) {\n      newStatus = 'unhealthy';\n    } else if (failureCount >= DEGRADED_THRESHOLD) {\n      newStatus = 'degraded';\n    }\n\n    const newHealth: EndpointHealth = {\n      status: newStatus,\n      lastSuccess: currentHealth.lastSuccess,\n      lastFailure: new Date(),\n      failureCount,\n      avgResponseTime: currentHealth.avgResponseTime,\n      errorMessage: reason,\n    };\n\n    this.health.set(name, newHealth);\n\n    if (currentHealth.status !== newStatus) {\n      this.emitEvent({\n        type: 'health-changed',\n        name,\n        previousHealth: currentHealth,\n        newHealth,\n        timestamp: new Date(),\n      });\n    }\n  }\n\n  /**\n   * Get health status for an endpoint.\n   */\n  getHealth(name: string): EndpointHealth | undefined {\n    return this.health.get(name);\n  }\n\n  /**\n   * Get all unhealthy endpoints.\n   */\n  getUnhealthyEndpoints(): readonly string[] {\n    return Array.from(this.health.entries())\n      .filter(([, health]) => health.status === 'unhealthy')\n      .map(([name]) => name);\n  }\n\n  /**\n   * Get all degraded endpoints.\n   */\n  getDegradedEndpoints(): readonly string[] {\n    return Array.from(this.health.entries())\n      .filter(([, health]) => health.status === 'degraded')\n      .map(([name]) => name);\n  }\n\n  /**\n   * Get all healthy endpoints.\n   */\n  getHealthyEndpoints(): readonly string[] {\n    return Array.from(this.health.entries())\n      .filter(([, health]) => health.status === 'healthy')\n      .map(([name]) => name);\n  }\n\n  /**\n   * Build a full URL for an endpoint.\n   */\n  buildUrl(name: string, params?: Record<string, string | number>): string {\n    const endpoint = this.endpoints.get(name);\n    if (!endpoint) {\n      throw new Error(`[EndpointRegistry] Endpoint \"${name}\" not found`);\n    }\n\n    let url = endpoint.path;\n\n    // Substitute path parameters\n    if (params) {\n      for (const [key, value] of Object.entries(params)) {\n        url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n      }\n    }\n\n    // Use endpoint-specific base URL or global base URL\n    const base = endpoint.baseUrl ?? this.baseUrl;\n\n    return base ? `${base}${url.startsWith('/') ? url : `/${url}`}` : url;\n  }\n\n  // ===========================================================================\n  // URL Building\n  // ===========================================================================\n\n  /**\n   * Build a URL with query parameters.\n   */\n  buildUrlWithQuery(\n    name: string,\n    params?: Record<string, string | number>,\n    query?: Record<string, string | number | boolean>\n  ): string {\n    const url = this.buildUrl(name, params);\n\n    if (!query || Object.keys(query).length === 0) {\n      return url;\n    }\n\n    const searchParams = new URLSearchParams();\n    for (const [key, value] of Object.entries(query)) {\n      if (value !== undefined && value !== null) {\n        searchParams.set(key, String(value));\n      }\n    }\n\n    const queryString = searchParams.toString();\n    return queryString ? `${url}?${queryString}` : url;\n  }\n\n  /**\n   * Subscribe to endpoint changes.\n   */\n  subscribe(listener: EndpointChangeListener): Unsubscribe {\n    this.listeners.add(listener);\n    return () => {\n      this.listeners.delete(listener);\n    };\n  }\n\n  // ===========================================================================\n  // Subscriptions\n  // ===========================================================================\n\n  /**\n   * Export all endpoints as JSON.\n   */\n  toJSON(): string {\n    const data = {\n      endpoints: Array.from(this.endpoints.values()),\n      health: Object.fromEntries(this.health),\n    };\n    return JSON.stringify(data, null, 2);\n  }\n\n  /**\n   * Import endpoints from JSON with schema validation.\n   *\n   * Validates the imported JSON against a strict Zod schema before processing\n   * to prevent injection of malformed or malicious data.\n   *\n   * @param json - JSON string to import\n   * @throws {z.ZodError} If validation fails\n   * @throws {SyntaxError} If JSON parsing fails\n   */\n  fromJSON(json: string): void {\n    // Step 1: Parse JSON (may throw SyntaxError)\n    let rawData: unknown;\n    try {\n      rawData = JSON.parse(json);\n    } catch (parseError) {\n      console.error('[EndpointRegistry] Failed to parse JSON:', parseError);\n      throw parseError;\n    }\n\n    // Step 2: Validate against Zod schema (may throw ZodError)\n    const validationResult = EndpointRegistryImportSchema.safeParse(rawData);\n\n    if (!validationResult.success) {\n      const errorMessage = validationResult.error.issues\n        .map((e) => `${e.path.join('.')}: ${e.message}`)\n        .join('; ');\n      console.error('[EndpointRegistry] JSON validation failed:', errorMessage);\n      throw new Error(`[EndpointRegistry] Invalid JSON structure: ${errorMessage}`);\n    }\n\n    // Step 3: Process validated data\n    const { data } = validationResult;\n\n    this.registerBatch(data.endpoints as EndpointDefinition[]);\n\n    if (data.health) {\n      for (const [name, health] of Object.entries(data.health)) {\n        this.health.set(name, health as EndpointHealth);\n      }\n    }\n  }\n\n  // ===========================================================================\n  // Serialization\n  // ===========================================================================\n\n  /**\n   * Get registry statistics.\n   */\n  getStats(): {\n    totalEndpoints: number;\n    healthy: number;\n    degraded: number;\n    unhealthy: number;\n    unknown: number;\n    avgResponseTime: Milliseconds | undefined;\n  } {\n    const healthCounts = {\n      healthy: 0,\n      degraded: 0,\n      unhealthy: 0,\n      unknown: 0,\n    };\n\n    for (const health of this.health.values()) {\n      healthCounts[health.status]++;\n    }\n\n    // Calculate overall average response time\n    let totalTime = 0;\n    let count = 0;\n    for (const times of this.responseTimes.values()) {\n      for (const time of times) {\n        totalTime += time;\n        count++;\n      }\n    }\n\n    return {\n      totalEndpoints: this.endpoints.size,\n      ...healthCounts,\n      avgResponseTime: count > 0 ? (Math.round(totalTime / count) as Milliseconds) : undefined,\n    };\n  }\n\n  /**\n   * Calculate average response time for an endpoint.\n   */\n  private calculateAvgResponseTime(name: string): Milliseconds | undefined {\n    const times = this.responseTimes.get(name);\n    if (!times || times.length === 0) {\n      return undefined;\n    }\n    return Math.round(times.reduce((a, b) => a + b, 0) / times.length) as Milliseconds;\n  }\n\n  // ===========================================================================\n  // Statistics\n  // ===========================================================================\n\n  private emitEvent(event: EndpointChangeEvent): void {\n    for (const listener of this.listeners) {\n      try {\n        listener(event);\n      } catch (error) {\n        console.error('[EndpointRegistry] Error in change listener:', error);\n      }\n    }\n  }\n}\n\n// =============================================================================\n// Convenience Functions\n// =============================================================================\n\n/**\n * Get the EndpointRegistry singleton instance.\n */\nexport function getEndpointRegistry(): EndpointRegistry {\n  return EndpointRegistry.getInstance();\n}\n\n/**\n * Register an endpoint.\n */\nexport function registerEndpoint(definition: EndpointDefinition): void {\n  getEndpointRegistry().register(definition);\n}\n\n/**\n * Get an endpoint by name.\n */\nexport function getEndpoint(name: string): EndpointDefinition | undefined {\n  return getEndpointRegistry().get(name);\n}\n\n/**\n * Build a URL for an endpoint.\n */\nexport function buildEndpointUrl(\n  name: string,\n  params?: Record<string, string | number>,\n  query?: Record<string, string | number | boolean>\n): string {\n  const registry = getEndpointRegistry();\n  return query ? registry.buildUrlWithQuery(name, params, query) : registry.buildUrl(name, params);\n}\n\n/**\n * Check endpoint health.\n */\nexport function isEndpointHealthy(name: string): boolean {\n  const health = getEndpointRegistry().getHealth(name);\n  return health?.status === 'healthy';\n}\n"],"names":["HttpMethodSchema","z","CacheStrategySchema","EndpointCacheConfigSchema","EndpointRateLimitSchema","EndpointDefinitionSchema","EndpointHealthStatusSchema","EndpointHealthSchema","val","EndpointRegistryImportSchema","DEFAULT_ENDPOINT_HEALTH","UNHEALTHY_THRESHOLD","DEGRADED_THRESHOLD","HEALTH_RECOVERY_THRESHOLD","EndpointRegistry","url","definition","existing","endpoint","DEFAULT_TIMEOUT","DEFAULT_MAX_RETRY_ATTEMPTS","definitions","obj","options","method","auth","prefix","tags","name","pathOrFn","path","tag","pathPattern","regex","updates","updated","responseTime","currentHealth","successCount","times","newStatus","newHealth","reason","failureCount","health","params","key","value","base","query","searchParams","queryString","listener","data","json","rawData","parseError","validationResult","errorMessage","e","healthCounts","totalTime","count","time","a","b","event","error","getEndpointRegistry","registerEndpoint","getEndpoint","buildEndpointUrl","registry","isEndpointHealthy"],"mappings":"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"}