npm package: @kreativa/tools-client
Description: TypeScript SDK for Kreativa Tools services (email, media, logger)
Author: Kreativa
Latest version: 1.1.0

# @kreativa/tools-client

TypeScript SDK for Kreativa Tools services - Email, Media, and Logger.

## Installation

```bash
npm install @kreativa/tools-client
# or
pnpm add @kreativa/tools-client
# or
yarn add @kreativa/tools-client
```

## Quick Start

```typescript
import { createEmailApi, createMediaApi, createCompatApi, createLogger } from '@kreativa/tools-client'

// Email client
const email = createEmailApi({ apiKey: 'your-api-key' })

// Media client
const media = createMediaApi({ apiKey: 'your-api-key' })

// Compat client (XChaCha20-Poly1305 encrypted files)
const compat = createCompatApi({ apiKey: 'your-api-key' })

// Logger client
const logger = createLogger({ apiKey: 'your-api-key' })
```

---

## Logger Client

Track events, errors, and user behavior in your applications.

### Basic Usage

```typescript
import { createLogger } from '@kreativa/tools-client'

const logger = createLogger({
  apiKey: 'your-project-api-key',
  environment: 'production',
  product: 'portal',
})

// Log events
logger.log('button_clicked', { button_id: 'submit' })
logger.info('User logged in')
logger.error('Payment failed', { code: 'CARD_DECLINED' })
logger.success('Order completed', { order_id: '12345' })
logger.warn('Low inventory', { remaining: 5 })
logger.debug('API response', { data: response })
```

### Configuration

```typescript
interface LoggerConfig {
  apiKey: string                    // Required: Your project API key
  basePath?: string                 // API endpoint (default: '/api/logger')
  environment?: EnvironmentType     // 'production' | 'stage' | 'preview' | 'development' | 'test'
  product?: ProductType             // 'portal' | 'phone-app' | 'server' | 'image-server' | 'api' | 'other'
  batchSize?: number                // Events before auto-flush (default: 10)
  flushInterval?: number            // Ms between auto-flushes (default: 5000)
  autoCapture?: {
    pageViews?: boolean             // Auto-log page navigations (default: false)
    errors?: boolean                // Capture unhandled errors (default: false)
  }
}
```

### Auto-Capture

Automatically track page views and unhandled errors:

```typescript
const logger = createLogger({
  apiKey: 'your-api-key',
  autoCapture: {
    pageViews: true,    // Logs 'page_view' on navigation
    errors: true,       // Logs 'unhandled_error' and 'unhandled_promise_rejection'
  },
})
```

### User Identification

```typescript
// Identify a user (call after login)
logger.identify('user_123', {
  email: 'user@example.com',
  plan: 'premium',
})

// Update user properties
logger.setUserProperties({ plan: 'enterprise' })

// Clear user data (call on logout)
logger.reset()
```

### Manual Flush

Events are batched and sent automatically. Force an immediate flush:

```typescript
await logger.flush()
```

### Cleanup

```typescript
// Stop the logger and flush remaining events
logger.destroy()
```

### Log Types

| Method | Type | Use Case |
|--------|------|----------|
| `log(event, props)` | info | General events |
| `info(message, props)` | info | Informational messages |
| `error(event, props)` | error | Errors and failures |
| `success(message, props)` | success | Successful operations |
| `warn(message, props)` | warning | Warnings |
| `debug(message, props)` | debug | Debug information |

---

## Email Client

Send emails using templates.

### Basic Usage

```typescript
import { createEmailApi } from '@kreativa/tools-client'

const email = createEmailApi({ apiKey: 'your-api-key' })

// Send email using template
await email.sendEmail({
  templateSlug: 'welcome-email',
  to: 'user@example.com',
  params: {
    name: 'John',
    activationLink: 'https://example.com/activate/xyz',
  },
})

// Or use template ID
await email.sendEmail({
  templateId: '507f1f77bcf86cd799439011',
  to: ['user1@example.com', 'user2@example.com'],
  params: { ... },
})
```

### Configuration

```typescript
interface EmailApiOptions {
  basePath?: string    // API endpoint (default: '/api/email')
  apiKey?: string      // Your project API key
}
```

### Methods

```typescript
// Send email
email.sendEmail(params: SendEmailParams): Promise<SendEmailResponse>

// Generic HTTP methods
email.get<T>(endpoint, params?)
email.post<T>(endpoint, body?)
email.put<T>(endpoint, body?)
email.delete<T>(endpoint)
```

---

## Media Client

Upload, manage, and serve files.

### Basic Usage

```typescript
import { createMediaApi } from '@kreativa/tools-client'

const media = createMediaApi({ apiKey: 'your-api-key' })

// Upload a file
const result = await media.uploadFile({
  projectId: 'your-project-id',
  file: fileBlob,
  filename: 'photo.jpg',
  folder: 'avatars',
  accessType: 'public',
})

// List files
const files = await media.listFiles({
  projectId: 'your-project-id',
  folder: 'avatars',
})

// Get file details
const file = await media.getFile('file-id')

// Move file to different folder
await media.moveFile('file-id', 'new-folder/path')

// Delete file
await media.deleteFile('file-id')
```

### Configuration

```typescript
interface MediaApiOptions {
  basePath?: string    // API endpoint (default: '/api/media')
  apiKey?: string      // Your project API key
}
```

### Upload Options

```typescript
interface UploadFileParams {
  projectId: string
  file: File | Blob
  filename?: string
  folder?: string                    // e.g., 'images/avatars'
  accessType?: FileAccessType        // 'public' | 'token' | 'server-only' | 'e2e-encrypted' | 'server-encrypted'
}
```

### Access Types

| Type | Description |
|------|-------------|
| `public` | Accessible via public URL |
| `token` | Requires signed token |
| `server-only` | Only accessible server-side |
| `server-encrypted` | Encrypted at rest (AES-256-GCM), decrypted on access |
| `e2e-encrypted` | End-to-end encrypted (client-side) |
| `xchacha-encrypted` | XChaCha20-Poly1305 with per-file client keys (PHP-compatible) |

### Methods

```typescript
media.uploadFile(params): Promise<UploadFileResponse>
media.deleteFile(fileId): Promise<DeleteFileResponse>
media.listFiles(params): Promise<ListFilesResponse>
media.getFile(fileId): Promise<{ success: boolean; data?: MediaFile }>
media.moveFile(fileId, folder): Promise<{ success: boolean; data?: MediaFile }>

// Generic HTTP methods
media.get<T>(endpoint, params?)
media.post<T>(endpoint, body?)
media.put<T>(endpoint, body?)
media.patch<T>(endpoint, body?)
media.delete<T>(endpoint)
media.upload<T>(endpoint, formData, params?)
```

---

## Compat API (XChaCha20-Poly1305 Encryption)

Upload and download files with XChaCha20-Poly1305 encryption, compatible with PHP sodium encryption.

### Basic Usage

```typescript
import { createCompatApi } from '@kreativa/tools-client'

const compat = createCompatApi({
  apiKey: 'your-project-api-key',
  basePath: 'https://media.example.com/api',  // Optional
})

// Generate a random encryption key
const encryptionKey = compat.generateKey()

// Upload a file with encryption
const result = await compat.upload({
  file: fileBlob,
  encryptionKey,
  app: 'myapp',        // Optional: defaults to project slug
  tag: 'avatars',      // Optional: defaults to 'general'
})

console.log(result.data.id)  // File ID for later retrieval

// Download and decrypt a file
const blob = await compat.download({
  id: result.data.id,
  encryptionKey,
})

// Or download using PHP-compatible path pattern
const blob2 = await compat.downloadByPath({
  app: 'myapp',
  tag: 'avatars',
  id: 'file-id',
  encryptionKey,
})

// Delete a file
await compat.delete('file-id')
await compat.deleteByPath('myapp', 'avatars', 'file-id')
```

### Configuration

```typescript
interface CompatApiOptions {
  apiKey: string       // Required: Your project API key
  basePath?: string    // API endpoint (default: '/api')
}
```

### Upload Options

```typescript
interface CompatUploadParams {
  file: File | Blob
  encryptionKey: string  // Base64-encoded 32-byte key
  app?: string           // Application identifier (default: project slug)
  tag?: string           // File category/tag (default: 'general')
  date?: string          // ISO 8601 date for folder structure (default: now)
  id?: string            // Custom file ID (default: auto-generated)
}
```

### Key Management

The encryption key is a 32-byte random value that you must store securely:

```typescript
// Generate a new key
const key = compat.generateKey()

// Store this key securely - you need it to decrypt the file!
// The server cannot decrypt without this key.

// Example: Store with the file reference in your database
await db.files.insert({
  fileId: result.data.id,
  encryptionKey: key,  // Store encrypted or in secure storage
})
```

### PHP Interoperability

Files encrypted with this API can be decrypted by the PHP file server and vice versa, as long as both use the same master key (`XCHACHA_MASTER_KEY`).

The encryption uses:
- **Algorithm**: XChaCha20-Poly1305 (libsodium)
- **Key derivation**: HMAC-SHA256(clientKey, masterKey)
- **Format**: 24-byte nonce + ciphertext (metadata + file content)

### Methods

```typescript
// Generate random encryption key
compat.generateKey(): string

// Upload with encryption
compat.upload(params: CompatUploadParams): Promise<CompatUploadResponse>

// Download and decrypt by ID
compat.download(params: CompatDownloadParams): Promise<Blob>

// Download by PHP path pattern (app/tag/id)
compat.downloadByPath(params: CompatDownloadByPathParams): Promise<Blob>

// Delete by ID
compat.delete(id: string): Promise<CompatDeleteResponse>

// Delete by PHP path pattern
compat.deleteByPath(app: string, tag: string, id: string): Promise<CompatDeleteResponse>
```

---

## Generic API Client

Create a client for any service:

```typescript
import { createApiClient } from '@kreativa/tools-client'

const client = createApiClient('/api/custom', { apiKey: 'your-key' })

await client.get('/endpoint')
await client.post('/endpoint', { data: 'value' })
await client.put('/endpoint', { data: 'value' })
await client.patch('/endpoint', { data: 'value' })
await client.delete('/endpoint')
await client.upload('/endpoint', formData)
```

---

## Session Handling

The SDK automatically handles 401 responses by dispatching a custom event:

```typescript
import { SESSION_EXPIRED_EVENT } from '@kreativa/tools-client'

window.addEventListener(SESSION_EXPIRED_EVENT, () => {
  // Redirect to login or refresh token
  window.location.href = '/login'
})
```

---

## TypeScript Types

All types are exported:

```typescript
import type {
  // Email
  SendEmailParams,
  SendEmailResponse,
  EmailApiClient,

  // Media
  MediaFile,
  FileAccessType,
  StorageBackend,
  UploadFileParams,
  UploadFileResponse,
  ListFilesParams,
  ListFilesResponse,
  DeleteFileResponse,
  MediaApiClient,

  // Compat (XChaCha20 encryption)
  CompatUploadParams,
  CompatUploadResponse,
  CompatDownloadParams,
  CompatDownloadByPathParams,
  CompatDeleteResponse,
  CompatApiClient,
  XChachaMeta,

  // Logger
  LoggerConfig,
  LogEvent,
  LogType,
  DeviceType,
  ProductType,
  EnvironmentType,
  Logger,

  // Generic
  ApiClient,
  ServiceId,
} from '@kreativa/tools-client'
```

---

## Environment Variables

When using in a browser with Vite:

```env
VITE_MEDIA_API_URL=/api/media
VITE_EMAIL_API_URL=/api/email
VITE_LOGGER_API_URL=/api/logger
```

The SDK will automatically use these if no `basePath` is provided.

---

## License

MIT