# DataApi System Overview

The DataApi system provides type-safe IPC communication for business data operations between the Renderer and Main processes.

## Purpose

DataApiService handles data that:
- Is **business data accumulated through user activity**
- Has **dedicated database schemas/tables**
- Users can **create, delete, modify records** without fixed limits
- Would be **severe and irreplaceable** if lost
- Can grow to **large volumes** (potentially GBs)

## What DataApi is NOT For

DataApi must not be used as a general-purpose RPC layer. It is the **data** business-logic layer (persisting and querying records), not the application's business-logic layer. The following categories of operations belong in traditional IPC handlers (`src/main/ipc.ts`) or lifecycle services:

- **System control**: Window management, process control, app configuration changes
- **External service integration**: OAuth flows, WebDAV/S3 operations, backup/restore workflows
- **Imperative commands**: Sending notifications, opening URLs, launching external processes
- **Stateless queries without database backing**: System info, font lists, disk space checks
- **Side effects bundled into a data write**: fs/network/process/external-service work performed inside a handler or service that also writes the database — no matter how deeply nested (see [Hard Rule: No Non-Data Side Effects](./api-design-guidelines.md#hard-rule-no-non-data-side-effects))

**Why?** DataApi's built-in retry, caching, and layered architecture (Handler → Service → SQLite) are designed for data persistence. These features become harmful or meaningless when applied to side-effectful operations. See [API Design Guidelines — Scope & Boundaries](./api-design-guidelines.md#dataapi-scope--boundaries) for detailed anti-patterns.

## Key Characteristics

### Type-Safe Communication
- End-to-end TypeScript types from client call to handler
- Path parameter inference from route definitions
- Compile-time validation of request/response shapes

### RESTful-Style API
- Familiar HTTP semantics (GET, POST, PUT, PATCH, DELETE)
- Resource-based URL patterns (`/topics/:id/messages`)
- Standard status codes and error responses

### On-Demand Data Access
- No automatic caching (fetch fresh data when needed)
- Explicit cache control via query options
- Supports large datasets with pagination

## Architecture Diagram

```
┌────────────────────────────────────────────────────────────┐
│ Renderer Process                                           │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ React Components                                       │ │
│ │ - useQuery('/topics')                                  │ │
│ │ - useMutation('/topics', 'POST')                       │ │
│ └──────────────────────────┬─────────────────────────────┘ │
│                            ▼                               │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ DataApiService (Renderer)                              │ │
│ │ - Type-safe ApiClient interface                        │ │
│ │ - Request serialization                                │ │
│ │ - Automatic retry with exponential backoff             │ │
│ │ - Error handling and transformation                    │ │
│ └──────────────────────────┬─────────────────────────────┘ │
└────────────────────────────┼───────────────────────────────┘
                             │ IPC
┌────────────────────────────┼───────────────────────────────┐
│ Main Process               ▼                               │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ IpcAdapter                                             │ │
│ │ - Receives IPC requests                                │ │
│ │ - Routes to ApiServer                                  │ │
│ └──────────────────────────┬─────────────────────────────┘ │
│                            ▼                               │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ApiServer                                              │ │
│ │ - Request routing by path and method                   │ │
│ │ - Middleware pipeline processing                       │ │
│ └──────────────────────────┬─────────────────────────────┘ │
│                            ▼                               │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Handlers (api/handlers/)                               │ │
│ │ - Thin layer: extract params, call service, transform  │ │
│ │ - NO business logic here                               │ │
│ └──────────────────────────┬─────────────────────────────┘ │
│                            ▼                               │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Services (services/)                                   │ │
│ │ - Business logic and validation                        │ │
│ │ - Transaction coordination                             │ │
│ │ - Data access via Drizzle ORM                          │ │
│ └──────────────────────────┬─────────────────────────────┘ │
│                            ▼                               │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ SQLite Database (via Drizzle ORM)                      │ │
│ │ - topic, message, file tables                          │ │
│ │ - Full-text search indexes                             │ │
│ └────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘
```

## Architecture Layers

### 1. API Layer (Handlers)
- **Location**: `src/main/data/api/handlers/`
- **Responsibility**: HTTP-like interface layer
- **Does**: Extract parameters, call services, transform responses
- **Does NOT**: Contain business logic

### 2. Service Layer (Services)
- **Location**: `src/main/data/services/`
- **Responsibility**: Domain logic, workflows, and data access
- **Does**: Validation, transaction coordination, orchestration, Drizzle ORM queries
- **Write atomicity**: use `application.get('DbService').withWriteTx(fn)` to commit multiple writes (or a read-then-write) all-or-nothing in one synchronous `BEGIN IMMEDIATE` transaction (`fn` must be synchronous — better-sqlite3 rejects a Promise-returning callback). A single autocommit write doesn't need it. See [Database Patterns — Write Serialization](./database-patterns.md#write-serialization-dbservicewithwritetx).

> **Note:** In rare cases, a read-only Registry Service (e.g., `ProviderRegistryService`)
> may exist alongside Entity Services to merge preset data with DB data.
> See [DataApi in Main — Registry Services](./data-api-in-main.md#registry-services-supplementary).

### 3. Database Layer
- **Location**: `src/main/data/db/`
- **Technology**: SQLite + Drizzle ORM
- **Schemas**: `db/schemas/` directory

### Repository Pattern (Strongly Discouraged)

> **⚠️ Do NOT create Repository files by default.** Services handle both business logic and data access directly via Drizzle ORM. This is an intentional design decision.
>
> Only create a separate Repository when you are **1000% certain** it is absolutely necessary — e.g., extremely complex multi-table queries with joins/CTEs that would make the Service unreadable, AND the query logic is reused across multiple services.
>
> If in doubt, keep it in the Service. The overhead of an extra architectural layer is not justified for this project's scale (Electron desktop app + SQLite).

## Key Features

### Automatic Retry
- Exponential backoff for transient failures
- Configurable retry count and delays
- Skips retry for client errors (4xx)

### Error Handling
- Typed error codes (`ErrorCode` enum)
- `DataApiError` class with retryability detection
- Factory methods for consistent error creation

### Request Timeout
- Configurable per-request timeouts
- Automatic cancellation of stale requests

### Dynamic Paths & Cache Invalidation
- `useQuery` / `useMutation` / `useInfiniteQuery` / `usePaginatedQuery` accept either concrete paths (`/providers/abc`) or template paths with `params` (`/providers/:providerId`)
- Each pagination hook constrains its path generic to the matching pagination shape — mixing cursor and offset paths is a compile-time error
- `refresh` option supports static paths, `/*` prefix for fan-out, and function form for keys computed from args/result
- Details, patterns, and misuse warnings: see [DataApi in Renderer → Dynamic Paths & Refresh Patterns](./data-api-in-renderer.md#dynamic-paths)

## Usage Summary

For detailed code examples, see:
- [DataApi in Renderer](./data-api-in-renderer.md) - Client-side usage
- [DataApi in Main](./data-api-in-main.md) - Server-side implementation
- [API Design Guidelines](./api-design-guidelines.md) - RESTful conventions
- [API Types](./api-types.md) - Type system details
