Hooks

useDocyrusInventory

Shared app-utils inventory cache for Docyrus metadata (apps, data sources with fields/enums/views/forms, users, brands, preferences) plus a post-sign-in load() warm-up hook that drives an application loading dialog.

Installation

pnpm dlx @docyrus/cli add @docyrus/hooks-use-docyrus-inventory
Required Packages(2 packages)
pnpm add @docyrus/app-utils @docyrus/api-client

This module ships two named exports:

  • getSharedDocyrusInventory(client) — returns the process-wide shared InventoryClient for a given RestApiClient, creating it on first use (memoized in a WeakMap keyed by client). Pass the result into createDataSourceClient / createDataViewClient / createDataFormClient ({ inventory }) so every client shares one in-memory cache. null in → null out.
  • useDocyrusInventoryLoader(options) — headless React hook that runs inventory.load() once per client (StrictMode-safe) right after sign-in, exposing determinate progress + status so a host app can render a loading dialog before routing to the home page.

Why this exists

The @docyrus/app-utils inventory (createInventoryClient) caches everything a Docyrus app needs at startup — apps, data sources (with embedded views / forms / fields, and enums on select-type fields), users, brands, and tenant preferences — in one GET /v1/apps/data-sources?expand=views,forms,fields request (plus a request each for users / brands / preferences). Because the cache lives in the returned client's closure, a single shared instance is what lets:

  1. a post-sign-in load() warm-up populate it behind a progress bar, and
  2. every inventory-backed hook (useDocyrusFormView, useDocyrusDataGrid, useDocyrusDataViewSelect, …) read tenant metadata from that same warm cache instead of re-fetching per mount.

getSharedDocyrusInventory is the single source of that instance; the Docyrus hooks call it internally, so warming the cache once makes their schema / enum / view / form / relation reads cache hits.

getSharedDocyrusInventory(client)

import { getSharedDocyrusInventory } from '@docyrus/ui/library/hooks/use-docyrus-inventory';
import { createDataSourceClient } from '@docyrus/app-utils';

const inventory = getSharedDocyrusInventory(apiClient);
const dataSources = createDataSourceClient(apiClient, { inventory });

// No `expand` → served from the shared cache (fields incl. enums, views, forms embedded)
const contacts = await dataSources.getBySlug('crm', 'contacts');
ParameterTypeDescription
clientRestApiClient | null | undefinedThe authenticated API client.

Returns: InventoryClient (or null when client is nullish).

useDocyrusInventoryLoader(options)

Runs inventory.load() once, as soon as it is enabled and a client exists, and re-runs automatically when the client identity changes (e.g. a tenant switch that rebuilds the client). Failures do not throw — status becomes 'error' and reload() retries; the app can still run (inventory-backed reads fall back to the API).

import { useDocyrusAuth } from '@docyrus/signin';
import { useDocyrusInventoryLoader } from '@docyrus/ui/library/hooks/use-docyrus-inventory';

function InventoryGate({ children }) {
  const { client, status } = useDocyrusAuth();
  const { status: loadStatus, progress, error, reload } = useDocyrusInventoryLoader({
    client,
    enabled: status === 'authenticated'
  });

  if (loadStatus === 'ready') return children;

  return (
    <LoadingDialog
      message={progress?.message}
      percent={Math.round((progress?.ratio ?? 0) * 100)}
      error={error}
      onRetry={reload} />
  );
}

Options

OptionTypeDefaultDescription
clientRestApiClient | null | undefined—The authenticated API client. The loader waits until this is set.
enabledbooleantrueGate the warm-up (e.g. only once authenticated). Still requires a non-null client.
includeInventoryLoadStepId[]['apps','data-sources','users','brands','preferences']Which tenant-wide steps to warm. Drop 'users' when the signed-in user may lack the Users.Read.All scope.
configAppIdsstring[]VITE_APP_ID (if set)App ids whose config + user-config to warm. Pass [] to skip.
forcebooleantrueInvalidate caches before loading so the warm-up issues fresh network calls.

Result

FieldTypeDescription
inventoryInventoryClient | nullThe shared inventory for the current client.
status'idle' | 'loading' | 'ready' | 'error'Warm-up lifecycle.
progressInventoryLoadProgress | nullLatest progress event — drive a determinate bar with progress.ratio.
errorunknownPresent when status === 'error'.
resultInventoryLoadResult | nullThe loaded payload once ready.
isLoadingbooleantrue while warming.
isReadybooleantrue once warmed successfully.
reload() => voidRe-run the warm-up (Retry button, or after a tenant switch).

On this page