npm package: @flic-sdk/client
Description: Client SDK for Flic feature flags (browser/single-user)
Latest version: 0.0.3

# @flic-sdk/client

Browser SDK for Flic feature flags. Designed for single-user contexts (browsers, mobile apps).

## Architecture

```
┌─────────────┐      ┌─────────────┐
│   Browser   │      │  Flic API   │
│             │ SSE  │             │
│  client-sdk │◄─────│  evaluates  │
│             │      │  for user   │
└─────────────┘      └─────────────┘
```

**Server-side evaluation**: Flags are evaluated on the server and streamed to the client. The SDK caches evaluated results.

## Installation

```bash
npm install @flic-sdk/client
```

## Quick Start

```ts
import { Flic } from "@flic-sdk/client";

const flic = new Flic({
  apiKey: "flic_xxx",
  baseUrl: "https://api.flic.dev",
  project: "my-project",
  environment: "production",
  context: { key: "user-123", attributes: { plan: "pro" } },
});

await flic.init();

// Boolean flag
if (flic.isEnabled("new-checkout")) {
  showNewCheckout();
}

// Value flag
const color = flic.getValue("button-color", "blue");

// Cleanup
await flic.stop();
```

## API

### Constructor

```ts
new Flic({
  apiKey: string;           // Required - API key
  baseUrl: string;          // Required - API URL
  project: string;          // Required - Project slug
  environment: string;      // Required - Environment name
  context?: EvaluateContext; // User context for targeting
  pollingInterval?: number; // Fallback polling interval (default: 30000ms)
  streaming?: boolean | StreamConfig; // SSE streaming (default: true)
  analytics?: boolean | AnalyticsConfig; // Impression tracking (default: true)
});
```

### Methods

| Method | Returns | Description |
|--------|---------|-------------|
| `init()` | `Promise<void>` | Initialize SDK, fetch flags, start updates |
| `isEnabled(key)` | `boolean` | Check if boolean flag is enabled |
| `getValue(key, default)` | `T` | Get flag value or default |
| `setContext(ctx)` | `void` | Replace user context (triggers re-evaluation) |
| `updateContext(partial)` | `void` | Merge into existing context |
| `getContext()` | `EvaluateContext` | Get current context |
| `subscribe(fn)` | `() => void` | Listen for flag changes, returns unsubscribe |
| `stop()` | `Promise<void>` | Stop updates, flush analytics |

### Context

```ts
type EvaluateContext = {
  key?: string;  // User ID for consistent rollouts
  attributes?: Record<string, unknown>; // Targeting attributes
};
```

## Real-time Updates

By default, the SDK uses Server-Sent Events (SSE) for instant flag updates:

1. **On connect**: Receives all evaluated flags
2. **On change**: Receives individual flag updates
3. **On disconnect**: Automatic reconnection with exponential backoff
4. **On failure**: Falls back to polling after max retries (default: 5)

### Streaming Config

```ts
new Flic({
  // ...
  streaming: {
    enabled: true,
    reconnectDelay: 1000,      // Initial retry delay
    maxReconnectDelay: 30000,  // Max retry delay
    maxReconnectAttempts: 5,   // Before fallback to polling
    fallbackToPolling: true,
  },
});
```

### Disable Streaming

```ts
new Flic({
  // ...
  streaming: false, // Use polling only
  pollingInterval: 10000,
});
```

## Resilience

**What happens if the connection fails?**

1. **Cached values persist** - All previously fetched flags remain available
2. **Auto reconnect** - SDK retries with exponential backoff (1s → 2s → 4s → ...)
3. **Fallback to polling** - After 5 failed reconnects, switches to polling
4. **No data loss** - Analytics events are buffered and retried

The SDK never throws during `isEnabled()`/`getValue()`. It returns cached values or defaults.

## React Integration

Use `@flic-sdk/react` for React hooks:

```tsx
import { FlicProvider, useFlag, useValue } from "@flic-sdk/react";

function App() {
  return (
    <FlicProvider
      apiKey="flic_xxx"
      baseUrl="https://api.flic.dev"
      project="my-project"
      environment="production"
      context={{ key: "user-123" }}
    >
      <MyComponent />
    </FlicProvider>
  );
}

function MyComponent() {
  const showFeature = useFlag("new-feature");
  const buttonColor = useValue("button-color", "blue");
  // Re-renders automatically when flags change
}
```

## Analytics

Tracks flag evaluations for analytics (first impression per flag per session):

```ts
new Flic({
  // ...
  analytics: {
    enabled: true,
    flushInterval: 10000, // Batch send interval
    maxBatchSize: 100,    // Max events before immediate flush
  },
});
```

Disable with `analytics: false`.

## Anonymous Users

If no `context.key` is provided, the SDK generates and persists an anonymous ID in localStorage for consistent targeting.

## TypeScript

```ts
import type { EvaluateContext, FlicConfig } from "@flic-sdk/client";
```