npm package: @joyida/eskiz
Description: Zero-dependency, fully typed Bun SDK for Eskiz.uz SMS API with namespaced architecture
Author: Joyida Team
Latest version: 0.2.1

# Eskiz SMS - Bun SDK

> **Zero-dependency**, namespaced architecture, fully typed SDK for Eskiz.uz SMS API

[![CI](https://github.com/joyida/eskiz/actions/workflows/ci.yml/badge.svg)](https://github.com/joyida/eskiz/actions/workflows/ci.yml)
[![Test Runtimes](https://github.com/joyida/eskiz/actions/workflows/test-runtimes.yml/badge.svg)](https://github.com/joyida/eskiz/actions/workflows/test-runtimes.yml)
[![Bun](https://img.shields.io/badge/bun-%3E%3D1.3.9-orange.svg)](https://bun.sh/)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)
[![Zero Dependencies](https://img.shields.io/badge/dependencies-0-success.svg)](package.json)

## ✨ Features

- 🚀 **Zero Dependencies** - Native Bun only
- 📦 **Namespaced API** - Clean, organized structure
- 💪 **Fully Typed** - 100% TypeScript with strict mode
- ⚡ **Native Fetch** - Built-in fetch API
- 🎯 **DRY Principle** - Zero code duplication
- 🔒 **Type Safe** - Strong typing everywhere
- 🏗️ **Clean Architecture** - Separated services
- 🔔 **Webhook Support** - Built-in callback server
- 📦 **ESM Support** - Modern module system

## 📋 Requirements

- **Bun** >= 1.3.9

## 🔧 Compatibility

✅ **ESM (ES Modules)** - `import` syntax  
✅ **TypeScript** - Full type definitions  
✅ **Bun 1.3.9+** - Optimized runtime  
✅ **Modern Frameworks** - Vite, Hono, Elysia, etc.  

Works with:
- Hono
- Elysia
- Bun native HTTP server
- Any modern Bun/TypeScript project

## 📥 Installation

```bash
bun add @joyida/eskiz
```

## 🚀 Quick Start

```typescript
import { EskizSMS } from '@joyida/eskiz';

const client = new EskizSMS({
  email: 'your@email.uz',
  password: 'your_password',
});

// Namespaced API - clean and organized!
await client.sms.send({
  mobile_phone: '998901234567',
  message: 'Hello from Eskiz!',
});
```

## 📚 API Reference

### 🔐 Authentication (`client.auth`)

```typescript
// Login (automatic on first API call)
await client.auth.login();

// Get current user
const user = await client.auth.getUser();
console.log(user.name, user.balance);

// Refresh token
await client.auth.refresh();
```

### 📤 SMS Operations (`client.sms`)

```typescript
// Send single SMS
await client.sms.send({
  mobile_phone: '998901234567',
  message: 'Test message',
  from: '4546',
  callback_url: 'https://your-domain.com/callback', // optional
});

// Send batch SMS
await client.sms.sendBatch({
  messages: [
    { to: 998901234567, text: 'Message 1' },
    { to: 998901234568, text: 'Message 2' },
  ],
  from: '4546',
  dispatch_id: 12345,
});

// Send international SMS
await client.sms.sendGlobal({
  mobile_phone: '12025550123',
  message: 'Hello!',
  country_code: 'US',
});

// Normalize SMS (check special characters)
const normalized = await client.sms.normalize('Test €100');
console.log(normalized.message);

// Check SMS (price, parts, etc.)
const check = await client.sms.check('Message');
console.log(`Parts: ${check.parts_count}, Price: ${check.info[0].price}`);
```

### 📨 Messages (`client.messages`)

```typescript
// Get message status (by ID or UUID)
const status = await client.messages.getStatus('sms-id');
console.log(status.status); // DELIVERED, REJECTED, etc.

// List messages
const messages = await client.messages.list({
  start_date: '2026-01-01 00:00',
  end_date: '2026-01-31 23:59',
  page_size: 50,
});

// List by dispatch
const dispatchMsgs = await client.messages.listByDispatch({
  dispatch_id: 12345,
});

// Get dispatch status
const dispatchStatus = await client.messages.getDispatchStatus({
  dispatch_id: 12345,
});

// Get system logs
const logs = await client.messages.getLogs('sms-id');
```

### 👤 User (`client.user`)

```typescript
// Get balance
const balance = await client.user.getBalance();
console.log(`Balance: ${balance} UZS`);

// Get sender names
const nicknames = await client.user.getNicknames();
console.log(nicknames);

// Get templates
const templates = await client.user.getTemplates();

// Create template
await client.user.createTemplate('Your template text');
```

### 📊 Reports (`client.reports`)

```typescript
// Monthly totals
const monthly = await client.reports.getMonthly(2026);

// Totals by SMSC (operators)
const bySMSC = await client.reports.getBySMSC();

// Totals by date range
const byRange = await client.reports.getByRange({
  start_date: '2026-01-01 00:00',
  to_date: '2026-01-31 23:59',
});

// Totals by dispatch
const byDispatch = await client.reports.getByDispatch({
  dispatch_id: 12345,
});

// Year totals
const yearTotals = await client.reports.getYearTotals({
  year: 2026,
});

// Export messages
await client.reports.export({
  year: 2026,
  month: 1,
  status: 'all',
});
```

### 🔑 Token Management

```typescript
// Set token (for persistence)
client.setToken('saved_token');

// Get current token
const token = client.getToken();

// Check if expired
const expired = client.isTokenExpired();

// Clear token
client.clearToken();
```

## 🔔 Webhook / Callbacks

```typescript
import { createWebhookServer } from '@joyida/eskiz';

const server = createWebhookServer({
  port: 3000,
  path: '/sms-callback',
  onCallback: async (data) => {
    console.log(`SMS ${data.message_id}: ${data.status}`);
    
    // Process callback
    if (data.status === 'DELIVRD') {
      await updateDatabase(data);
    }
  },
});

server.start();

// Send SMS with callback
await client.sms.send({
  mobile_phone: '998901234567',
  message: 'Test',
  callback_url: 'https://your-domain.com/sms-callback',
});
```

## 🎯 Complete Example

```typescript
import { EskizSMS } from '@joyida/eskiz';

const client = new EskizSMS({
  email: process.env.ESKIZ_EMAIL!,
  password: process.env.ESKIZ_PASSWORD!,
});

// Check balance
const balance = await client.user.getBalance();
if (balance < 1000) {
  console.log('Low balance!');
  return;
}

// Check SMS
const check = await client.sms.check('Test message');
if (!check.can_send) {
  console.log('Cannot send SMS');
  return;
}

// Send SMS
const sms = await client.sms.send({
  mobile_phone: '998901234567',
  message: 'Test message',
  from: '4546',
});

console.log(`Sent: ${sms.id}`);

// Wait and check status
await new Promise(r => setTimeout(r, 5000));

const status = await client.messages.getStatus(sms.id);
console.log(`Status: ${status.status}`);

// Get monthly report
const monthly = await client.reports.getMonthly(2026);
console.log('Monthly stats:', monthly);
```

## 🏗️ Architecture

```
client.auth.*       → Authentication
client.sms.*        → SMS operations
client.messages.*   → Message queries
client.user.*       → User operations
client.reports.*    → Analytics & reports
```

**Benefits:**
- ✅ Clear separation of concerns
- ✅ Easy to discover methods (autocomplete)
- ✅ Logical grouping
- ✅ No code duplication
- ✅ Easy to extend

## 🔒 Environment Variables

```bash
# .env
ESKIZ_EMAIL=your@email.uz
ESKIZ_PASSWORD=your_password
```

```typescript
// Bun (built-in)
const client = new EskizSMS({
  email: Bun.env.ESKIZ_EMAIL!,
  password: Bun.env.ESKIZ_PASSWORD!,
});
```

## 📦 Bundle Size

- **~15KB** minified (ESM)
- **~5KB** gzipped
- Zero dependencies!

## 🧪 Testing

```bash
bun test
```

## 📄 License

MIT

## 🤝 Contributing

Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details.

## 📝 Changelog

See [CHANGELOG.md](CHANGELOG.md) for release history.

## 🔗 Links

- [Eskiz.uz](https://eskiz.uz)
- [API Documentation](https://documenter.getpostman.com/view/663428/RzfmES4z)
- [GitHub](https://github.com/joyida/eskiz)
- [NPM Package](https://www.npmjs.com/package/@joyida/eskiz)

## 📧 Support

- GitHub Issues: [Report a bug](https://github.com/joyida/eskiz/issues)
- Email: support@joyida.uz

## ⚠️ Important Notes

- This package requires Bun 1.3.9+ for native fetch API support
- Keep your Eskiz credentials secure (use environment variables)
- Test in development before production use
- Check your SMS balance before sending bulk messages

---

**Made with ❤️ for Uzbekistan developers**

Supports Bun 1.3.9+, ESM