# How `get_connectors_by_server` Fetches and Represents Connector Information

> Learn how infinilabs/coco-app's get_connectors_by_server function fetches and represents connector information. This TypeScript wrapper handles authentication and error checking for type-safe metadata.

- Repository: [INFINI Labs/coco-app](https://github.com/infinilabs/coco-app)
- Tags: how-to-guide
- Published: 2026-03-04

---

**The `get_connectors_by_server` function is a TypeScript wrapper around Tauri's invoke API that retrieves an array of `Connector` objects from the native backend, performing authentication checks and error handling before returning type-safe connector metadata.**

The `get_connectors_by_server` function in the **infinilabs/coco-app** repository serves as the primary bridge between the frontend and native backend for retrieving server-specific connector data. This utility demonstrates how the application leverages Tauri's command system to fetch structured connector information while maintaining strict type safety and centralized error management.

## How `get_connectors_by_server` Fetches Connector Data

### Tauri Invoke Mechanism

In [`src/commands/servers.ts`](https://github.com/infinilabs/coco-app/blob/main/src/commands/servers.ts) (lines 49-51), the function is implemented as a thin wrapper:

```ts
export function get_connectors_by_server(id: string): Promise<Connector[]> {
  return invokeWithErrorHandler(`get_connectors_by_server`, { id });
}

```

The implementation forwards the command name **`get_connectors_by_server`** and a payload containing the server identifier to `invokeWithErrorHandler`. This abstraction layer sits on top of **@tauri-apps/api/core**'s `invoke` function, which serializes the request and sends it to the native Rust backend for processing.

### Authentication and Error Handling

The `invokeWithErrorHandler` utility (lines 37-102 in [`src/commands/servers.ts`](https://github.com/infinilabs/coco-app/blob/main/src/commands/servers.ts)) implements a security gate before executing any command. It first validates whether the command resides in the whitelist of unauthenticated endpoints. If the command requires authentication and no user profile exists in the application state, it immediately throws an authentication error.

After passing the auth check, it calls the native `invoke<T>` function, catches any runtime errors, logs them via the global error store, and propagates the error to the caller. This ensures that network failures or backend panics surface as typed JavaScript exceptions that frontend code can handle gracefully.

## Connector Data Structure and Representation

### The Connector Interface

The function returns a `Promise<Connector[]>`, where the `Connector` interface is defined in [`src/types/commands.ts`](https://github.com/infinilabs/coco-app/blob/main/src/types/commands.ts) (lines 68-79):

```ts
export interface Connector {
  id: string;
  created?: string;
  updated?: string;
  name: string;
  description?: string;
  category?: string;
  icon?: string;
  tags?: string[];
  url?: string;
  assets?: { icons?: Record<string, string> };
}

```

This type definition enforces that every connector object contains mandatory fields **`id`** and **`name`**, while allowing optional metadata such as timestamps, descriptions, categories, and asset references.

### Optional vs Required Fields

The representation supports sparse connector definitions. While `id` and `name` must always be present, fields like `assets`, `tags`, and `url` may be omitted depending on the connector's configuration in the native backend. The `assets.icons` field uses a `Record<string, string>` structure to map icon size identifiers to URL paths, enabling responsive icon selection in the UI.

## Implementation Examples

### Basic Async Usage

Import the function from the commands module to fetch connectors directly:

```ts
import { get_connectors_by_server } from '@/commands/servers';

async function loadConnectors(serverId: string) {
  try {
    const connectors = await get_connectors_by_server(serverId);
    console.log('Connectors for server', serverId, connectors);
  } catch (e) {
    console.error('Failed to load connectors:', e);
  }
}

```

This pattern handles the promise resolution manually and logs errors to the console.

### React Hook Integration

For component-level state management, wrap the function in a custom hook:

```tsx
import { useEffect, useState } from 'react';
import { get_connectors_by_server } from '@/commands/servers';
import type { Connector } from '@/types/commands';

export function useConnectors(serverId: string) {
  const [connectors, setConnectors] = useState<Connector[]>([]);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!serverId) return;

    get_connectors_by_server(serverId)
      .then(setConnectors)
      .catch(err => setError(err.message));
  }, [serverId]);

  return { connectors, error };
}

```

This encapsulates loading states and error boundaries within the React lifecycle.

### Rendering Connector Lists

Consume the hook in a component to display connector data:

```tsx
function ConnectorList({ serverId }: { serverId: string }) {
  const { connectors, error } = useConnectors(serverId);

  if (error) return <div>Error: {error}</div>;
  if (!connectors.length) return <div>No connectors found.</div>;

  return (
    <ul>
      {connectors.map(c => (
        <li key={c.id}>
          <strong>{c.name}</strong>
          {c.category && <em> ({c.category})</em>}
        </li>
      ))}
    </ul>
  );
}

```

The component leverages the mandatory `id` field as a React key and conditionally renders optional category metadata.

## Key Source Files

- **[`src/commands/servers.ts`](https://github.com/infinilabs/coco-app/blob/main/src/commands/servers.ts)** – Defines `get_connectors_by_server` and the shared `invokeWithErrorHandler` authentication and error-handling logic.
- **[`src/types/commands.ts`](https://github.com/infinilabs/coco-app/blob/main/src/types/commands.ts)** – Contains the `Connector` TypeScript interface that describes the shape of returned connector objects.
- **[`src/stores/appStore.ts`](https://github.com/infinilabs/coco-app/blob/main/src/stores/appStore.ts)** – Provides the global error-handling store used by `invokeWithErrorHandler` to log and manage application errors.

## Summary

- **`get_connectors_by_server`** is a thin TypeScript wrapper that invokes the native backend via Tauri's command system.
- The function requires a server `id` string and returns a `Promise<Connector[]>` containing type-safe connector metadata.
- **Authentication checks** occur in `invokeWithErrorHandler` before the native call executes, throwing errors for unauthenticated users when required.
- The **Connector interface** in [`src/types/commands.ts`](https://github.com/infinilabs/coco-app/blob/main/src/types/commands.ts) mandates `id` and `name` fields while supporting optional assets, tags, and descriptions.
- **Error propagation** ensures that backend failures surface as catchable JavaScript exceptions in the frontend code.

## Frequently Asked Questions

### What is the return type of `get_connectors_by_server`?

The function returns `Promise<Connector[]>`, which resolves to an array of objects conforming to the `Connector` interface defined in [`src/types/commands.ts`](https://github.com/infinilabs/coco-app/blob/main/src/types/commands.ts). Each object contains mandatory `id` and `name` strings plus optional metadata fields like `description`, `category`, and `assets`.

### How does authentication work with `get_connectors_by_server`?

The underlying `invokeWithErrorHandler` utility checks the command against a whitelist of unauthenticated endpoints before executing. If the command requires a logged-in user and no profile exists in the application state, it throws an authentication error immediately without calling the native backend.

### Where is the Connector interface defined?

The TypeScript interface is defined in **[`src/types/commands.ts`](https://github.com/infinilabs/coco-app/blob/main/src/types/commands.ts)** at lines 68-79. It specifies the structure for connector objects including required fields (`id`, `name`) and optional fields like `description`, `category`, `assets`, and `tags`.

### What happens if the native backend throws an error?

`invokeWithErrorHandler` catches any runtime errors from the Tauri `invoke` call, logs them via the application's error store ([`appStore.ts`](https://github.com/infinilabs/coco-app/blob/main/appStore.ts)), and propagates the error to the caller. This allows frontend code to handle failures using standard `try/catch` blocks or `.catch()` promise handlers.