# LiveComponents API Reference

Vollständige API-Referenz für LiveComponents - Contracts, Attributes, Value Objects, HTTP Endpoints und JavaScript APIs.

## Table of Contents

1. [Core Contracts](#core-contracts)
2. [Attributes](#attributes)
3. [Value Objects](#value-objects)
4. [HTTP Endpoints](#http-endpoints)
5. [JavaScript Client API](#javascript-client-api)
6. [Caching API](#caching-api)
7. [Event System](#event-system)
8. [Security API](#security-api)
9. [Upload System API](#upload-system-api)
10. [Testing Helpers](#testing-helpers)

---

## Core Contracts

### LiveComponentContract

**Main contract** that all LiveComponents must implement.

```php
namespace App\Framework\LiveComponents\Contracts;

interface LiveComponentContract
{
    // Public readonly properties (PHP 8.4 property hooks)
    public ComponentId $id {get;}
    public LiveComponentState $state {get;}

    /**
     * Get render data for component
     * Returns template path and data for rendering
     */
    public function getRenderData(): ComponentRenderData;
}
```

**Usage:**

```php
#[LiveComponent('shopping-cart')]
final readonly class ShoppingCartComponent implements LiveComponentContract
{
    public function __construct(
        public ComponentId $id,
        public ShoppingCartState $state
    ) {}

    public function getRenderData(): ComponentRenderData
    {
        return new ComponentRenderData(
            template: 'components/shopping-cart',
            data: [
                'items' => $this->state->items,
                'total' => $this->state->total,
                'itemCount' => count($this->state->items)
            ]
        );
    }
}
```

### Optional Contracts

#### Cacheable

Enable caching for component with cache configuration.

```php
interface Cacheable
{
    /**
     * Get cache TTL in seconds (null = no caching)
     */
    public function getCacheTTL(): ?int;

    /**
     * Get cache key variation factors (optional)
     * Enables context-specific caching (per-user, per-locale, etc.)
     */
    public function getVaryBy(): ?VaryBy;
}
```

**Example:**

```php
final readonly class ProductListComponent implements LiveComponentContract, Cacheable
{
    public function getCacheTTL(): ?int
    {
        return 300;  // Cache for 5 minutes
    }

    public function getVaryBy(): ?VaryBy
    {
        return VaryBy::none()
            ->withUserId()      // Different cache per user
            ->withLocale()      // Different cache per language
            ->withCustom(['category']);  // Different cache per category
    }
}
```

#### LifecycleAware

React to component lifecycle events.

```php
interface LifecycleAware
{
    /**
     * Called when component is first created
     */
    public function onMount(): void;

    /**
     * Called after state update
     */
    public function onUpdate(LiveComponentState $previousState): void;

    /**
     * Called before component is destroyed
     */
    public function onDestroy(): void;
}
```

**Example:**

```php
final readonly class NotificationBellComponent implements
    LiveComponentContract,
    LifecycleAware
{
    public function onMount(): void
    {
        // Start polling for new notifications
        $this->notificationService->startPolling($this->id);
    }

    public function onUpdate(LiveComponentState $previousState): void
    {
        // Track state changes
        $this->analytics->track('notification_state_changed', [
            'old_count' => $previousState->unreadCount,
            'new_count' => $this->state->unreadCount
        ]);
    }

    public function onDestroy(): void
    {
        // Stop polling
        $this->notificationService->stopPolling($this->id);
    }
}
```

#### SupportsNesting

Support parent-child component relationships.

```php
interface SupportsNesting
{
    /**
     * Get child component IDs
     */
    public function getChildren(): array;

    /**
     * Handle event from child component
     */
    public function onChildEvent(ComponentId $childId, ComponentEvent $event): void;
}
```

#### SupportsSlots

Support slot-based content injection.

```php
interface SupportsSlots
{
    /**
     * Get available slot names
     */
    public function getSlots(): array;

    /**
     * Get default content for a slot
     */
    public function getDefaultSlotContent(string $slotName): ?string;
}
```

#### Uploadable

Support file uploads.

```php
interface Uploadable
{
    /**
     * Handle uploaded file
     */
    public function handleUpload(UploadedComponentFile $file): LiveComponentState;

    /**
     * Get allowed file types (MIME types)
     */
    public function getAllowedFileTypes(): array;

    /**
     * Get max file size in bytes
     */
    public function getMaxFileSize(): int;
}
```

---

## Attributes

### #[LiveComponent]

**Marks a class as LiveComponent** and defines its public name.

```php
#[Attribute(Attribute::TARGET_CLASS)]
final readonly class LiveComponent
{
    public function __construct(
        public string $name  // Component name for URLs and client-side
    ) {}
}
```

**Usage:**

```php
#[LiveComponent('counter')]
final readonly class CounterComponent implements LiveComponentContract
{
    // Component implementation
}

// Accessible at: /live-component/counter:instance-id
```

### #[Action]

**Marks a method as callable action** from client-side.

```php
#[Attribute(Attribute::TARGET_METHOD)]
final readonly class Action
{
    public function __construct(
        public ?string $description = null,     // Documentation
        public ?int $rateLimit = null,          // Requests per minute
        public ?int $idempotencyTTL = null      // Cache TTL for deduplication
    ) {}
}
```

**Usage:**

```php
#[LiveComponent('shopping-cart')]
final readonly class ShoppingCartComponent implements LiveComponentContract
{
    #[Action(
        description: 'Add item to cart',
        rateLimit: 60,           // Max 60 requests per minute
        idempotencyTTL: 300      // Deduplicate for 5 minutes
    )]
    public function addItem(CartItem $item): ShoppingCartState
    {
        return $this->state->addItem($item);
    }

    #[Action(description: 'Remove item from cart')]
    public function removeItem(string $itemId): ShoppingCartState
    {
        return $this->state->removeItem($itemId);
    }

    // ❌ NOT an action - cannot be called from client
    private function calculateTax(): int
    {
        return $this->state->subtotal * 0.19;
    }
}
```

### #[DataProvider]

**Marks a method as data provider** for child components.

```php
#[Attribute(Attribute::TARGET_METHOD)]
final readonly class DataProvider
{
    public function __construct(
        public string $name  // Data provider name
    ) {}
}
```

**Usage:**

```php
#[LiveComponent('product-grid')]
final readonly class ProductGridComponent implements LiveComponentContract
{
    #[DataProvider('products')]
    public function getProducts(): array
    {
        return $this->productRepository->findAll();
    }

    #[DataProvider('categories')]
    public function getCategories(): array
    {
        return $this->categoryRepository->findAll();
    }
}
```

### #[RequiresPermission]

**Adds authorization check** to action.

```php
#[Attribute(Attribute::TARGET_METHOD)]
final readonly class RequiresPermission
{
    public function __construct(
        public string $permission  // Required permission
    ) {}
}
```

**Usage:**

```php
#[LiveComponent('admin-panel')]
final readonly class AdminPanelComponent implements LiveComponentContract
{
    #[Action]
    #[RequiresPermission('admin.users.delete')]
    public function deleteUser(string $userId): AdminPanelState
    {
        $this->userService->delete($userId);
        return $this->state->withUserDeleted($userId);
    }
}
```

---

## Value Objects

### ComponentId

**Unique identifier for component instances**.

```php
final readonly class ComponentId
{
    public function __construct(
        public string $name,        // Component name (e.g., 'counter')
        public string $instanceId   // Unique instance (e.g., 'main', 'header')
    ) {}

    public static function fromString(string $id): self;
    public function toString(): string;
    public function equals(ComponentId $other): bool;
}
```

**Usage:**

```php
// Create from string
$id = ComponentId::fromString('shopping-cart:main');

// Create programmatically
$id = new ComponentId('shopping-cart', 'sidebar');

// Convert back to string
$idString = $id->toString();  // "shopping-cart:sidebar"

// Equality check
$id1->equals($id2);
```

### ComponentData

**Wrapper for component state data** with metadata.

```php
final readonly class ComponentData
{
    public function __construct(
        public array $data,           // State data as array
        public ?string $hash = null   // Optional state hash for change detection
    ) {}

    public function toArray(): array;
    public function toJson(): string;
    public static function fromArray(array $data): self;
}
```

**Usage:**

```php
// Create from array
$data = ComponentData::fromArray([
    'count' => 5,
    'lastUpdated' => time()
]);

// Convert to JSON
$json = $data->toJson();

// Get raw array
$array = $data->toArray();
```

### ComponentRenderData

**Template and data for rendering**.

```php
final readonly class ComponentRenderData
{
    public function __construct(
        public string $template,  // Template path (e.g., 'components/counter')
        public array $data        // Template data
    ) {}
}
```

### ActionParameters

**Parameters for action execution**.

```php
final readonly class ActionParameters
{
    public function __construct(
        public array $params,              // Action parameters
        public ?string $csrfToken = null,  // CSRF token
        public ?string $idempotencyKey = null  // Idempotency key
    ) {}

    public function get(string $key, mixed $default = null): mixed;
    public function has(string $key): bool;
    public function toArray(): array;
}
```

**Usage:**

```php
#[Action]
public function updateQuantity(ActionParameters $params): CartState
{
    $itemId = $params->get('itemId');
    $quantity = $params->get('quantity', 1);

    return $this->state->updateQuantity($itemId, $quantity);
}
```

### ComponentFragment

**Partial HTML update** for fragment rendering.

```php
final readonly class ComponentFragment
{
    public function __construct(
        public string $selector,  // CSS selector (e.g., '#cart-total')
        public string $html       // Fragment HTML
    ) {}
}
```

### FragmentCollection

**Collection of fragments** for batch updates.

```php
final readonly class FragmentCollection
{
    public function add(ComponentFragment $fragment): self;
    public function isEmpty(): bool;
    public function toArray(): array;
    public function toAssociativeArray(): array;
}
```

### ComponentEvent

**Event emitted by component**.

```php
final readonly class ComponentEvent
{
    public function __construct(
        public string $name,          // Event name
        public EventPayload $payload  // Event data
    ) {}
}
```

**Usage:**

```php
#[Action]
public function checkout(): CartState
{
    $order = $this->orderService->create($this->state);

    // Emit event
    $this->eventDispatcher->dispatch(
        new ComponentEvent(
            'order.created',
            new EventPayload(['orderId' => $order->id])
        )
    );

    return $this->state->clear();
}
```

---

## HTTP Endpoints

### POST /live-component/{id}

**Execute component action**.

**Request:**

```http
POST /live-component/shopping-cart:main
Content-Type: application/json

{
  "action": "addItem",
  "params": {
    "item": {
      "id": "prod-123",
      "name": "Product Name",
      "price": 2999,
      "quantity": 1
    }
  },
  "state": {
    "items": [],
    "total": 0
  },
  "fragments": ["#cart-items", "#cart-total"],
  "_csrf_token": "token_here",
  "idempotency_key": "uuid-here"
}
```

**Response (Full Render):**

```json
{
  "html": "<div class='shopping-cart'>...</div>",
  "state": {
    "items": [{...}],
    "total": 2999
  },
  "events": []
}
```

**Response (Fragment Render):**

```json
{
  "fragments": {
    "#cart-items": "<div class='cart-item'>...</div>",
    "#cart-total": "<span>€29.99</span>"
  },
  "state": {
    "items": [{...}],
    "total": 2999
  },
  "events": []
}
```

### POST /live-component/{id}/upload

**Upload file to component**.

**Request:**

```http
POST /live-component/file-uploader:main/upload
Content-Type: multipart/form-data

------boundary
Content-Disposition: form-data; name="file"; filename="document.pdf"
Content-Type: application/pdf

[binary data]
------boundary
Content-Disposition: form-data; name="state"

{"uploadedFiles":[]}
------boundary--
```

**Response:**

```json
{
  "success": true,
  "state": {
    "uploadedFiles": ["document.pdf"]
  }
}
```

### POST /live-component/batch

**Execute multiple actions** in single request.

**Request:**

```json
{
  "operations": [
    {
      "id": "op-1",
      "componentId": "counter:main",
      "action": "increment",
      "params": {},
      "state": {"count": 0}
    },
    {
      "id": "op-2",
      "componentId": "counter:main",
      "action": "increment",
      "params": {},
      "state": {"count": 1}
    }
  ]
}
```

**Response:**

```json
{
  "results": [
    {
      "id": "op-1",
      "success": true,
      "state": {"count": 1}
    },
    {
      "id": "op-2",
      "success": true,
      "state": {"count": 2}
    }
  ]
}
```

### POST /live-component/upload/init

**Initialize chunked upload**.

**Request:**

```json
{
  "fileName": "large-video.mp4",
  "fileSize": 104857600,
  "fileType": "video/mp4",
  "totalChunks": 200,
  "componentId": "video-uploader:main"
}
```

**Response:**

```json
{
  "sessionId": "upload_abc123",
  "chunkSize": 524288,
  "uploadedChunks": []
}
```

### POST /live-component/upload/chunk

**Upload single chunk**.

**Request:**

```http
POST /live-component/upload/chunk
Content-Type: multipart/form-data

------boundary
Content-Disposition: form-data; name="sessionId"

upload_abc123
------boundary
Content-Disposition: form-data; name="chunkIndex"

0
------boundary
Content-Disposition: form-data; name="chunk"; filename="chunk"

[binary data]
------boundary--
```

**Response:**

```json
{
  "success": true,
  "chunkIndex": 0,
  "hash": "sha256_hash_here",
  "uploadedChunks": [0],
  "totalChunks": 200
}
```

### POST /live-component/upload/complete

**Complete chunked upload**.

**Request:**

```json
{
  "sessionId": "upload_abc123",
  "expectedHash": "sha256_full_file_hash"
}
```

**Response:**

```json
{
  "success": true,
  "fileId": "file_xyz789",
  "filePath": "/uploads/large-video.mp4",
  "quarantineStatus": "scanning"
}
```

### GET /live-component/upload/progress/{sessionId}

**Get upload progress via SSE**.

**Response (Server-Sent Events):**

```
data: {"uploadedChunks":50,"totalChunks":200,"percentage":25,"bytesUploaded":26214400}

data: {"uploadedChunks":100,"totalChunks":200,"percentage":50,"bytesUploaded":52428800}

data: {"uploadedChunks":200,"totalChunks":200,"percentage":100,"bytesUploaded":104857600,"status":"complete"}
```

---

## JavaScript Client API

### Core API

#### window.LiveComponents

**Global registry** for LiveComponent instances.

```javascript
// Get component by ID
const component = window.LiveComponents.get('shopping-cart:main');

// Get all components
const allComponents = window.LiveComponents.getAll();

// Check if component exists
const exists = window.LiveComponents.has('counter:main');

// Register component
window.LiveComponents.register(componentInstance);

// Unregister component
window.LiveComponents.unregister('counter:main');

// Enable debug mode
window.LiveComponents.setDebug(true);
```

### Component Instance API

```javascript
class LiveComponent {
    // Properties
    id: string;
    name: string;
    state: object;

    // Call action
    async call(action: string, params?: object): Promise<Response>;

    // Update state without action
    async updateState(newState: object): Promise<void>;

    // Get current state
    getState(): object;

    // Emit event
    emit(eventName: string, payload?: object): void;

    // Listen to events
    on(eventName: string, handler: Function): void;
    off(eventName: string, handler: Function): void;

    // Start polling
    startPolling(interval: number, action: string, params?: object): void;

    // Stop polling
    stopPolling(): void;

    // Destroy component
    destroy(): void;
}
```

**Usage Examples:**

```javascript
// Get component
const cart = window.LiveComponents.get('shopping-cart:main');

// Call action
const result = await cart.call('addItem', {
    item: {
        id: 'prod-123',
        name: 'Product',
        price: 2999
    }
});

// Listen to events
cart.on('item.added', (event) => {
    console.log('Item added:', event.detail);
});

// Start polling
cart.startPolling(5000, 'refresh');  // Poll every 5 seconds

// Stop polling
cart.stopPolling();

// Update state manually
await cart.updateState({
    items: [...cart.state.items, newItem]
});
```

### Batch API

```javascript
// Create batch request
const batch = new BatchRequest();

batch.add('op-1', 'counter:main', 'increment', {});
batch.add('op-2', 'counter:sidebar', 'increment', {});

// Execute batch
const results = await batch.execute();

// Check results
results.forEach(result => {
    if (result.success) {
        console.log('Operation succeeded:', result.state);
    } else {
        console.error('Operation failed:', result.error);
    }
});
```

### Upload API

#### ChunkedUploader

```javascript
import { ChunkedUploader } from './chunked-uploader.js';

// Create uploader
const uploader = new ChunkedUploader('file-uploader:main', {
    chunkSize: 512 * 1024,       // 512KB chunks
    maxConcurrentChunks: 3,      // Parallel uploads
    maxRetries: 3,               // Retry failed chunks
    enableSSE: true,             // Real-time progress via SSE

    onProgress: (progress) => {
        console.log(`Progress: ${progress}%`);
        progressBar.value = progress;
    },

    onChunkComplete: (chunkIndex, totalChunks) => {
        console.log(`Chunk ${chunkIndex + 1}/${totalChunks} uploaded`);
    },

    onComplete: (result) => {
        console.log('Upload complete:', result);
    },

    onError: (error) => {
        console.error('Upload failed:', error);
    }
});

// Upload file
const file = document.querySelector('#file-input').files[0];
const result = await uploader.uploadFile(file);

// Pause upload
uploader.pause();

// Resume upload
uploader.resume();

// Cancel upload
uploader.cancel();
```

### Event Listeners

```javascript
// Global event listeners
window.LiveComponents.onRequest((request) => {
    console.log('Request:', request);
});

window.LiveComponents.onResponse((response) => {
    console.log('Response:', response);
});

window.LiveComponents.onError((error) => {
    console.error('Error:', error);
});

window.LiveComponents.onStateChange((event) => {
    console.log('State changed:', event.componentId, event.newState);
});

// Component-specific events
const component = window.LiveComponents.get('counter:main');

component.on('mounted', () => {
    console.log('Component mounted');
});

component.on('updated', (state) => {
    console.log('Component updated:', state);
});

component.on('destroyed', () => {
    console.log('Component destroyed');
});
```

---

## Caching API

### VaryBy

**Cache variation factors** for context-specific caching.

```php
final readonly class VaryBy
{
    // Factory: No variation
    public static function none(): self;

    // Built-in variations
    public function withUserId(): self;
    public function withLocale(): self;
    public function withRoles(array $roles): self;
    public function withFeatureFlags(array $flags): self;

    // Custom variations
    public function withCustom(array $keys): self;

    // Combine variations
    public function with(string $key, mixed $value): self;
}
```

**Usage:**

```php
public function getVaryBy(): ?VaryBy
{
    return VaryBy::none()
        ->withUserId()              // Cache per user
        ->withLocale()              // Cache per language
        ->withRoles(['admin'])      // Cache per role
        ->withFeatureFlags(['new-ui'])  // Cache per feature
        ->withCustom(['theme']);    // Custom variation
}

// Generated cache key:
// livecomponent:dashboard:main:u:123:l:en:r:admin:f:new-ui:c:theme=dark
```

### CacheContext

**Runtime cache context** for cache key generation.

```php
final readonly class CacheContext
{
    public function __construct(
        public ?string $userId = null,
        public ?string $locale = null,
        public array $roles = [],
        public array $featureFlags = [],
        public array $custom = []
    ) {}

    public static function fromRequest(HttpRequest $request): self;
}
```

### ComponentCacheKey

**Structured cache key** for components.

```php
final readonly class ComponentCacheKey
{
    public function __construct(
        public ComponentId $componentId,
        public ?CacheContext $context = null
    ) {}

    public function toString(): string;
    public static function fromString(string $key): self;
}
```

---

## Event System

### ComponentEventDispatcher

**Dispatch and listen** to component events.

```php
interface ComponentEventDispatcher
{
    public function dispatch(ComponentEvent $event): void;
    public function listen(string $eventName, callable $handler): void;
    public function unlisten(string $eventName, callable $handler): void;
}
```

**Usage:**

```php
// Dispatch event
$this->eventDispatcher->dispatch(
    new ComponentEvent('cart.item.added', new EventPayload([
        'itemId' => $item->id,
        'quantity' => $item->quantity
    ]))
);

// Listen to event
$this->eventDispatcher->listen('cart.item.added', function(ComponentEvent $event) {
    $this->analytics->track('item_added', $event->payload->toArray());
});
```

### NestedComponentEventDispatcher

**Parent-child event** communication.

```php
interface NestedComponentEventDispatcher
{
    public function dispatchToParent(ComponentId $parentId, ComponentEvent $event): void;
    public function dispatchToChildren(array $childIds, ComponentEvent $event): void;
}
```

---

## Security API

### LiveComponentRateLimiter

**Rate limiting** for actions.

```php
interface LiveComponentRateLimiter
{
    public function checkLimit(
        ComponentId $componentId,
        string $action,
        ?int $customLimit = null
    ): bool;

    public function getRemainingAttempts(
        ComponentId $componentId,
        string $action
    ): int;

    public function getRetryAfter(
        ComponentId $componentId,
        string $action
    ): ?int;
}
```

**Usage:**

```php
// Check rate limit
if (!$this->rateLimiter->checkLimit($this->id, 'sendMessage')) {
    throw new RateLimitExceededException(
        retryAfter: $this->rateLimiter->getRetryAfter($this->id, 'sendMessage')
    );
}

// Get remaining attempts
$remaining = $this->rateLimiter->getRemainingAttempts($this->id, 'sendMessage');
```

### ActionAuthorizationChecker

**Authorization checks** for actions.

```php
interface ActionAuthorizationChecker
{
    public function canExecute(
        string $componentClass,
        string $actionMethod,
        ?string $userId = null
    ): bool;

    public function getRequiredPermissions(
        string $componentClass,
        string $actionMethod
    ): array;
}
```

---

## Upload System API

### UploadSessionStore

**Manage upload sessions**.

```php
interface UploadSessionStore
{
    public function create(
        UploadSessionId $sessionId,
        string $fileName,
        int $fileSize,
        int $totalChunks,
        ComponentId $componentId
    ): void;

    public function recordChunk(
        UploadSessionId $sessionId,
        int $chunkIndex,
        ChunkHash $hash
    ): void;

    public function getUploadedChunks(UploadSessionId $sessionId): array;

    public function isComplete(UploadSessionId $sessionId): bool;

    public function delete(UploadSessionId $sessionId): void;
}
```

### IntegrityValidator

**Validate file integrity**.

```php
interface IntegrityValidator
{
    public function validateChunk(string $chunkData, ChunkHash $expectedHash): bool;

    public function validateCompleteFile(
        string $filePath,
        string $expectedHash
    ): bool;

    public function calculateHash(string $data): string;
}
```

### QuarantineService

**Virus scanning** for uploads.

```php
interface QuarantineService
{
    public function quarantineFile(string $filePath): QuarantineStatus;

    public function scanFile(string $filePath): ScanResult;

    public function releaseFile(string $filePath): bool;

    public function deleteQuarantinedFile(string $filePath): bool;
}
```

---

## Testing Helpers

### Pest Helpers

```php
use function Pest\LiveComponents\mountComponent;
use function Pest\LiveComponents\callAction;
use function Pest\LiveComponents\assertFragmentRendered;
use function Pest\LiveComponents\assertStateEquals;
use function Pest\LiveComponents\assertEventDispatched;

// Mount component
it('increments counter', function () {
    $component = mountComponent('counter:test', ['count' => 0]);

    expect($component->state['count'])->toBe(0);
});

// Call action
it('calls action and returns new state', function () {
    $component = mountComponent('counter:test', ['count' => 0]);

    $result = callAction($component, 'increment', []);

    expect($result['state']['count'])->toBe(1);
});

// Assert fragment rendered
it('renders cart total fragment', function () {
    $component = mountComponent('shopping-cart:test', [
        'items' => [],
        'total' => 0
    ]);

    $result = callAction($component, 'addItem', [
        'item' => ['id' => '1', 'price' => 1000]
    ], fragments: ['#cart-total']);

    assertFragmentRendered($result, '#cart-total');
    expect($result['fragments']['#cart-total'])->toContain('€10.00');
});

// Assert state equals
it('updates state correctly', function () {
    $component = mountComponent('counter:test', ['count' => 0]);

    $result = callAction($component, 'increment', []);

    assertStateEquals($result, ['count' => 1]);
});

// Assert event dispatched
it('dispatches event on action', function () {
    $component = mountComponent('cart:test', []);

    $result = callAction($component, 'checkout', []);

    assertEventDispatched($result, 'order.created');
});
```

### Custom Expectations

```php
// State expectations
expect($result)->toHaveState(['count' => 5]);

// Fragment expectations
expect($result)->toHaveFragment('#selector');
expect($result)->toHaveFragments(['#sel1', '#sel2']);

// Event expectations
expect($result)->toHaveEvent('event.name');
expect($result)->toHaveEvents(['event1', 'event2']);

// Error expectations
expect(fn() => callAction($component, 'invalid'))
    ->toThrow(ActionNotFoundException::class);
```

---

## Summary

### Quick Reference

**Core Contracts:**
- `LiveComponentContract` - Main interface
- `Cacheable` - Enable caching
- `LifecycleAware` - Lifecycle hooks
- `SupportsNesting` - Parent-child relationships
- `Uploadable` - File uploads

**Attributes:**
- `#[LiveComponent('name')]` - Register component
- `#[Action]` - Mark callable methods
- `#[RequiresPermission('perm')]` - Authorization
- `#[DataProvider('name')]` - Provide data

**HTTP Endpoints:**
- `POST /live-component/{id}` - Execute action
- `POST /live-component/{id}/upload` - Upload file
- `POST /live-component/batch` - Batch operations
- `POST /live-component/upload/init` - Init chunked upload
- `POST /live-component/upload/chunk` - Upload chunk
- `POST /live-component/upload/complete` - Complete upload

**JavaScript API:**
- `window.LiveComponents.get(id)` - Get component
- `component.call(action, params)` - Call action
- `component.on(event, handler)` - Listen events
- `new ChunkedUploader()` - Chunked upload

**Caching:**
- `VaryBy::none()->withUserId()` - Cache variations
- `getCacheTTL()` - Cache duration
- `getVaryBy()` - Variation factors

This reference covers all public APIs for LiveComponents development, testing, and integration.
