UNPKG

@hakit/core

Version:

A collection of React hooks and helpers for Home Assistant to easily communicate with the Home Assistant WebSocket API.

1 lines 43.3 kB
{"version":3,"file":"Provider-CYRAeT2G.cjs","sources":["../../../node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js","../../../node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js","../../../node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js","../../../node_modules/@emotion/react/jsx-runtime/dist/emotion-react-jsx-runtime.browser.esm.js","../src/HassConnect/Provider.tsx"],"sourcesContent":["'use strict';\n\nvar reactIs = require('react-is');\n\n/**\n * Copyright 2015, Yahoo! Inc.\n * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.\n */\nvar REACT_STATICS = {\n childContextTypes: true,\n contextType: true,\n contextTypes: true,\n defaultProps: true,\n displayName: true,\n getDefaultProps: true,\n getDerivedStateFromError: true,\n getDerivedStateFromProps: true,\n mixins: true,\n propTypes: true,\n type: true\n};\nvar KNOWN_STATICS = {\n name: true,\n length: true,\n prototype: true,\n caller: true,\n callee: true,\n arguments: true,\n arity: true\n};\nvar FORWARD_REF_STATICS = {\n '$$typeof': true,\n render: true,\n defaultProps: true,\n displayName: true,\n propTypes: true\n};\nvar MEMO_STATICS = {\n '$$typeof': true,\n compare: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n type: true\n};\nvar TYPE_STATICS = {};\nTYPE_STATICS[reactIs.ForwardRef] = FORWARD_REF_STATICS;\nTYPE_STATICS[reactIs.Memo] = MEMO_STATICS;\n\nfunction getStatics(component) {\n // React v16.11 and below\n if (reactIs.isMemo(component)) {\n return MEMO_STATICS;\n } // React v16.12 and above\n\n\n return TYPE_STATICS[component['$$typeof']] || REACT_STATICS;\n}\n\nvar defineProperty = Object.defineProperty;\nvar getOwnPropertyNames = Object.getOwnPropertyNames;\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\nvar getPrototypeOf = Object.getPrototypeOf;\nvar objectPrototype = Object.prototype;\nfunction hoistNonReactStatics(targetComponent, sourceComponent, blacklist) {\n if (typeof sourceComponent !== 'string') {\n // don't hoist over string (html) components\n if (objectPrototype) {\n var inheritedComponent = getPrototypeOf(sourceComponent);\n\n if (inheritedComponent && inheritedComponent !== objectPrototype) {\n hoistNonReactStatics(targetComponent, inheritedComponent, blacklist);\n }\n }\n\n var keys = getOwnPropertyNames(sourceComponent);\n\n if (getOwnPropertySymbols) {\n keys = keys.concat(getOwnPropertySymbols(sourceComponent));\n }\n\n var targetStatics = getStatics(targetComponent);\n var sourceStatics = getStatics(sourceComponent);\n\n for (var i = 0; i < keys.length; ++i) {\n var key = keys[i];\n\n if (!KNOWN_STATICS[key] && !(blacklist && blacklist[key]) && !(sourceStatics && sourceStatics[key]) && !(targetStatics && targetStatics[key])) {\n var descriptor = getOwnPropertyDescriptor(sourceComponent, key);\n\n try {\n // Avoid failures from read-only properties\n defineProperty(targetComponent, key, descriptor);\n } catch (e) {}\n }\n }\n }\n\n return targetComponent;\n}\n\nmodule.exports = hoistNonReactStatics;\n","import * as React from 'react';\n\nvar syncFallback = function syncFallback(create) {\n return create();\n};\n\nvar useInsertionEffect = React['useInsertion' + 'Effect'] ? React['useInsertion' + 'Effect'] : false;\nvar useInsertionEffectAlwaysWithSyncFallback = useInsertionEffect || syncFallback;\nvar useInsertionEffectWithLayoutFallback = useInsertionEffect || React.useLayoutEffect;\n\nexport { useInsertionEffectAlwaysWithSyncFallback, useInsertionEffectWithLayoutFallback };\n","import * as React from 'react';\nimport { useContext, forwardRef } from 'react';\nimport createCache from '@emotion/cache';\nimport _extends from '@babel/runtime/helpers/esm/extends';\nimport weakMemoize from '@emotion/weak-memoize';\nimport hoistNonReactStatics from '../_isolated-hnrs/dist/emotion-react-_isolated-hnrs.browser.esm.js';\nimport { getRegisteredStyles, registerStyles, insertStyles } from '@emotion/utils';\nimport { serializeStyles } from '@emotion/serialize';\nimport { useInsertionEffectAlwaysWithSyncFallback } from '@emotion/use-insertion-effect-with-fallbacks';\n\nvar isDevelopment = false;\n\nvar EmotionCacheContext = /* #__PURE__ */React.createContext( // we're doing this to avoid preconstruct's dead code elimination in this one case\n// because this module is primarily intended for the browser and node\n// but it's also required in react native and similar environments sometimes\n// and we could have a special build just for that\n// but this is much easier and the native packages\n// might use a different theme context in the future anyway\ntypeof HTMLElement !== 'undefined' ? /* #__PURE__ */createCache({\n key: 'css'\n}) : null);\n\nvar CacheProvider = EmotionCacheContext.Provider;\nvar __unsafe_useEmotionCache = function useEmotionCache() {\n return useContext(EmotionCacheContext);\n};\n\nvar withEmotionCache = function withEmotionCache(func) {\n return /*#__PURE__*/forwardRef(function (props, ref) {\n // the cache will never be null in the browser\n var cache = useContext(EmotionCacheContext);\n return func(props, cache, ref);\n });\n};\n\nvar ThemeContext = /* #__PURE__ */React.createContext({});\n\nvar useTheme = function useTheme() {\n return React.useContext(ThemeContext);\n};\n\nvar getTheme = function getTheme(outerTheme, theme) {\n if (typeof theme === 'function') {\n var mergedTheme = theme(outerTheme);\n\n return mergedTheme;\n }\n\n return _extends({}, outerTheme, theme);\n};\n\nvar createCacheWithTheme = /* #__PURE__ */weakMemoize(function (outerTheme) {\n return weakMemoize(function (theme) {\n return getTheme(outerTheme, theme);\n });\n});\nvar ThemeProvider = function ThemeProvider(props) {\n var theme = React.useContext(ThemeContext);\n\n if (props.theme !== theme) {\n theme = createCacheWithTheme(theme)(props.theme);\n }\n\n return /*#__PURE__*/React.createElement(ThemeContext.Provider, {\n value: theme\n }, props.children);\n};\nfunction withTheme(Component) {\n var componentName = Component.displayName || Component.name || 'Component';\n var WithTheme = /*#__PURE__*/React.forwardRef(function render(props, ref) {\n var theme = React.useContext(ThemeContext);\n return /*#__PURE__*/React.createElement(Component, _extends({\n theme: theme,\n ref: ref\n }, props));\n });\n WithTheme.displayName = \"WithTheme(\" + componentName + \")\";\n return hoistNonReactStatics(WithTheme, Component);\n}\n\nvar hasOwn = {}.hasOwnProperty;\n\nvar typePropName = '__EMOTION_TYPE_PLEASE_DO_NOT_USE__';\nvar createEmotionProps = function createEmotionProps(type, props) {\n\n var newProps = {};\n\n for (var _key in props) {\n if (hasOwn.call(props, _key)) {\n newProps[_key] = props[_key];\n }\n }\n\n newProps[typePropName] = type; // Runtime labeling is an opt-in feature because:\n\n return newProps;\n};\n\nvar Insertion = function Insertion(_ref) {\n var cache = _ref.cache,\n serialized = _ref.serialized,\n isStringTag = _ref.isStringTag;\n registerStyles(cache, serialized, isStringTag);\n useInsertionEffectAlwaysWithSyncFallback(function () {\n return insertStyles(cache, serialized, isStringTag);\n });\n\n return null;\n};\n\nvar Emotion = /* #__PURE__ */withEmotionCache(function (props, cache, ref) {\n var cssProp = props.css; // so that using `css` from `emotion` and passing the result to the css prop works\n // not passing the registered cache to serializeStyles because it would\n // make certain babel optimisations not possible\n\n if (typeof cssProp === 'string' && cache.registered[cssProp] !== undefined) {\n cssProp = cache.registered[cssProp];\n }\n\n var WrappedComponent = props[typePropName];\n var registeredStyles = [cssProp];\n var className = '';\n\n if (typeof props.className === 'string') {\n className = getRegisteredStyles(cache.registered, registeredStyles, props.className);\n } else if (props.className != null) {\n className = props.className + \" \";\n }\n\n var serialized = serializeStyles(registeredStyles, undefined, React.useContext(ThemeContext));\n\n className += cache.key + \"-\" + serialized.name;\n var newProps = {};\n\n for (var _key2 in props) {\n if (hasOwn.call(props, _key2) && _key2 !== 'css' && _key2 !== typePropName && (!isDevelopment )) {\n newProps[_key2] = props[_key2];\n }\n }\n\n newProps.className = className;\n\n if (ref) {\n newProps.ref = ref;\n }\n\n return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Insertion, {\n cache: cache,\n serialized: serialized,\n isStringTag: typeof WrappedComponent === 'string'\n }), /*#__PURE__*/React.createElement(WrappedComponent, newProps));\n});\n\nvar Emotion$1 = Emotion;\n\nexport { CacheProvider as C, Emotion$1 as E, ThemeContext as T, __unsafe_useEmotionCache as _, ThemeProvider as a, withTheme as b, createEmotionProps as c, hasOwn as h, isDevelopment as i, useTheme as u, withEmotionCache as w };\n","import * as ReactJSXRuntime from 'react/jsx-runtime';\nimport { h as hasOwn, E as Emotion, c as createEmotionProps } from '../../dist/emotion-element-f0de968e.browser.esm.js';\nimport 'react';\nimport '@emotion/cache';\nimport '@babel/runtime/helpers/extends';\nimport '@emotion/weak-memoize';\nimport '../../_isolated-hnrs/dist/emotion-react-_isolated-hnrs.browser.esm.js';\nimport 'hoist-non-react-statics';\nimport '@emotion/utils';\nimport '@emotion/serialize';\nimport '@emotion/use-insertion-effect-with-fallbacks';\n\nvar Fragment = ReactJSXRuntime.Fragment;\nvar jsx = function jsx(type, props, key) {\n if (!hasOwn.call(props, 'css')) {\n return ReactJSXRuntime.jsx(type, props, key);\n }\n\n return ReactJSXRuntime.jsx(Emotion, createEmotionProps(type, props), key);\n};\nvar jsxs = function jsxs(type, props, key) {\n if (!hasOwn.call(props, 'css')) {\n return ReactJSXRuntime.jsxs(type, props, key);\n }\n\n return ReactJSXRuntime.jsxs(Emotion, createEmotionProps(type, props), key);\n};\n\nexport { Fragment, jsx, jsxs };\n","import { useEffect, useCallback, useRef } from \"react\";\n// types\nimport type { Connection, getAuthOptions as AuthOptions, Auth, UnsubscribeFunc } from \"home-assistant-js-websocket\";\n// methods\nimport {\n getAuth,\n createLongLivedTokenAuth,\n createConnection,\n subscribeEntities,\n callService as _callService,\n getStates as _getStates,\n getServices as _getServices,\n getConfig as _getConfig,\n getUser as _getUser,\n ERR_HASS_HOST_REQUIRED,\n ERR_CONNECTION_LOST,\n ERR_CANNOT_CONNECT,\n ERR_INVALID_AUTH,\n ERR_INVALID_HTTPS_TO_HTTP,\n subscribeConfig,\n} from \"home-assistant-js-websocket\";\nimport { isArray, snakeCase } from \"lodash\";\nimport { SnakeOrCamelDomains, DomainService, Locales, CallServiceArgs, Route, ServiceResponse } from \"@typings\";\nimport { saveTokens, loadTokens, clearTokens } from \"./token-storage\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { HassContext, type HassContextProps, useStore } from \"./HassContext\";\n\nexport interface HassProviderProps {\n /** components to render once authenticated, this accepts a child function which will pass if it is ready or not */\n children: (ready: boolean) => React.ReactNode;\n /** the home assistant url */\n hassUrl: string;\n /** if you provide a hassToken you will bypass the login screen altogether - @see https://developers.home-assistant.io/docs/auth_api/#long-lived-access-token */\n hassToken?: string;\n /** the language of the UI to use, this will also control the values used within the `localize` function or `useLocale` / `useLocales` hooks, by default this is retrieved from your home assistant instance. */\n locale?: Locales;\n /** location to render portals @default document.body */\n portalRoot?: HTMLElement;\n /** Will tell the various features like breakpoints, modals and resize events which window to match media on, if serving within an iframe it'll potentially be running in the wrong window */\n windowContext?: Window;\n}\n\nfunction handleError(err: number | string | Error | unknown, hassToken?: string): string {\n const getMessage = () => {\n switch (err) {\n case ERR_INVALID_AUTH:\n return `ERR_INVALID_AUTH: Invalid authentication. ${hassToken ? 'Check your \"Long-Lived Access Token\".' : \"\"}`;\n case ERR_CANNOT_CONNECT:\n return \"ERR_CANNOT_CONNECT: Unable to connect\";\n case ERR_CONNECTION_LOST:\n return \"ERR_CONNECTION_LOST: Lost connection to home assistant.\";\n case ERR_HASS_HOST_REQUIRED:\n return \"ERR_HASS_HOST_REQUIRED: Please enter a Home Assistant URL.\";\n case ERR_INVALID_HTTPS_TO_HTTP:\n return 'ERR_INVALID_HTTPS_TO_HTTP: Cannot connect to Home Assistant instances over \"http://\".';\n default:\n return null;\n }\n };\n const message = getMessage();\n if (message !== null) return message;\n return (\n (\n err as {\n error: string;\n }\n )?.error ||\n (err as Error)?.message ||\n `Unknown Error (${err})`\n );\n}\ntype ConnectionResponse =\n | {\n type: \"success\";\n connection: Connection;\n auth: Auth;\n }\n | {\n type: \"error\";\n error: string;\n }\n | {\n type: \"failed\";\n cannotConnect: true;\n };\n\ntype ConnectionType = \"auth-callback\" | \"user-request\" | \"saved-tokens\" | \"inherited-auth\" | \"provided-token\";\n\nfunction getInheritedConnection(): typeof window.hassConnection | undefined {\n try {\n return window.top?.hassConnection;\n } catch (e) {\n console.error(\"Error getting inherited connection\", e);\n return undefined;\n }\n}\n\nfunction determineConnectionType(hassUrl: string, hassToken?: string): ConnectionType {\n const isAuthCallback = location && location.search.includes(\"auth_callback=1\");\n const hasHassConnection = !!getInheritedConnection();\n const providedToken = !!hassToken;\n // when we have a hass connection, we don't need to validate the tokens\n // so removing the tokens if values are different and we have a connection are not needed.\n const savedTokens = !!loadTokens(hassUrl, false);\n\n switch (true) {\n case isAuthCallback:\n return \"auth-callback\";\n case hasHassConnection:\n return \"inherited-auth\";\n case providedToken:\n return \"provided-token\";\n case savedTokens:\n return \"saved-tokens\";\n default:\n return \"user-request\";\n }\n}\n\nconst tryConnection = async (hassUrl: string, hassToken?: string): Promise<ConnectionResponse> => {\n const connectionType = determineConnectionType(hassUrl, hassToken);\n\n if (connectionType === \"inherited-auth\") {\n try {\n // if we've hit this connect type, the connection will be available\n const { auth, conn } = (await getInheritedConnection()) as { conn: Connection; auth: Auth };\n return {\n type: \"success\",\n connection: conn,\n auth: auth,\n };\n } catch (e) {\n const message = handleError(e, hassToken);\n return {\n type: \"error\",\n error: message,\n };\n }\n }\n if (connectionType === \"provided-token\" && hassToken) {\n try {\n const auth = await createLongLivedTokenAuth(hassUrl, hassToken);\n const connection = await createConnection({ auth });\n return {\n type: \"success\",\n connection,\n auth,\n };\n } catch (e) {\n const message = handleError(e, hassToken);\n return {\n type: \"error\",\n error: message,\n };\n }\n }\n\n const options: AuthOptions = {\n saveTokens,\n loadTokens: () => Promise.resolve(loadTokens(hassUrl)),\n };\n\n if (hassUrl && connectionType === \"user-request\") {\n options.hassUrl = hassUrl;\n if (options.hassUrl === \"\") {\n return {\n type: \"error\",\n error: \"Please enter a Home Assistant URL.\",\n };\n }\n if (options.hassUrl.indexOf(\"://\") === -1) {\n return {\n type: \"error\",\n error: \"Please enter your full URL, including the protocol part (https://).\",\n };\n }\n try {\n new URL(options.hassUrl);\n } catch (err: unknown) {\n console.error(\"Error:\", err);\n return {\n type: \"error\",\n error: \"Invalid URL\",\n };\n }\n }\n let auth: Auth;\n\n try {\n auth = await getAuth(options);\n } catch (err: unknown) {\n if (\n (\n err as {\n error: string;\n }\n )?.error === \"invalid_grant\"\n ) {\n // the refresh token is incorrect and most likely from another browser / instance\n clearTokens();\n return tryConnection(hassUrl, hassToken);\n }\n if (connectionType === \"saved-tokens\" && err === ERR_CANNOT_CONNECT) {\n return {\n type: \"failed\",\n cannotConnect: true,\n };\n }\n return {\n type: \"error\",\n error: handleError(err, hassToken),\n };\n } finally {\n // Clear url if we have a auth callback in url.\n if (location && location.search.includes(\"auth_callback=1\")) {\n history.replaceState(null, \"\", location.pathname);\n }\n }\n let connection: Connection;\n try {\n // create the connection to the websockets\n connection = await createConnection({ auth });\n } catch (err) {\n // In case of saved tokens, silently solve problems.\n if (connectionType === \"saved-tokens\") {\n if (err === ERR_CANNOT_CONNECT) {\n return {\n type: \"failed\",\n cannotConnect: true,\n };\n } else if (err === ERR_INVALID_AUTH) {\n saveTokens(null);\n }\n }\n return {\n type: \"error\",\n error: handleError(err, hassToken),\n };\n }\n return {\n type: \"success\",\n connection,\n auth,\n };\n};\n\nexport function HassProvider({ children, hassUrl, hassToken, portalRoot, windowContext }: HassProviderProps) {\n const entityUnsubscribe = useRef<UnsubscribeFunc | null>(null);\n const authenticated = useRef(false);\n const configUnsubscribe = useRef<UnsubscribeFunc | null>(null);\n const setHash = useStore((store) => store.setHash);\n const _hash = useStore((store) => store.hash);\n const routes = useStore((store) => store.routes);\n const setRoutes = useStore((store) => store.setRoutes);\n const connection = useStore((store) => store.connection);\n const setConnection = useStore((store) => store.setConnection);\n const _connectionRef = useRef<Connection | null>(null);\n const entities = useStore((store) => store.entities);\n const setEntities = useStore((store) => store.setEntities);\n const error = useStore((store) => store.error);\n const setError = useStore((store) => store.setError);\n const cannotConnect = useStore((store) => store.cannotConnect);\n const setCannotConnect = useStore((store) => store.setCannotConnect);\n const setAuth = useStore((store) => store.setAuth);\n const triggerOnDisconnect = useStore((store) => store.triggerOnDisconnect);\n // ready is set internally in the store when we have entities (setEntities does this)\n const ready = useStore((store) => store.ready);\n const setUser = useStore((store) => store.setUser);\n const setReady = useStore((store) => store.setReady);\n const setConfig = useStore((store) => store.setConfig);\n const setHassUrl = useStore((store) => store.setHassUrl);\n const setPortalRoot = useStore((store) => store.setPortalRoot);\n const setWindowContext = useStore((store) => store.setWindowContext);\n\n const getStates = useCallback(async () => (connection === null ? null : await _getStates(connection)), [connection]);\n const getServices = useCallback(async () => (connection === null ? null : await _getServices(connection)), [connection]);\n const getConfig = useCallback(async () => (connection === null ? null : await _getConfig(connection)), [connection]);\n const getUser = useCallback(async () => (connection === null ? null : await _getUser(connection)), [connection]);\n\n useEffect(() => {\n if (portalRoot) setPortalRoot(portalRoot);\n }, [portalRoot, setPortalRoot]);\n\n useEffect(() => {\n if (windowContext) setWindowContext(windowContext);\n }, [windowContext, setWindowContext]);\n\n const reset = useCallback(() => {\n // when the hassUrl changes, reset some properties and re-authenticate\n setAuth(null);\n setConnection(null);\n _connectionRef.current = null;\n setEntities({});\n setConfig(null);\n setError(null);\n setCannotConnect(false);\n setReady(false);\n setRoutes([]);\n setUser(null);\n authenticated.current = false;\n if (configUnsubscribe.current) {\n configUnsubscribe.current();\n configUnsubscribe.current = null;\n }\n if (entityUnsubscribe.current) {\n entityUnsubscribe.current();\n entityUnsubscribe.current = null;\n }\n }, [setAuth, setUser, setCannotConnect, setConfig, setConnection, setEntities, setError, setReady, setRoutes]);\n\n const logout = useCallback(async () => {\n try {\n reset();\n clearTokens();\n if (location) location.reload();\n } catch (err: unknown) {\n console.error(\"Error:\", err);\n setError(\"Unable to log out!\");\n }\n }, [reset, setError]);\n\n const handleConnect = useCallback(async () => {\n // this will trigger on first mount\n const connectionResponse = await tryConnection(hassUrl, hassToken);\n if (connectionResponse.type === \"error\") {\n authenticated.current = false;\n setError(connectionResponse.error);\n } else if (connectionResponse.type === \"failed\") {\n authenticated.current = false;\n setCannotConnect(true);\n } else if (connectionResponse.type === \"success\") {\n // store a reference to the authentication object\n setAuth(connectionResponse.auth);\n // store the connection to pass to the provider\n setConnection(connectionResponse.connection);\n entityUnsubscribe.current = subscribeEntities(connectionResponse.connection, ($entities) => {\n setEntities($entities);\n });\n configUnsubscribe.current = subscribeConfig(connectionResponse.connection, (newConfig) => {\n setConfig(newConfig);\n });\n connectionResponse.connection.addEventListener(\"disconnected\", () => {\n console.error(\"Disconnected from Home Assistant, reconnecting...\");\n triggerOnDisconnect();\n // on disconnection, reset local state\n reset();\n // try to reconnect\n handleConnect();\n });\n connectionResponse.connection.addEventListener(\"reconnect-error\", (_, eventData) => {\n console.error(\"Reconnection error:\", eventData);\n // on connection error, reset local state\n reset();\n });\n _connectionRef.current = connectionResponse.connection;\n _getUser(connectionResponse.connection).then((user) => {\n setUser(user);\n });\n }\n }, [hassUrl, hassToken, triggerOnDisconnect, setError, setUser, setCannotConnect, setAuth, setConnection, setEntities, setConfig, reset]);\n\n useEffect(() => {\n setHassUrl(hassUrl);\n }, [hassUrl, setHassUrl]);\n\n const joinHassUrl = useCallback(\n (path: string) => {\n return new URL(path, connection?.options.auth?.data.hassUrl).toString();\n },\n [connection],\n );\n\n async function callApi<T>(\n endpoint: string,\n options?: RequestInit,\n ): Promise<\n | {\n data: T;\n status: \"success\";\n }\n | {\n data: string;\n status: \"error\";\n }\n > {\n try {\n const response = await fetch(`${hassUrl}/api${endpoint}`, {\n method: \"GET\",\n ...(options ?? {}),\n headers: {\n Authorization: \"Bearer \" + connection?.options.auth?.accessToken,\n \"Content-type\": \"application/json;charset=UTF-8\",\n ...(options?.headers ?? {}),\n },\n });\n if (response.status === 200) {\n const data = await response.json();\n return {\n status: \"success\",\n data,\n };\n }\n return {\n status: \"error\",\n data: response.statusText,\n };\n } catch (e) {\n console.error(\"API Error:\", e);\n return {\n status: \"error\",\n data: `API Request failed for endpoint \"${endpoint}\", follow instructions here: https://shannonhochkins.github.io/ha-component-kit/?path=/docs/core-hooks-usehass-hass-callapi--docs.`,\n };\n }\n }\n\n useEffect(() => {\n if (location.hash === \"\") return;\n if (location.hash.replace(\"#\", \"\") === _hash) return;\n setHash(location.hash);\n }, [setHash, _hash]);\n\n useEffect(() => {\n function onHashChange() {\n setRoutes(\n routes.map((route) => {\n if (route.hash === location.hash.replace(\"#\", \"\")) {\n return {\n ...route,\n active: true,\n };\n }\n return {\n ...route,\n active: false,\n };\n }),\n );\n setHash(location.hash);\n }\n window.addEventListener(\"hashchange\", onHashChange);\n return () => {\n window.removeEventListener(\"hashchange\", onHashChange);\n };\n }, [routes, setHash, setRoutes]);\n\n const addRoute = useCallback(\n (route: Omit<Route, \"active\">) => {\n const exists = routes.find((_route) => _route.hash === route.hash) !== undefined;\n if (!exists && typeof window !== \"undefined\") {\n // if the current has value is the same as the hash, we're active\n const hashWithoutPound = window.location.hash.replace(\"#\", \"\");\n const active = hashWithoutPound !== \"\" && hashWithoutPound === route.hash;\n setRoutes([\n ...routes,\n {\n ...route,\n active,\n } satisfies Route,\n ]);\n }\n },\n [routes, setRoutes],\n );\n\n const getRoute = useCallback(\n (hash: string) => {\n const route = routes.find((route) => route.hash === hash);\n return route || null;\n },\n [routes],\n );\n\n const getAllEntities = useCallback(() => entities, [entities]);\n\n const callService = useCallback(\n async <ResponseType extends object, T extends SnakeOrCamelDomains, M extends DomainService<T>, R extends boolean>({\n domain,\n service,\n serviceData,\n target: _target,\n returnResponse,\n }: CallServiceArgs<T, M, R>): Promise<R extends true ? ServiceResponse<ResponseType> : void> => {\n const target =\n typeof _target === \"string\" || isArray(_target)\n ? {\n entity_id: _target,\n }\n : _target;\n if (typeof service !== \"string\") {\n throw new Error(\"service must be a string\");\n }\n if (connection && ready) {\n try {\n const result = await _callService(\n connection,\n snakeCase(domain),\n snakeCase(service),\n // purposely cast here as we know it's correct\n serviceData as object,\n target,\n returnResponse,\n );\n if (returnResponse) {\n // Return the result if returnResponse is true\n return result as R extends true ? ServiceResponse<ResponseType> : never;\n }\n // Otherwise, return void\n return undefined as R extends true ? never : void;\n } catch (e) {\n // TODO - raise error to client here\n console.log(\"Error:\", e);\n }\n }\n return undefined as R extends true ? never : void;\n },\n [connection, ready],\n );\n\n useEffect(() => {\n return () => {\n reset();\n };\n }, [reset]);\n\n const debounceConnect = useDebouncedCallback(\n async () => {\n try {\n if (authenticated.current) {\n reset();\n }\n authenticated.current = true;\n await handleConnect();\n } catch (e) {\n const message = handleError(e);\n setError(`Unable to connect to Home Assistant, please check the URL: \"${message}\"`);\n }\n },\n 25,\n {\n leading: true,\n trailing: false,\n },\n );\n\n useEffect(() => {\n // authenticate with ha\n debounceConnect();\n }, [debounceConnect]);\n\n if (cannotConnect) {\n return (\n <p>\n Unable to connect to ${loadTokens(hassUrl)!.hassUrl}, refresh the page and try again, or <a onClick={logout}>Logout</a>.\n </p>\n );\n }\n return (\n <HassContext.Provider\n value={{\n useStore,\n logout,\n addRoute,\n getRoute,\n getStates,\n getServices,\n getConfig,\n getUser,\n callApi,\n getAllEntities,\n // cast here we don't have to redefine all the overloads, might fix later\n callService: callService as HassContextProps[\"callService\"],\n joinHassUrl,\n }}\n >\n {error === null ? children(ready) : error}\n </HassContext.Provider>\n );\n}\n"],"names":["reactIs","require$$0","REACT_STATICS","KNOWN_STATICS","FORWARD_REF_STATICS","MEMO_STATICS","TYPE_STATICS","getStatics","component","defineProperty","getOwnPropertyNames","getOwnPropertySymbols","getOwnPropertyDescriptor","getPrototypeOf","objectPrototype","hoistNonReactStatics","targetComponent","sourceComponent","blacklist","inheritedComponent","keys","targetStatics","sourceStatics","i","key","descriptor","hoistNonReactStatics_cjs","syncFallback","create","useInsertionEffect","React","useInsertionEffectAlwaysWithSyncFallback","EmotionCacheContext","createCache","withEmotionCache","func","forwardRef","props","ref","cache","useContext","ThemeContext","hasOwn","typePropName","createEmotionProps","type","newProps","_key","Insertion","_ref","serialized","isStringTag","registerStyles","insertStyles","Emotion","cssProp","WrappedComponent","registeredStyles","className","getRegisteredStyles","serializeStyles","_key2","Emotion$1","Fragment","ReactJSXRuntime","jsx","jsxs","handleError","err","hassToken","message","ERR_INVALID_AUTH","ERR_CANNOT_CONNECT","ERR_CONNECTION_LOST","ERR_HASS_HOST_REQUIRED","ERR_INVALID_HTTPS_TO_HTTP","getInheritedConnection","e","determineConnectionType","hassUrl","isAuthCallback","hasHassConnection","providedToken","savedTokens","loadTokens","tryConnection","connectionType","auth","conn","createLongLivedTokenAuth","createConnection","options","saveTokens","getAuth","clearTokens","connection","HassProvider","children","portalRoot","windowContext","entityUnsubscribe","useRef","authenticated","configUnsubscribe","setHash","useStore","store","_hash","routes","setRoutes","setConnection","_connectionRef","entities","setEntities","error","setError","cannotConnect","setCannotConnect","setAuth","triggerOnDisconnect","ready","setUser","setReady","setConfig","setHassUrl","setPortalRoot","setWindowContext","getStates","useCallback","_getStates","getServices","_getServices","getConfig","_getConfig","getUser","_getUser","useEffect","reset","logout","handleConnect","connectionResponse","subscribeEntities","$entities","subscribeConfig","newConfig","_","eventData","user","joinHassUrl","path","callApi","endpoint","response","onHashChange","route","addRoute","_route","hashWithoutPound","active","getRoute","hash","getAllEntities","callService","domain","service","serviceData","_target","returnResponse","target","isArray","result","_callService","snakeCase","debounceConnect","useDebouncedCallback","HassContext"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}