npm package: @kudosapi/sdk
Description: Official SDK for KudosAPI - Get positive notifications when good things happen in your app
Author: KudosAPI
Latest version: 0.1.2

# @kudosapi/sdk

Official SDK for [KudosAPI](https://kudosapi.com) - Get positive notifications when good things happen in your app.

## Installation

```bash
npm install @kudosapi/sdk
```

## Quick Start

```typescript
import { Kudos } from '@kudosapi/sdk';

const kudos = new Kudos({ apiKey: 'kudo_live_xxx' });

// Track a sale
await kudos.track({
  type: 'sale',
  title: 'New Pro subscription',
  value: 99,
  currency: 'USD',
  data: { customer: 'jane@example.com' }
});
```

## Configuration

```typescript
const kudos = new Kudos({
  apiKey: 'kudo_live_xxx',      // Required: Your project API key
  baseUrl: 'https://api.kudosapi.com', // Optional: API base URL
  timeout: 5000,                // Optional: Request timeout in ms (default: 5000)
  debug: false                  // Optional: Enable debug logging
});
```

## API Keys: Test vs Live

KudosAPI provides two types of API keys for each project:

| Key Type | Prefix | Purpose |
|----------|--------|---------|
| **Live** | `kudo_live_` | Production use. Events are processed and notifications are sent. |
| **Test** | `kudo_test_` | Development/testing. Events are accepted but NOT processed or stored. |

### Using Test Keys

Use test keys during development to verify your integration without generating real notifications:

```typescript
// Development - events are accepted but not processed
const kudos = new Kudos({ apiKey: 'kudo_test_xxx' });

// The SDK will warn if you accidentally use a test key in production
// "[KudosAPI] Warning: Using a test API key in production. Events will not be processed."
```

### Environment-Based Configuration

A common pattern is to use environment variables to switch between test and live keys:

```typescript
const kudos = new Kudos({
  apiKey: process.env.KUDOS_API_KEY!, // kudo_test_xxx in dev, kudo_live_xxx in prod
});
```

```bash
# .env.local (development)
KUDOS_API_KEY=kudo_test_xxx

# .env.production
KUDOS_API_KEY=kudo_live_xxx
```

## Local Development

### Testing Against Local KudosAPI

If you're running KudosAPI locally, override the `baseUrl`:

```typescript
const kudos = new Kudos({
  apiKey: 'kudo_test_xxx',
  baseUrl: 'http://localhost:3000', // Your local KudosAPI instance
  debug: true, // Enable debug logging to see requests
});
```

### Mocking in Tests

For unit tests, mock the SDK to avoid network calls:

```typescript
// __mocks__/@kudosapi/sdk.ts (Jest/Vitest)
export class Kudos {
  track = vi.fn().mockResolvedValue({ success: true, eventId: 'evt_mock' });
  sale = vi.fn().mockResolvedValue({ success: true, eventId: 'evt_mock' });
  signup = vi.fn().mockResolvedValue({ success: true, eventId: 'evt_mock' });
  milestone = vi.fn().mockResolvedValue({ success: true, eventId: 'evt_mock' });
}
```

```typescript
// your-code.test.ts
vi.mock('@kudosapi/sdk');

it('tracks sale on checkout', async () => {
  const kudos = new Kudos({ apiKey: 'test' });
  await processCheckout(kudos);
  expect(kudos.sale).toHaveBeenCalledWith(99, 'USD', expect.any(Object));
});
```

### Integration Testing

For integration tests that need to hit the real API, use test keys:

```typescript
// integration.test.ts
import { Kudos } from '@kudosapi/sdk';

const kudos = new Kudos({
  apiKey: process.env.KUDOS_TEST_API_KEY!, // kudo_test_xxx
  debug: true,
});

it('successfully sends event to KudosAPI', async () => {
  const result = await kudos.track({
    type: 'integration_test',
    title: 'Test event',
  });

  // Test keys return success but don't process events
  expect(result.success).toBe(true);
  expect(result.eventId).toMatch(/^evt_/);
});
```

## Methods

### `track(event, options?)`

Send a custom event.

```typescript
await kudos.track({
  type: 'sale',           // Required: Event type
  title: 'New sale!',     // Optional: Human-readable title
  value: 49.00,           // Optional: Numeric value
  currency: 'USD',        // Optional: ISO currency code
  data: { ... }           // Optional: Additional data
});
```

Options:
- `fireAndForget`: Set to `true` to return immediately without waiting for a response.

### `sale(amount, currency, data?)`

Convenience method for tracking sales.

```typescript
await kudos.sale(99.00, 'USD', { customer: 'jane@example.com' });
```

### `signup(data?)`

Convenience method for tracking signups.

```typescript
await kudos.signup({ source: 'landing_page' });
```

### `milestone(title, value?, data?)`

Convenience method for tracking milestones.

```typescript
await kudos.milestone('100 customers!', 100);
```

## Fire and Forget

For non-blocking event tracking, use fire-and-forget mode:

```typescript
// Returns immediately, doesn't wait for response
kudos.track({ type: 'pageview' }, { fireAndForget: true });
```

## Error Handling

The SDK handles errors gracefully and returns structured error responses:

```typescript
const result = await kudos.track({ type: 'sale' });

if (!result.success) {
  console.error(result.error); // Error message
  console.error(result.code);  // Error code (e.g., 'INVALID_API_KEY')
}
```

### Error Codes

| Code | Description |
|------|-------------|
| `MISSING_API_KEY` | No API key provided |
| `INVALID_API_KEY` | API key is invalid |
| `INVALID_PAYLOAD` | Request body is malformed |
| `PAYLOAD_TOO_LARGE` | Request exceeds 100KB limit |
| `RATE_LIMITED` | Too many requests |
| `INTERNAL_ERROR` | Server error |
| `TIMEOUT` | Request timed out |
| `NETWORK_ERROR` | Network connection failed |

## TypeScript

Full TypeScript support is included:

```typescript
import { Kudos, TrackEventData, TrackResponse } from '@kudosapi/sdk';

const event: TrackEventData = {
  type: 'sale',
  value: 99,
  currency: 'USD'
};

const result: TrackResponse = await kudos.track(event);
```

## Publishing (Maintainers)

To publish a new version to npm:

1. **Update version** in `packages/sdk/package.json`
2. **Run the deploy script** from the repo root:
   ```bash
   ./scripts/deploy-sdk-npm.sh
   ```
3. **When prompted**, enter your npm 2FA code (from your authenticator app):
   ```bash
   cd packages/sdk && npm publish --access public --otp=YOUR_6_DIGIT_CODE
   cd ../.. && git checkout dev
   ```

The deploy script will checkout `master`, run tests, build, and prompt for publish confirmation.

## License

MIT