npm package: @prava-sdk/core
Description: Prava SDK — PCI-compliant card enrollment for merchants
Latest version: 0.1.1

# @prava-sdk/core

PCI-compliant card enrollment SDK for AI Apps or merchant. Securely collect card data via an isolated iframe — your servers never touch raw PANs. This enables cards to be used for secure agentic payments

## Install

```bash
npm install @prava-sdk/core
```

## Quick Start

```ts
import { PravaSDK } from '@prava-sdk/core';

// 1. Initialize with your publishable key
const prava = new PravaSDK({
  publishableKey: 'pk_live_xxx',
});

// 2. Create a session via Prava backend (server-side, using your secret key)
const session = await fetch('/api/create-session', {
  method: 'POST',
  body: JSON.stringify({ userId: 'user_123' }),
}).then(res => res.json());

// 3. Collect card data
const result = await prava.collectPAN({
  sessionToken: session.session_token,
  iframeUrl: session.iframe_url,
  container: '#card-form',       // DOM element or selector
  onReady: () => {
    console.log('Card form loaded');
  },
  onChange: (state) => {
    // Real-time validation
    console.log('Valid:', state.isComplete);
  },
  onSuccess: (data) => {
    console.log('Enrolled!', data.enrollmentId, data.last4);
  },
  onError: (error) => {
    console.error(error.code, error.message);
  },
});
```

```html
<!-- In your HTML -->
<div id="card-form"></div>
```

## How It Works

1. **Your backend** creates a session using your secret key → returns `session_token` + `iframe_url`
2. **The SDK** mounts a sandboxed iframe from `iframe_url` into your page
3. **The user** enters card details inside the iframe (your page never sees raw card data)
4. **The iframe** tokenizes the card and communicates the result back via PostMessage
5. **You receive** an `enrollmentId` + `last4` + `brand` — no PCI scope for your servers

## API

### `new PravaSDK(config)`

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `publishableKey` | `string` | ✅ | Your publishable key (`pk_live_...` or `pk_test_...`) |

### `prava.collectPAN(options)`

Returns `Promise<CollectPANResult>`.

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `sessionToken` | `string` | ✅ | Session token from your backend |
| `iframeUrl` | `string` | ✅ | Iframe URL from your backend session response |
| `container` | `string \| HTMLElement` | ✅ | CSS selector or DOM element to mount the card form |
| `onReady` | `() => void` | | Called when iframe is loaded and ready |
| `onChange` | `(state: CardValidationState) => void` | | Called on every input change with validation state |
| `onSuccess` | `(result: CollectPANResult) => void` | | Called on successful card enrollment |
| `onError` | `(error: PravaError) => void` | | Called on error |
| `styles` | `CardFormStyles` | | Custom styles for the card form |

### `prava.destroy()`

Cleanup the SDK instance, remove the iframe, and release resources.

### Types

```ts
interface CollectPANResult {
  enrollmentId: string;
  last4: string;
  brand: string;
  expMonth: number;
  expYear: number;
}

interface CardValidationState {
  cardNumber: FieldState;
  expiry: FieldState;
  cvv: FieldState;
  isComplete: boolean;
}

interface PravaError {
  code: string;
  message: string;
  details?: Record<string, unknown>;
}
```

## Framework Examples

### React

```tsx
import { useRef, useEffect } from 'react';
import { PravaSDK } from '@prava-sdk/core';

function CardForm({ session }) {
  const containerRef = useRef<HTMLDivElement>(null);
  const sdkRef = useRef<PravaSDK | null>(null);

  useEffect(() => {
    if (!session || !containerRef.current) return;

    const sdk = new PravaSDK({ publishableKey: 'pk_live_xxx' });
    sdkRef.current = sdk;

    sdk.collectPAN({
      sessionToken: session.session_token,
      iframeUrl: session.iframe_url,
      container: containerRef.current,
      onSuccess: (data) => console.log('Enrolled:', data.enrollmentId),
    });

    return () => sdk.destroy();
  }, [session]);

  return <div ref={containerRef} />;
}
```

### Vanilla JS

```html
<div id="card-form"></div>
<script type="module">
  import { PravaSDK } from '@prava-sdk/core';

  const prava = new PravaSDK({ publishableKey: 'pk_live_xxx' });
  const session = await fetch('/api/session').then(r => r.json());

  prava.collectPAN({
    sessionToken: session.session_token,
    iframeUrl: session.iframe_url,
    container: '#card-form',
    onSuccess: (data) => alert(`Card enrolled: •••• ${data.last4}`),
  });
</script>
```

## Security

- Card data is entered inside a ** PCI compliant iframe** — your page never accesses raw card numbers
- The SDK validates publishable keys and session tokens

## Requirements

- Modern browser (Chrome 80+, Firefox 80+, Safari 14+, Edge 80+)
- Your backend must implement the Prava session API