Horizon Framework

Function Installed

Components that depend on a connected function from another package (e.g. a timesheets console depending on the timesheets ingestion function from workforce-management) need a way to check whether that function is installed on the current tenant, so they can degrade gracefully when it's missing. This is checked via GET /pkg/installed.

React Hook: useFunctionInstalled

Use useFunctionInstalled inside a React component to reactively check whether a connected function is installed. installed is undefined while loading (or if the request fails); otherwise it's true or false.

import { useFunctionInstalled } from '@skedulo/horizon-core'

const MyComponent = () => {
  const { installed, loading, error } = useFunctionInstalled('timesheets')

  if (loading) return <div>Loading...</div>
  if (error) return <div>Could not determine feature availability</div>
  if (!installed) return <div>Feature unavailable</div>

  return <TimesheetsConsole />
}

Parameters

ParameterTypeDescription
functionNamestringThe connected function name to check
optionsobjectOptional settings
options.bypassCacheboolean (default: false)When true, skips the cache and always fetches fresh data

Return Value

PropertyTypeDescription
installedboolean | undefinedWhether the function is installed; undefined while loading or on error
loadingbooleantrue while the request is in flight
errorError | undefinedThe error from the request, if it failed

Standalone Function: fetchInstalledPackages

Use fetchInstalledPackages outside of React components when you need the raw list of installed packages imperatively. Combine it with isFunctionInstalled to get the same verdict the hook computes.

import {
  fetchInstalledPackages,
  isFunctionInstalled,
} from '@skedulo/horizon-core'

const packages = await fetchInstalledPackages(apiClient)
const installed = isFunctionInstalled(packages, 'timesheets')

Caching

The installed packages list is cached in memory (module-level, no persistence, no stale-while-revalidate) so that multiple components checking different function names on the same page share a single request rather than each firing their own. Pass bypassCache: true to skip the cache and always fetch fresh data.

Installed Verdict

A function is considered installed when some entry in the response has status === "Installed" and either:

  • its metadata.components.functions.items array includes the function name, or
  • when items is absent, its package name matches the function name.

Malformed or partial entries (missing metadata, components, or functions) are tolerated rather than throwing: since these leave items absent, they fall through to the package-name comparison above, not treated as "not exposing that function".