# @sylphx/sdk

[![npm version](https://img.shields.io/npm/v/@sylphx/sdk.svg?style=flat)](https://www.npmjs.com/package/@sylphx/sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue?logo=typescript)](https://www.typescriptlang.org/)
[![docs](https://img.shields.io/badge/docs-sylphx.com%2Fdocs-green)](https://sylphx.com/docs)

Auth, billing, analytics, AI, storage, and more — in one SDK.

📖 **Full docs:** [sylphx.com/docs](https://sylphx.com/docs)

---

## Installation

```bash
npm install @sylphx/sdk
# or
pnpm add @sylphx/sdk
bun add @sylphx/sdk
```

---

## Quick Start (Next.js)

### 1. Environment Variables

Two keys from your [Platform Console](https://sylphx.com/console):

```bash
# .env.local
SYLPHX_SECRET_KEY=sk_dev_xxxxxxxxxxxxxxxxxxxx        # server-only
NEXT_PUBLIC_SYLPHX_APP_ID=app_dev_xxxxxxxxxxxx        # safe to expose
```

That's it. No other config needed.

> **Key formats**
> - `sk_dev_*` / `sk_stg_*` / `sk_prod_*` — Secret key (server only, never expose)
> - `app_dev_*` / `app_stg_*` / `app_prod_*` — App ID (safe for client-side)
>
> Get both from **Console → Your App → API Keys**.

---

### 2. Middleware

Handles auth routes (`/auth/callback`, `/auth/signout`) and route protection automatically.

```ts
// middleware.ts
import { createSylphxMiddleware } from '@sylphx/sdk/nextjs'

export default createSylphxMiddleware({
  publicRoutes: ['/', '/about', '/pricing', '/login'],
})

export const config = {
  matcher: ['/((?!_next|.*\\..*).*)', '/'],
}
```

No manual `/api/auth/*` routes needed — the middleware handles everything.

---

### 3. Root Layout

Fetch config server-side once, pass to the provider:

```tsx
// app/layout.tsx
import { getAppConfig } from '@sylphx/sdk/server'
import { SylphxProvider } from '@sylphx/sdk/react'

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const config = await getAppConfig({
    secretKey: process.env.SYLPHX_SECRET_KEY!,
    appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
  })

  return (
    <html>
      <body>
        <SylphxProvider
          config={config}
          appId={process.env.NEXT_PUBLIC_SYLPHX_APP_ID!}
        >
          {children}
        </SylphxProvider>
      </body>
    </html>
  )
}
```

---

### 4. Protect Pages (Server Components)

```tsx
// app/dashboard/page.tsx
import { currentUser } from '@sylphx/sdk/nextjs'
import { redirect } from 'next/navigation'

export default async function Dashboard() {
  const user = await currentUser()
  if (!user) redirect('/login')

  return <h1>Hello, {user.name}</h1>
}
```

---

### 5. Auth UI (Client Components)

```tsx
'use client'
import { useUser, SignedIn, SignedOut, UserButton } from '@sylphx/sdk/react'

export default function Header() {
  const { user } = useUser()

  return (
    <header>
      <SignedOut>
        <a href="/login">Sign in</a>
      </SignedOut>
      <SignedIn>
        <span>Hello, {user?.name}</span>
        <UserButton afterSignOutUrl="/" />
      </SignedIn>
    </header>
  )
}
```

---

## Server-Side

### Get Current User

```tsx
import { auth, currentUser, currentUserId } from '@sylphx/sdk/nextjs'

// Full auth state
const { userId, user, sessionToken } = await auth()

// Just the user object (null if not signed in)
const user = await currentUser()

// Just the user ID
const userId = await currentUserId()
```

### Server API Client

```ts
import { createServerClient } from '@sylphx/sdk/server'

const client = createServerClient({
  secretKey: process.env.SYLPHX_SECRET_KEY!,
})

// GET /billing/plans
const plans = await client.GET('/billing/plans')

// POST /analytics/track
await client.POST('/analytics/track', {
  body: { events: [{ event: 'purchase', properties: { amount: 99 } }] },
})
```

### Prefetch App Config

```ts
import {
  getAppConfig,    // All config in one call (recommended)
  getPlans,        // Billing plans
  getFeatureFlags, // Feature flag definitions
  getConsentTypes, // GDPR consent config
} from '@sylphx/sdk/server'

const config = await getAppConfig({
  secretKey: process.env.SYLPHX_SECRET_KEY!,
  appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
})
// config.plans, config.featureFlags, config.oauthProviders, config.consentTypes
```

### Verify Webhooks

```ts
import { verifyWebhook } from '@sylphx/sdk/server'

export async function POST(request: Request) {
  const body = await request.text()

  const result = await verifyWebhook({
    payload: body,
    signatureHeader: request.headers.get('x-webhook-signature'),
    secret: process.env.SYLPHX_SECRET_KEY!,
  })

  if (!result.valid) {
    return new Response('Unauthorized', { status: 401 })
  }

  const { event, data } = result.payload!
  // handle event...
  return Response.json({ received: true })
}
```

Or use the handler factory:

```ts
import { createWebhookHandler } from '@sylphx/sdk/server'

export const POST = createWebhookHandler({
  secret: process.env.SYLPHX_SECRET_KEY!,
  handlers: {
    'user.created': async (data) => { /* ... */ },
    'subscription.updated': async (data) => { /* ... */ },
  },
})
```

### JWT Verification

```ts
import { verifyAccessToken } from '@sylphx/sdk/server'

const payload = await verifyAccessToken(token, {
  secretKey: process.env.SYLPHX_SECRET_KEY!,
})
// payload.sub, payload.email, payload.role, payload.app_id
```

---

## React Hooks

### Auth

```tsx
import { useUser, useAuth } from '@sylphx/sdk/react'

const { user, isLoading, isSignedIn } = useUser()
const { signIn, signUp, signOut, forgotPassword } = useAuth()

await signIn({ email: 'user@example.com', password: '...' })
await signOut()
```

### Billing

```tsx
import { useBilling } from '@sylphx/sdk/react'

const { subscription, isPremium, plans, createCheckout, openPortal } = useBilling()

// Check access
if (!isPremium) return <UpgradePrompt />

// Start checkout
const url = await createCheckout('pro', 'monthly')
window.location.href = url

// Manage subscription
await openPortal()
```

### Analytics

```tsx
import { useAnalytics } from '@sylphx/sdk/react'

const { track, identify, page } = useAnalytics()

track('button_clicked', { button: 'upgrade' })
identify({ name: 'John', email: 'john@example.com' })
```

### Feature Flags

```tsx
import { useFeatureFlag } from '@sylphx/sdk/react'

const { isEnabled } = useFeatureFlag('new-dashboard')
if (isEnabled) return <NewDashboard />
```

### AI

```tsx
import { useChat, useCompletion } from '@sylphx/sdk/react'

const { messages, send, isLoading } = useChat({
  model: 'anthropic/claude-3.5-sonnet',
})

await send('What is the meaning of life?')
```

### Storage

```tsx
import { useStorage } from '@sylphx/sdk/react'

const { upload, uploadAvatar, isUploading, progress } = useStorage()

const url = await upload(file, { path: 'documents/' })
const avatarUrl = await uploadAvatar(imageFile)
```

### More Hooks

```tsx
import { useConsent }       from '@sylphx/sdk/react' // GDPR consent
import { useFeatureFlags }  from '@sylphx/sdk/react' // All flags at once
import { useNotifications } from '@sylphx/sdk/react' // In-app notifications
import { useReferral }      from '@sylphx/sdk/react' // Referral program
import { useOrganization }  from '@sylphx/sdk/react' // Multi-tenant orgs
import { useJobs }          from '@sylphx/sdk/react' // Background jobs
import { useErrorTracking } from '@sylphx/sdk/react' // Error capture
```

---

## UI Components

### Auth

```tsx
import { SignIn, SignUp, UserButton, SignedIn, SignedOut } from '@sylphx/sdk/react'

<SignedOut><SignIn mode="embedded" afterSignInUrl="/dashboard" /></SignedOut>
<SignedIn><UserButton afterSignOutUrl="/" /></SignedIn>
```

### Billing

```tsx
import { PricingTable, CheckoutButton } from '@sylphx/sdk/react'

<PricingTable plans={plans} />
<CheckoutButton planSlug="pro" interval="monthly">Upgrade</CheckoutButton>
```

### Route Protection

```tsx
import { Protect } from '@sylphx/sdk/react'

<Protect role="admin">
  <AdminPanel />
</Protect>
```

---

## Pure Functions (Server or Client)

For non-React environments or maximum control:

```ts
import { createConfig, signIn, track, getPlans } from '@sylphx/sdk'

const config = createConfig({ secretKey: process.env.SYLPHX_SECRET_KEY! })

// Auth
const tokens = await signIn(config, { email, password })
const authedConfig = withToken(config, tokens.accessToken)

// Analytics
await track(config, { event: 'purchase', properties: { amount: 99 } })

// Billing
const plans = await getPlans(config)
```

---

## Entry Points

| Import path | Use for |
|---|---|
| `@sylphx/sdk` | Pure functions (server or client, no React) |
| `@sylphx/sdk/react` | React hooks, components, `SylphxProvider` |
| `@sylphx/sdk/server` | JWT verification, webhook verification, server client |
| `@sylphx/sdk/nextjs` | `createSylphxMiddleware`, `auth()`, `currentUser()` |

---

## TypeScript

All types are fully inferred. Import them directly:

```ts
import type { User, Plan, Subscription, AppConfig } from '@sylphx/sdk'
import type { AuthResult } from '@sylphx/sdk/nextjs'
```

---

## Self-Hosting

If you're running your own Sylphx Platform deployment:

```bash
# .env.local — only needed for self-hosting
SYLPHX_PLATFORM_URL=https://platform.your-domain.com
```

You will not need this if you're using the hosted platform at [sylphx.com](https://sylphx.com).
