# zidane-ui/app/headless

Import: `import { … } from 'zidane-ui/app/headless'`. Source: [ui/src/app/headless/index.ts](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/index.ts).

## Functions

### `createResourceStore`

Function.

A new resource store over an invalidation source.

```ts
function createResourceStore<Topic extends string = string>(
  options?: ResourceStoreOptions<Topic>,
): ResourceStore<Topic>
```

**Type parameters**

- `Topic` (`extends string`, default `string`)

**Parameters**

- `options?` (`ResourceStoreOptions<Topic>`, default `{}`): The event source, the watched topics and the focus signal.

**Returns** `ResourceStore<Topic>`

Source: [ui/src/app/headless/resource.ts:199](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L199)

### `readableResource`

Function.

One resource of a store as a readable value (`get` + `subscribe`, the shape hosts hand to components):
subscribing keeps it live like a mounted reader. Both methods keep their identity.

```ts
function readableResource<T, Topic extends string = string>(
  store: ResourceStore<Topic>,
  spec: ResourceSpec<T, Topic>,
): { get(): ResourceSnapshot<T>; subscribe(listener: () => void): () => void }
```

**Type parameters**

- `T`
- `Topic` (`extends string`, default `string`)

**Parameters**

- `store` (`ResourceStore<Topic>`): The store holding it.
- `spec` (`ResourceSpec<T, Topic>`): The resource.

**Returns** `{ get(): ResourceSnapshot<T>; subscribe(listener: () => void): () => void }`

Source: [ui/src/app/headless/resource.ts:439](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L439)

### `resourceEventMatches`

Function.

Whether `event` concerns a resource with `options`: its topic is listed, and absent fields on either side
mean "any"; folders match when one holds the other (a repo root vs a subfolder).

```ts
function resourceEventMatches<Topic extends string>(
  event: ResourceEvent<Topic>,
  options: ResourceOptions<Topic>,
): boolean
```

**Type parameters**

- `Topic` (`extends string`)

**Parameters**

- `event` (`ResourceEvent<Topic>`): An invalidation event.
- `options` (`ResourceOptions<Topic>`): A resource's options.

**Returns** `boolean`

Source: [ui/src/app/headless/resource.ts:160](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L160)

## Constants

### `IDLE_RESOURCE`

Constant.

What a null spec reads.

```ts
const IDLE_RESOURCE: ResourceSnapshot<never>
```

Source: [ui/src/app/headless/resource.ts:137](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L137)

## Interfaces

### `AppHost`

Interface.

Every area's host an app offers. An area whose host is absent is not shown.

```ts
interface AppHost
```

**Properties**

- `appearance?` (`AppearanceHost`): Where the appearance preferences live, the extra themes, the pre-paint snapshot and the window effects. Absent: the app applies no appearance (the stylesheet's defaults).
- `approvals?` (`ApprovalsHost`): Tool approvals (safe mode): the pending approvals, the decisions and the safelist. Absent: no approval UI.
- `chat?` (`ChatHost`): The chat area: sessions, transcripts, sending and interactions. Absent: no chat.
- `composer?` (`ComposerHost`): The rich composer's host: shared drafts, completions, ghost text and next-prompt suggestions. Absent: those stay off (`zidane-ui/chat/rich-composer`).
- `extensions?` (`ExtensionsHost`): What the extensions behind the app contribute (slots, screens, renderers, dialogs, settings pages, webviews) and the way back to them. Absent: no extension UI.
- `files?` (`FilesHost`): The Files and Diffs tabs' host: listing, reading, writing and searching files, git status, the working-tree diff and the editor preferences. Absent: no Files or Diffs tab.
- `git?` (`GitHost`): The git area's host: branches and pull requests, worktrees, environment kinds and remote folders. Absent: no branch menu, no remote folder picker.
- `keybindings?` (`KeybindingsHost`): Where the user's keybinding overrides live. Absent: the default bindings.
- `machines?` (`MachinesHost`): Which agent hosts the app talks to and how they are: servers, machines, self-update, tokens, the local daemon. Absent: no host status, banners or server settings.
- `onboarding?` (`OnboardingHost`): The setup wizard's host: detection, settings, sign-in and the commit. Absent: no onboarding.
- `palette?` (`PaletteHost`): The command palette's host: commands, files, extension items, settings and recents. Absent: the palette lists only the app's own sources.
- `session?` (`SessionHost`): The session panels' host: todos, the message queue and artifacts. Absent: no session panels.
- `settings?` (`SettingsHost`): The zidane settings document: read, written through when this connection may. Absent: no settings rows.
- `sidebar?` (`SidebarHost`): The session sidebar's platform members: Finder, standalone windows, environment commands. Absent: those menu rows hide.
- `terminal?` (`TerminalHost`): The terminals: listing, opening and viewing them per scope. Absent: no terminal drawer or tab.
- `workspace?` (`WorkspaceHost<WorkspaceScope>`): Where the side panel's layouts live, and the extension panels. Absent: layouts last as long as the page, no extension panels.

Source: [ui/src/app/headless/app-host.ts:28](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/app-host.ts#L28)

### `ResourceEvent`

Interface.

An invalidation event: a topic, and the scope it is about (absent fields: any).

```ts
interface ResourceEvent<Topic extends string = string> extends ResourceScope
```

**Type parameters**

- `Topic` (`extends string`, default `string`)

**Properties**

- `cwd?` (`string`, from `ResourceScope`): The folder (an event about a folder that holds it, or that it holds, concerns it).
- `hostId?` (`string`, from `ResourceScope`): The host (this computer's or a server's id).
- `sessionId?` (`string`, from `ResourceScope`): The session.
- `topic` (`Topic`): What changed.

Source: [ui/src/app/headless/resource.ts:46](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L46)

### `ResourceInvalidation`

Interface.

Where invalidation events come from (an app's IPC, a server's signals).

```ts
interface ResourceInvalidation<Topic extends string = string>
```

**Type parameters**

- `Topic` (`extends string`, default `string`)

**Properties**

- `onInvalidate` (`(listener: (event: ResourceEvent<Topic>) => void) => () => void`): Calls `listener` with each event; returns the unsubscribe.
- `unwatch?` (`(topic: Topic, cwd: string) => unknown`): Stop emitting it.
- `watch?` (`(topic: Topic, cwd: string) => unknown`): Start emitting a watched topic for a folder.

Source: [ui/src/app/headless/resource.ts:91](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L91)

### `ResourceOptions`

Interface.

How a resource stays current.

```ts
interface ResourceOptions<Topic extends string = string>
```

**Type parameters**

- `Topic` (`extends string`, default `string`)

**Properties**

- `revalidateOnFocus?` (`boolean`): Refetch (when old) as the window regains focus.
- `scope?` (`ResourceScope`): What the data is about.
- `topics?` (`readonly Topic[]`): Topics whose events stale this resource.
- `ttl?` (`number`): A new reader refetches data older than this (ms).

Source: [ui/src/app/headless/resource.ts:52](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L52)

### `ResourceScope`

Interface.

What a resource's data is about; an event naming another folder, server or session leaves it alone.

```ts
interface ResourceScope
```

**Properties**

- `cwd?` (`string`): The folder (an event about a folder that holds it, or that it holds, concerns it).
- `hostId?` (`string`): The host (this computer's or a server's id).
- `sessionId?` (`string`): The session.

Source: [ui/src/app/headless/resource.ts:36](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L36)

### `ResourceSnapshot`

Interface.

A resource as read: immutable, replaced only when something changed.

```ts
interface ResourceSnapshot<T>
```

**Type parameters**

- `T`

**Properties**

- `data` (`T | undefined`): The last data fetched.
- `error` (`unknown`): The last fetch's error.
- `refresh` (`() => Promise<void>`): Refetch now; keeps its identity for the life of the entry.
- `stale` (`boolean`): `data` is known out of date (invalidated, refetching).
- `status` (`ResourceStatus`): See [`ResourceStatus`](https://zidane.si/docs/reference/ui-app-headless.md#ResourceStatus).

Source: [ui/src/app/headless/resource.ts:77](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L77)

### `ResourceSpec`

Interface.

One kind of data: the same key and fetcher wherever it is read.

```ts
interface ResourceSpec<T, Topic extends string = string>
```

**Type parameters**

- `T`
- `Topic` (`extends string`, default `string`)

**Properties**

- `fetcher` (`() => Promise<T>`): Reads the data.
- `key` (`ResourceKey`): The resource's identity.
- `options?` (`ResourceOptions<Topic>`): How it stays current; the first read of a key decides.

Source: [ui/src/app/headless/resource.ts:64](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L64)

### `ResourceStore`

Interface.

A store of resources; see the top of this file.

```ts
interface ResourceStore<Topic extends string = string>
```

**Type parameters**

- `Topic` (`extends string`, default `string`)

**Properties**

- `fetch` (`<T>(spec: ResourceSpec<T, Topic>) => Promise<T>`): The data now: a fresh value is reused and an in-flight fetch joined. Rejects with the fetch's error.
- `keyOf` (`(key: ResourceKey) => string`): The serialized form of a key: what `ResourceStore.peekKey` takes.
- `peek` (`<T>(spec: ResourceSpec<T, Topic>) => ResourceSnapshot<T>`): The snapshot `spec` holds now, without reading or subscribing.
- `peekKey` (`(id: string) => ResourceSnapshot<unknown>`): The snapshot a serialized key holds now (`loading` before anyone subscribed).
- `reset` (`() => void`): Forget every entry and listener, and unhook the event source (tests).
- `subscribe` (`<T>(spec: ResourceSpec<T, Topic>, onChange: (snapshot: ResourceSnapshot<T>) => void) => () => void`): Keep `spec` live; `onChange` gets the current snapshot now and every new one. Returns the unsubscribe.
- `subscribeInvalidation` (`(options: ResourceOptions<Topic>, listener: (event: ResourceEvent<Topic>) => void) => () => void`): `listener` hears the events `options` matches (as a resource with them would), watched topics watched meanwhile.
- `watch` (`<T>(spec: ResourceSpec<T, Topic>, listener: () => void) => () => void`): Keep `spec` live; `listener` hears each new snapshot (not the current one). Returns the unsubscribe.

Source: [ui/src/app/headless/resource.ts:114](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L114)

### `ResourceStoreOptions`

Interface.

Options of [`createResourceStore`](https://zidane.si/docs/reference/ui-app-headless.md#createResourceStore).

```ts
interface ResourceStoreOptions<Topic extends string = string>
```

**Type parameters**

- `Topic` (`extends string`, default `string`)

**Properties**

- `invalidation?` (`() => ResourceInvalidation<Topic> | undefined`): The event source, read when the store first needs it (and again after `reset`), so an app can
  install it after the store is made. Absent or `undefined`: no invalidation, only TTL and refresh.
- `onFocus?` (`(listener: () => void) => () => void`): Calls `listener` when the window regains focus; returns the unsubscribe. Default: the window's `focus` event.
- `watchedTopics?` (`readonly Topic[]`): Topics only emitted while watched for a folder.

Source: [ui/src/app/headless/resource.ts:101](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L101)

## Types

### `ResourceKey`

Type.

A resource's identity: a string, or values serialized as JSON.

```ts
type ResourceKey = string | readonly unknown[]
```

Source: [ui/src/app/headless/resource.ts:33](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L33)

### `ResourceStatus`

Type.

Where a resource is: `idle` (nothing asked), `loading` (the first fetch runs), then the last fetch's outcome.

```ts
type ResourceStatus = 'idle' | 'loading' | 'success' | 'error'
```

Source: [ui/src/app/headless/resource.ts:74](https://github.com/Tahul/zidane/blob/main/ui/src/app/headless/resource.ts#L74)
