npm package: @holler2660/console-text
Description: Send SMS alerts from your code with console.text()
Author: Noel
Latest version: 0.1.0

# @console-text/sdk

Get alerted when critical code paths execute. As simple as `console.text('Error!')` and you'll receive an SMS.

## Why console.text()?

You're fast asleep. Your checkout flow breaks. You're losing thousands of dollars per hour.

**Traditional approach:**
1. Set up DataDog (enterprise complexity)
2. Configure PagerDuty (more complexity)
3. Hope your alerts work

**console.text() approach:**
```javascript
try {
  await processPayment(order);
} catch (error) {
  console.text('Payment failed!', { orderId: order.id });
  // You get an SMS within 5 seconds
}
```

That's it. One line of code. No enterprise complexity.

## Installation

```bash
npm install @console-text/sdk
```

## Quick Start

### 1. Initialize (once in your app)

```javascript
import { init } from '@console-text/sdk';

init({
  apiKey: 'ct_live_xxxxxxxxxxxxx' // Get from dashboard
});
```

### 2. Use anywhere in your code

```javascript
// In critical error handlers
try {
  await chargeCustomer(amount);
} catch (error) {
  console.text('Payment failed!', {
    customerId: customer.id,
    amount,
    error: error.message
  });
}

// In monitoring checks
if (queueDepth > 10000) {
  console.text('Queue backing up!', { depth: queueDepth });
}

// In cron jobs
if (dailyRevenue < yesterdayRevenue * 0.5) {
  console.text('Revenue drop detected!', {
    today: dailyRevenue,
    yesterday: yesterdayRevenue
  });
}
```

## API Reference

### `init(options)`

Initializes the SDK and adds `console.text()` to the global console object.

**Parameters:**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `apiKey` | string | Yes | Your API key (`ct_live_*` or `ct_test_*`) |
| `endpoint` | string | No | API endpoint (default: `https://api.consoletext.dev`) |
| `debug` | boolean | No | Enable debug logging (default: `false`) |

**Example:**

```javascript
import { init } from '@console-text/sdk';

init({
  apiKey: process.env.CONSOLE_TEXT_API_KEY,
  debug: process.env.NODE_ENV === 'development'
});
```

### `console.text(message, metadata?, options?)`

Sends an alert to your phone via SMS.

**Parameters:**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `message` | string | Yes | Alert message (max 500 chars, auto-truncated) |
| `metadata` | object | No | Additional context (logged in dashboard) |
| `options.severity` | string | No | `'info'`, `'warning'`, or `'critical'` (default: `'info'`) |

**Example:**

```javascript
// Simple message
console.text('Deployment complete!');

// With metadata
console.text('Database connection lost', {
  host: 'db.example.com',
  retryCount: 3
});

// With severity
console.text('Critical: Server out of memory!', {
  memUsage: '98%',
  severity: 'critical'
});
```

## Features

### ✅ Never Crashes Your App

**The #1 rule:** Alerting failures should never break your application.

```javascript
console.text('Test'); // If this fails, your app keeps running
```

All errors are caught and logged (if debug mode enabled). Your app never knows if the alert succeeded or failed.

### ✅ Smart Rate Limiting

Same message won't spam you:

```javascript
// Only sends ONE SMS within 5 minutes
for (let i = 0; i < 100; i++) {
  console.text('Error in loop!');
}
```

Rate limiting is per-message, so different errors still get through:

```javascript
console.text('Payment failed');  // ✅ Sends SMS
console.text('Database error');   // ✅ Sends SMS (different message)
console.text('Payment failed');   // ❌ Rate limited (same as first)
```

**Pro tip:** Add dynamic data to bypass rate limiting when needed:

```javascript
console.text(`Payment failed at ${new Date().toISOString()}`);
// Each timestamp creates a unique message
```

### ✅ Tiny Bundle Size

- **4.71 KB** minified
- **Zero dependencies**
- Tree-shakeable ESM

### ✅ TypeScript Support

Full type definitions included:

```typescript
import { init, AlertOptions } from '@console-text/sdk';

init({ apiKey: 'ct_live_xxx' });

const metadata: Record<string, any> = {
  userId: '123',
  timestamp: new Date()
};

const options: AlertOptions = {
  severity: 'critical'
};

console.text('Error!', metadata, options);
```

## Environment-Specific Keys

Use **test keys** in development to avoid SMS costs:

```javascript
// .env.development
CONSOLE_TEXT_API_KEY=ct_test_xxxxx

// .env.production
CONSOLE_TEXT_API_KEY=ct_live_xxxxx
```

**Test keys** (`ct_test_*`):
- Don't send real SMS
- Log to API console instead
- Perfect for development/staging

**Live keys** (`ct_live_*`):
- Send real SMS via Twilio
- Count against your quota
- Use in production only

## Real-World Examples

### Example 1: E-commerce Checkout

```javascript
import { init } from '@console-text/sdk';

init({ apiKey: process.env.CONSOLE_TEXT_API_KEY });

export async function processOrder(order) {
  try {
    const payment = await stripe.charges.create({
      amount: order.total,
      source: order.paymentToken
    });

    await db.orders.create({ ...order, paymentId: payment.id });

    return { success: true };
  } catch (error) {
    // Get alerted immediately
    console.text('Checkout failed!', {
      orderId: order.id,
      amount: order.total,
      error: error.message,
      customer: order.customerId
    });

    throw error;
  }
}
```

### Example 2: Cron Job Monitoring

```javascript
import { init } from '@console-text/sdk';

init({ apiKey: process.env.CONSOLE_TEXT_API_KEY });

// Daily report generation
export async function generateDailyReport() {
  const startTime = Date.now();

  try {
    const report = await buildReport();
    await uploadToS3(report);

    const duration = Date.now() - startTime;

    // Alert if too slow
    if (duration > 300000) { // 5 minutes
      console.text('Daily report slow!', {
        duration: `${duration / 1000}s`,
        date: new Date().toISOString()
      });
    }
  } catch (error) {
    console.text('Daily report failed!', {
      error: error.message,
      date: new Date().toISOString()
    });

    throw error;
  }
}
```

### Example 3: Health Check Monitoring

```javascript
import { init } from '@console-text/sdk';

init({ apiKey: process.env.CONSOLE_TEXT_API_KEY });

// Check critical services every minute
setInterval(async () => {
  // Check database
  try {
    await db.raw('SELECT 1');
  } catch (error) {
    console.text('Database health check failed!', {
      service: 'postgresql',
      error: error.message
    });
  }

  // Check Redis
  try {
    await redis.ping();
  } catch (error) {
    console.text('Redis health check failed!', {
      service: 'redis',
      error: error.message
    });
  }

  // Check external API
  try {
    const response = await fetch('https://api.stripe.com/v1/charges');
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
  } catch (error) {
    console.text('Stripe API unreachable!', {
      service: 'stripe',
      error: error.message
    });
  }
}, 60000);
```

### Example 4: Express.js Error Handler

```javascript
import express from 'express';
import { init } from '@console-text/sdk';

init({ apiKey: process.env.CONSOLE_TEXT_API_KEY });

const app = express();

// Global error handler
app.use((err, req, res, next) => {
  console.error(err);

  // Alert on 500 errors
  if (err.status === 500 || !err.status) {
    console.text('Server error!', {
      error: err.message,
      path: req.path,
      method: req.method,
      stack: err.stack?.split('\n')[0]
    });
  }

  res.status(err.status || 500).json({
    error: 'Internal server error'
  });
});
```

## Configuration Best Practices

### Use Environment Variables

```javascript
// config.js
import { init } from '@console-text/sdk';

const apiKey = process.env.CONSOLE_TEXT_API_KEY;

if (!apiKey) {
  throw new Error('CONSOLE_TEXT_API_KEY environment variable required');
}

init({ apiKey });
```

### Initialize Once

```javascript
// ✅ Good - initialize in entry file
// index.js or app.js
import './config/console-text'; // Initializes SDK
import express from 'express';

const app = express();
// ... rest of app

// ❌ Bad - initializing multiple times
import { init } from '@console-text/sdk';

function handler() {
  init({ apiKey: 'xxx' }); // Don't do this
  console.text('Error');
}
```

### Don't Log Secrets

```javascript
// ❌ Bad - exposes secrets
console.text('Auth failed', {
  password: user.password,      // Never log passwords
  apiKey: config.stripeKey,     // Never log API keys
  token: session.token          // Never log tokens
});

// ✅ Good - safe logging
console.text('Auth failed', {
  userId: user.id,
  email: user.email.replace(/(.{2}).*(@.*)/, '$1***$2'), // Redact email
  reason: 'invalid_credentials'
});
```

## Troubleshooting

### Not receiving SMS?

1. **Check your API key format:**
   - Live keys: `ct_live_xxxxx`
   - Test keys: `ct_test_xxxxx` (don't send SMS)

2. **Check rate limiting:**
   - Same message only sends once per 5 minutes
   - Add timestamps to bypass: `` `Error ${Date.now()}` ``

3. **Check the dashboard:**
   - Log in to https://consoletext.dev
   - View all alert attempts (even rate-limited ones)

### Debug mode

Enable debug logging to see what's happening:

```javascript
init({
  apiKey: 'ct_test_xxx',
  debug: true
});

console.text('Test');
// Logs: [console.text] Sending alert: "Test"
// Logs: [console.text] Alert sent successfully
```

### TypeScript errors?

Make sure you're importing types correctly:

```typescript
import { init, AlertOptions } from '@console-text/sdk';

// Add to global console type
declare global {
  interface Console {
    text(message: string, metadata?: Record<string, any>, options?: AlertOptions): void;
  }
}
```

## FAQ

**Q: What happens if the API is down?**
A: The SDK fails silently. Your app continues running. Alerts are queued and sent when the API recovers.

**Q: Can I send to multiple phone numbers?**
A: Yes! Each API key maps to one phone number in your account settings. Create multiple API keys for team members.

**Q: Does this work in browsers?**
A: No, console.text() is for Node.js servers only. Browsers would expose your API key.

**Q: How much does it cost?**
A: First 100 alerts/month free. Then $0.01/alert. See [pricing](https://consoletext.dev/pricing).

**Q: Can I customize the SMS format?**
A: Not yet, but it's on our roadmap! Vote for features at [github.com/yourorg/console-text/discussions](https://github.com).

## Support

- **Documentation:** https://docs.consoletext.dev
- **Dashboard:** https://consoletext.dev
- **Issues:** https://github.com/yourorg/console-text/issues
- **Email:** support@consoletext.dev

## License

MIT

---

**Made with ☕ by developers tired of DataDog complexity**