npm package: @notif-hub/sdk
Description: TypeScript SDK for NotifHub push notification server
Latest version: 1.0.1

# @notif-hub/sdk

Official JavaScript/TypeScript SDK for NotifHub - Multi-tenant push notification service with FCM and APNs support.

## Installation

```bash
npm install @notif-hub/sdk
```

## Quick Start

```typescript
import { NotifHubClient } from '@notif-hub/sdk';

const client = new NotifHubClient({
  baseUrl: 'http://localhost:8080',
  apiKey: 'your-api-key',
});

const app = client.app('your-app-id');

await app.notifications.sendToAll({
  title: 'Hello World',
  body: 'This is a test notification',
});
```

## Complete Usage Guide

### 1. Initialize Client

```typescript
const client = new NotifHubClient({
  baseUrl: 'http://localhost:8080',
  apiKey: 'optional-api-key',
  timeout: 30000,    // optional, default 30s
  retries: 3,        // optional, default 3
});
```

### 2. Apps Management

```typescript
// Create app
const app = await client.apps.create({
  name: 'My App',
  slug: 'my-app',
});

// List apps
const { apps, total } = await client.apps.list();

// Get app
const app = await client.apps.get('app-id');

// Update app
await client.apps.update('app-id', {
  name: 'Updated Name',
  status: 'PAUSED',
});

// Delete app
await client.apps.delete('app-id');

// Update credentials
await client.apps.updateCredentials('app-id', {
  fcmProjectId: 'my-project',
  fcmServiceAccountEnc: JSON.stringify(serviceAccount),
  apnsKeyId: 'ABC123',
  apnsTeamId: 'TEAM123',
  apnsTopic: 'com.myapp',
  apnsEnvironment: 'PRODUCTION',
  apnsKeyP8Enc: '-----BEGIN PRIVATE KEY-----...',
});
```

### 3. Device Management

```typescript
const appClient = client.app('app-id');

// Register device
await appClient.devices.register({
  platform: 'IOS',
  deviceToken: 'device-token-here',
  userId: 'user-123',
  tags: ['premium', 'beta'],
  locale: 'en-US',
});

// List devices
const { devices, total } = await appClient.devices.list({
  platform: 'IOS',
  userId: 'user-123',
  limit: 100,
});

// Get device
const device = await appClient.devices.get('device-id');

// Delete device (unsubscribe)
await appClient.devices.delete('device-id');
```

### 4. Sending Notifications

```typescript
// Send to all users
await appClient.notifications.sendToAll({
  title: 'New Feature',
  body: 'Check out our latest update',
  data: { screen: 'features' },
});

// Send to specific devices
await appClient.notifications.sendToDevices(['device-1', 'device-2'], {
  title: 'Hello',
  body: 'Hello specific devices',
});

// Send to specific users
await appClient.notifications.sendToUsers(['user-1', 'user-2'], {
  title: 'Hello Users',
  body: 'Hello specific users',
}, {
  platform: 'IOS',  // optional
});

// Send to tags
await appClient.notifications.sendToTags(['premium', 'beta'], {
  title: 'Premium Feature',
  body: 'Check out our new feature',
}, {
  match: 'all',     // 'all' or 'any'
  platform: 'ANDROID',
});

// Scheduled notification
await appClient.notifications.sendToAll({
  title: 'Reminder',
  body: 'Your appointment is tomorrow',
}, {
  scheduledAt: '2025-12-31T23:59:59Z',
});

// Platform-specific options
await appClient.notifications.send({
  payload: {
    title: 'Platform Specific',
    body: 'Different options per platform',
    badge: 5,
    sound: 'default',
    ios: {
      subtitle: 'iOS Only',
      threadId: 'chat-1',
      categoryId: 'MESSAGE_CATEGORY',
    },
    android: {
      channelId: 'default',
      icon: 'ic_notification',
      color: '#FF0000',
    },
  },
  target: { type: 'all' },
});

// Advanced iOS Features
await appClient.notifications.send({
  payload: {
    title: 'Time Sensitive Alert',
    body: 'This notification bypasses Focus modes',
    interruptionLevel: 'time-sensitive', // 'passive' | 'active' | 'time-sensitive' | 'critical'
    mutableContent: true, // Enable notification service extensions
    collapseId: 'chat-123', // Collapse multiple notifications
    ttlSeconds: 3600, // 1 hour TTL
    ios: {
      pushType: 'alert',
      priority: 'immediate',
      imageUrl: 'https://example.com/image.png',
      relevanceScore: 0.8, // For notification summary
      targetContentId: 'screen://chat/123', // Deep linking
    },
  },
  target: { type: 'all' },
});

// Critical Sound (iOS) - requires special entitlement
await appClient.notifications.send({
  payload: {
    title: 'Emergency Alert',
    body: 'Critical notification with custom volume',
    sound: {
      name: 'emergency.aiff',
      critical: true,
      volume: 1.0, // 0.0 to 1.0
    },
    interruptionLevel: 'critical',
  },
  target: { type: 'users', userIds: ['user-1'] },
});

// Background Content Available (Silent Push)
await appClient.notifications.send({
  payload: {
    contentAvailable: true, // Silent push for background updates
    data: { action: 'sync', timestamp: Date.now().toString() },
    ios: {
      pushType: 'background',
      priority: 'throttled',
    },
  },
  target: { type: 'all' },
});

// Android Rich Notifications
await appClient.notifications.send({
  payload: {
    title: 'New Message',
    body: 'You have a new message',
    android: {
      channelId: 'messages',
      priority: 'HIGH',
      imageUrl: 'https://example.com/big-image.jpg',
      icon: 'ic_message',
      color: '#2196F3',
      tag: 'chat-123', // Replace previous notification with same tag
      clickAction: 'OPEN_CHAT',
    },
  },
  target: { type: 'users', userIds: ['user-1'] },
});
```

### 5. Notification Tracking

```typescript
// Get notification status
const status = await appClient.notifications.getStatus('notification-id');
console.log('Sent:', status.stats.sent);
console.log('Errors:', status.stats.error);

// List notification history
const { notifications, total } = await appClient.notifications.list({
  status: 'SENT',
  limit: 50,
  offset: 0,
});

// Get notification details
const notification = await appClient.notifications.get('notification-id');
```

### 6. Templates

```typescript
// Create template
await appClient.templates.create({
  key: 'welcome',
  title: 'Welcome {{name}}!',
  body: 'Thanks for joining {{appName}}',
  data: { type: 'welcome' },
  ios: { sound: 'welcome.aiff' },
  android: { channelId: 'welcome' },
});

// List templates
const { templates, total } = await appClient.templates.list();

// Get template
const template = await appClient.templates.get('welcome');

// Update template
await appClient.templates.update('welcome', {
  title: 'Welcome aboard {{name}}!',
});

// Delete template
await appClient.templates.delete('welcome');
```

### 7. API Keys

```typescript
// Create API key
const apiKey = await appClient.keys.create({
  name: 'Production Key',
  roles: ['send'],
});

console.log('IMPORTANT: Save this key:', apiKey.key);

// List API keys
const { keys, total } = await appClient.keys.list();

// Delete API key
await appClient.keys.delete('key-id');
```

## Error Handling

```typescript
import { NotifHubError } from '@notif-hub/sdk';

try {
  await appClient.notifications.sendToAll({
    title: 'Test',
    body: 'Test message',
  });
} catch (error) {
  if (error instanceof NotifHubError) {
    console.error('Error:', error.message);
    console.error('Code:', error.code);
    console.error('Status:', error.statusCode);
    console.error('Details:', error.details);
  }
}
```

## TypeScript Support

Full TypeScript support with comprehensive type definitions:

```typescript
import type {
  NotificationPayload,
  Platform,
  DeviceStatus,
  NotificationStatusType,
} from '@notif-hub/sdk';

const payload: NotificationPayload = {
  title: 'Hello',
  body: 'World',
  data: { key: 'value' },
};
```

## Complete Example

```typescript
import { NotifHubClient } from '@notif-hub/sdk';

async function main() {
  const client = new NotifHubClient({
    baseUrl: 'http://localhost:8080',
  });

  // Create app
  const app = await client.apps.create({
    name: 'My App',
    slug: 'my-app',
  });

  // Configure credentials
  await client.apps.updateCredentials(app.id, {
    fcmProjectId: 'my-project',
    fcmServiceAccountEnc: JSON.stringify(serviceAccount),
  });

  // Get app client
  const appClient = client.app(app.id);

  // Register device
  await appClient.devices.register({
    platform: 'ANDROID',
    deviceToken: 'fcm-token',
    userId: 'user-1',
    tags: ['premium'],
  });

  // Send notification
  const result = await appClient.notifications.sendToUsers(['user-1'], {
    title: 'Welcome',
    body: 'Thanks for signing up!',
    data: { screen: 'home' },
  });

  // Check status
  const status = await appClient.notifications.getStatus(result.notificationId);
  console.log('Sent to', status.stats.sent, 'devices');
}

main().catch(console.error);
```

## License

MIT