{"version":3,"file":"useEndpoint.mjs","sources":["../../../../../src/lib/core/config/hooks/useEndpoint.ts"],"sourcesContent":["/**\n * @fileoverview React hooks for the endpoint registry.\n *\n * These hooks provide easy access to endpoint configuration and health\n * with automatic re-rendering on changes.\n *\n * @module core/config/hooks/useEndpoint\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { ms } from '../../../shared/type-utils';\n\nimport type { EndpointChangeEvent, EndpointDefinition, EndpointHealth } from '../types';\n\nimport { getEndpoint, getEndpointRegistry } from '../registry/EndpointRegistry';\n\n// =============================================================================\n// Endpoint Access Hooks\n// =============================================================================\n\n/**\n * Hook to access an endpoint by name.\n *\n * @param name - The endpoint name\n *\n * @example\n * ```tsx\n * function UserList() {\n *   const endpoint = useEndpoint('users.list');\n *\n *   if (!endpoint) {\n *     return <div>Endpoint not found</div>;\n *   }\n *\n *   return <div>Path: {endpoint.path}</div>;\n * }\n * ```\n */\nexport function useEndpoint(name: string): EndpointDefinition | undefined {\n  const [endpoint, setEndpoint] = useState(() => getEndpoint(name));\n  const nameRef = useRef(name);\n\n  useEffect(() => {\n    // Update state only if name changed\n    if (nameRef.current !== name) {\n      queueMicrotask(() => {\n        nameRef.current = name;\n        setEndpoint(getEndpoint(name));\n      });\n    }\n\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe((event) => {\n      if (event.name === name) {\n        setEndpoint(event.endpoint);\n      }\n    });\n  }, [name]);\n\n  return endpoint;\n}\n\n/**\n * Hook to get all endpoints.\n */\nexport function useAllEndpoints(): readonly EndpointDefinition[] {\n  const [endpoints, setEndpoints] = useState<readonly EndpointDefinition[]>(() =>\n    getEndpointRegistry().getAll()\n  );\n\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe(() => {\n      setEndpoints(registry.getAll());\n    });\n  }, []);\n\n  return endpoints;\n}\n\n/**\n * Hook to get endpoints by tag.\n */\nexport function useEndpointsByTag(tag: string): readonly EndpointDefinition[] {\n  const [endpoints, setEndpoints] = useState<readonly EndpointDefinition[]>(() =>\n    getEndpointRegistry().getByTag(tag)\n  );\n\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe(() => {\n      setEndpoints(registry.getByTag(tag));\n    });\n  }, [tag]);\n\n  return endpoints;\n}\n\n// =============================================================================\n// URL Building Hooks\n// =============================================================================\n\n/**\n * Hook to build an endpoint URL.\n *\n * @param name - The endpoint name\n * @param params - Path parameters\n * @param query - Query parameters\n *\n * @example\n * ```tsx\n * function UserDetail({ userId }: { userId: string }) {\n *   const url = useEndpointUrl('users.detail', { id: userId });\n *   // url = '/users/123'\n *\n *   return <div>URL: {url}</div>;\n * }\n * ```\n */\nexport function useEndpointUrl(\n  name: string,\n  params?: Record<string, string | number>,\n  query?: Record<string, string | number | boolean>\n): string | null {\n  return useMemo(() => {\n    try {\n      const registry = getEndpointRegistry();\n      return query\n        ? registry.buildUrlWithQuery(name, params, query)\n        : registry.buildUrl(name, params);\n    } catch {\n      return null;\n    }\n  }, [name, params, query]);\n}\n\n/**\n * Hook to get a URL builder function for an endpoint.\n *\n * @param name - The endpoint name\n *\n * @example\n * ```tsx\n * function UserList() {\n *   const buildUserUrl = useEndpointUrlBuilder('users.detail');\n *\n *   return (\n *     <ul>\n *       {users.map((user) => (\n *         <li key={user.id}>\n *           <a href={buildUserUrl({ id: user.id })}>{user.name}</a>\n *         </li>\n *       ))}\n *     </ul>\n *   );\n * }\n * ```\n */\nexport function useEndpointUrlBuilder(\n  name: string\n): (\n  params?: Record<string, string | number>,\n  query?: Record<string, string | number | boolean>\n) => string | null {\n  return useCallback(\n    (params, query) => {\n      try {\n        const registry = getEndpointRegistry();\n        return query\n          ? registry.buildUrlWithQuery(name, params, query)\n          : registry.buildUrl(name, params);\n      } catch {\n        return null;\n      }\n    },\n    [name]\n  );\n}\n\n// =============================================================================\n// Health Monitoring Hooks\n// =============================================================================\n\n/**\n * Hook to monitor endpoint health.\n *\n * @param name - The endpoint name\n *\n * @example\n * ```tsx\n * function EndpointStatus({ name }: { name: string }) {\n *   const health = useEndpointHealth(name);\n *\n *   if (!health) {\n *     return <span>Unknown</span>;\n *   }\n *\n *   return (\n *     <span className={health.status}>\n *       {health.status} ({health.avgResponseTime}ms)\n *     </span>\n *   );\n * }\n * ```\n */\nexport function useEndpointHealth(name: string): EndpointHealth | undefined {\n  const [health, setHealth] = useState<EndpointHealth | undefined>(() =>\n    getEndpointRegistry().getHealth(name)\n  );\n  const nameRef = useRef(name);\n\n  useEffect(() => {\n    // Update state only if name changed\n    if (nameRef.current !== name) {\n      queueMicrotask(() => {\n        nameRef.current = name;\n        const registry = getEndpointRegistry();\n        setHealth(registry.getHealth(name));\n      });\n    }\n\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe((event) => {\n      if (event.name === name && event.type === 'health-changed') {\n        setHealth(event.newHealth);\n      }\n    });\n  }, [name]);\n\n  return health;\n}\n\n/**\n * Hook to check if an endpoint is healthy.\n */\nexport function useIsEndpointHealthy(name: string): boolean {\n  const health = useEndpointHealth(name);\n  return health?.status === 'healthy';\n}\n\n/**\n * Hook to get all unhealthy endpoints.\n */\nexport function useUnhealthyEndpoints(): readonly string[] {\n  const [unhealthy, setUnhealthy] = useState<readonly string[]>(() =>\n    getEndpointRegistry().getUnhealthyEndpoints()\n  );\n\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe((event) => {\n      if (event.type === 'health-changed') {\n        setUnhealthy(registry.getUnhealthyEndpoints());\n      }\n    });\n  }, []);\n\n  return unhealthy;\n}\n\n/**\n * Hook to get all degraded endpoints.\n */\nexport function useDegradedEndpoints(): readonly string[] {\n  const [degraded, setDegraded] = useState<readonly string[]>(() =>\n    getEndpointRegistry().getDegradedEndpoints()\n  );\n\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe((event) => {\n      if (event.type === 'health-changed') {\n        setDegraded(registry.getDegradedEndpoints());\n      }\n    });\n  }, []);\n\n  return degraded;\n}\n\n// =============================================================================\n// Statistics Hooks\n// =============================================================================\n\n/**\n * Hook to get endpoint registry statistics.\n */\nexport function useEndpointStats(): ReturnType<\n  typeof getEndpointRegistry\n>['getStats'] extends () => infer R\n  ? R\n  : never {\n  const [stats, setStats] = useState(() => getEndpointRegistry().getStats());\n\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe(() => {\n      setStats(registry.getStats());\n    });\n  }, []);\n\n  return stats;\n}\n\n// =============================================================================\n// Change Tracking Hooks\n// =============================================================================\n\n/**\n * Hook to track endpoint changes.\n *\n * @param onChangeCallback - Callback to invoke when endpoints change\n */\nexport function useEndpointChangeTracking(\n  onChangeCallback: (event: EndpointChangeEvent) => void\n): void {\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe(onChangeCallback);\n  }, [onChangeCallback]);\n}\n\n/**\n * Hook to get the last endpoint change.\n */\nexport function useLastEndpointChange(): EndpointChangeEvent | null {\n  const [lastChange, setLastChange] = useState<EndpointChangeEvent | null>(null);\n\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n\n    return registry.subscribe((event) => {\n      setLastChange(event);\n    });\n  }, []);\n\n  return lastChange;\n}\n\n// =============================================================================\n// Registration Hooks\n// =============================================================================\n\n/**\n * Hook to register an endpoint on mount and unregister on unmount.\n *\n * Useful for dynamic endpoints in feature modules.\n *\n * @param definition - The endpoint definition\n * @param autoRemove - Whether to remove on unmount (default: true)\n *\n * @example\n * ```tsx\n * function FeatureModule() {\n *   // Registers on mount, removes on unmount\n *   useRegisterEndpoint({\n *     name: 'feature.custom',\n *     path: '/feature/custom',\n *     method: 'GET',\n *     auth: true,\n *   });\n *\n *   return <div>Feature Module</div>;\n * }\n * ```\n */\nexport function useRegisterEndpoint(definition: EndpointDefinition, autoRemove = true): void {\n  useEffect(() => {\n    const registry = getEndpointRegistry();\n    registry.register(definition);\n\n    return () => {\n      if (autoRemove) {\n        registry.remove(definition.name);\n      }\n    };\n  }, [definition, autoRemove]);\n}\n\n/**\n * Hook to get endpoint management functions.\n */\nexport function useEndpointRegistry(): {\n  registry: ReturnType<typeof getEndpointRegistry>;\n  register: (definition: EndpointDefinition) => void;\n  update: (name: string, updates: Partial<EndpointDefinition>) => void;\n  remove: (name: string) => void;\n  markHealthy: (name: string, responseTime?: number) => void;\n  markUnhealthy: (name: string, reason: string) => void;\n} {\n  const registry = useMemo(() => getEndpointRegistry(), []);\n\n  const register = useCallback(\n    (definition: EndpointDefinition) => {\n      registry.register(definition);\n    },\n    [registry]\n  );\n\n  const update = useCallback(\n    (name: string, updates: Partial<EndpointDefinition>) => {\n      registry.update(name, updates);\n    },\n    [registry]\n  );\n\n  const remove = useCallback(\n    (name: string) => {\n      registry.remove(name);\n    },\n    [registry]\n  );\n\n  const markHealthy = useCallback(\n    (name: string, responseTime?: number) => {\n      registry.markHealthy(name, responseTime != null ? ms(responseTime) : undefined);\n    },\n    [registry]\n  );\n\n  const markUnhealthy = useCallback(\n    (name: string, reason: string) => {\n      registry.markUnhealthy(name, reason);\n    },\n    [registry]\n  );\n\n  return {\n    registry,\n    register,\n    update,\n    remove,\n    markHealthy,\n    markUnhealthy,\n  };\n}\n"],"names":["useEndpoint","name","endpoint","setEndpoint","useState","getEndpoint","nameRef","useRef","useEffect","getEndpointRegistry","event","useAllEndpoints","endpoints","setEndpoints","registry","useEndpointsByTag","tag","useEndpointUrl","params","query","useMemo","useEndpointUrlBuilder","useCallback","useEndpointHealth","health","setHealth","useIsEndpointHealthy","useUnhealthyEndpoints","unhealthy","setUnhealthy","useDegradedEndpoints","degraded","setDegraded","useEndpointStats","stats","setStats","useEndpointChangeTracking","onChangeCallback","useLastEndpointChange","lastChange","setLastChange","useRegisterEndpoint","definition","autoRemove","useEndpointRegistry","register","update","updates","remove","markHealthy","responseTime","ms","markUnhealthy","reason"],"mappings":"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"}