npm package: @slackgram/logger
Description: TypeScript-first logger for Node.js with file rotation and webhook support for Discord/Slack/Telegram
Latest version: 1.0.16

## @slackgram/logger

`@slackgram/logger` is a modern, dependency‑free, TypeScript‑first logging system that works in Node.js and can be bundled into browser/front‑end apps. It provides colorful, human‑friendly logs in development and structured JSON logs in production, with optional **file logging** and **real‑time tracking** via Slack / Telegram (and Discord) webhooks/bots.

### Features

- **Dependency‑free**: Uses only built‑in Node APIs when available.
- **Log levels**: `debug`, `info`, `warn`, `error`.
- **Optional emojis** and **colored console output**.
- **Timestamps** by default (ISO 8601 with milliseconds).
- **File logging** (Node.js):
  - Configurable path.
  - Rotation: `"1H"`, `"1D"`, `"1W"`.
  - Retention by max number of files.
  - Buffered, async, non‑blocking writes.
  - Optional pretty JSON lines.
- **Hooks system**:
  - Discord / Slack / Telegram integrations.
  - Hook thresholds via `hooks.minLevel`.
  - Fire asynchronously; failures are swallowed (best‑effort).
- **Pretty formatting**:
  - Objects / arrays via safe `JSON.stringify`.
  - `Error` → stack.
  - `BigInt` → `"123n"`.
  - Node `Buffer` → `"<Buffer length=...>"`.
- **Convenience utilities**:
  - `log.time(label, asyncFn)` → times async code.
  - `log.group()` / `log.groupEnd()` for indentation‑based grouping.
  - `log.tag("HTTP")` to create tagged child loggers.
- **Environment aware**:
  - `development` → colorful text logs.
  - `production` → one JSON object per console line.

### Installation

Add the files to your project (or publish to npm and install from there):

```bash
pnpm add @slackgram/logger
# or
npm install @slackgram/logger
# or
yarn add @slackgram/logger
```

If using this repo directly, just reference the entry file in your imports (e.g. `./src/index`).

### Basic usage

```ts
import log, { config } from '@slackgram/logger';

config({
  env: 'development',
  minLevel: 'info',
  debug: true,
});

log.info('Server started on port', 3000);
log.warn('Cache miss for key', 'user:123');
log.error('Unexpected error', new Error('boom'));
log.debug('Raw payload', { foo: 'bar' });
```

### Tagging

```ts
import log, { tag } from '@slackgram/logger';

const httpLog = tag('HTTP');

httpLog.info('GET /users', { userId: 42 });
httpLog.error('Request failed', new Error('timeout'));
```

### Timing async work

```ts
await log.time('user.fetch', async () => {
  // some async work
});
```

This will emit debug‑level logs like:

- `⏱️ user.fetch - start`
- `⏱️ user.fetch - done in 37ms`

### Grouping logs

```ts
log.group('Processing batch #1');
log.info('Step 1');
log.info('Step 2');
log.groupEnd();
```

In development this adds indentation to grouped logs to make them visually distinct.

### File logging (Node.js)

```ts
import log, { config } from '@slackgram/logger';

config({
  file: {
    enabled: true,
    filePath: 'logs/app.log',
    rotation: {
      strategy: '1D', // rotate daily
      maxFiles: 7, // keep last 7
    },
    flushIntervalMs: 2000,
    prettyJson: true,
  },
});
```

File logging is **no‑op in browser** environments; it only activates when a Node‑like `process.cwd()` is available.

You can force a flush (for example, before process exit):

```ts
await log.flush();
```

### Webhook hooks (Discord, Slack, Telegram)

```ts
import { config } from '@slackgram/logger';

config({
  hooks: {
    minLevel: 'error', // only trigger on error and above
    discord: {
      enabled: true,
      webhookUrl: 'https://discord.com/api/webhooks/...',
    },
    slack: {
      enabled: true,
      webhookUrl: 'https://hooks.slack.com/services/...',
    },
    telegram: {
      enabled: true,
      botToken: 'BOT_TOKEN',
      chatId: 'CHAT_ID',
    },
  },
});
```

Hooks are fired asynchronously and are best‑effort; network/HTTP errors are ignored so logging never blocks your application.

### Setting hooks via environment variables

Keep webhook URLs and tokens out of code by using environment variables. In Node.js, read `process.env` when calling `config()`:

```ts
import { config } from '@slackgram/logger';

config({
  hooks: {
    minLevel: process.env.MB_LOG_HOOK_LEVEL || 'warn',
    discord: {
      enabled: !!process.env.DISCORD_WEBHOOK_URL,
      webhookUrl: process.env.DISCORD_WEBHOOK_URL || '',
    },
    slack: {
      enabled: !!process.env.SLACK_WEBHOOK_URL,
      webhookUrl: process.env.SLACK_WEBHOOK_URL || '',
    },
    telegram: {
      enabled: !!(process.env.TELEGRAM_BOT_TOKEN && process.env.TELEGRAM_CHAT_ID),
      botToken: process.env.TELEGRAM_BOT_TOKEN || '',
      chatId: process.env.TELEGRAM_CHAT_ID || '',
    },
  },
});
```

**Suggested env vars**

| Variable | Used by | Description |
|----------|---------|-------------|
| `DISCORD_WEBHOOK_URL` | Discord | Incoming webhook URL from Discord server settings |
| `SLACK_WEBHOOK_URL` | Slack | Incoming webhook URL from Slack app (e.g. `https://hooks.slack.com/services/...`) |
| `TELEGRAM_BOT_TOKEN` | Telegram | Bot token from @BotFather |
| `TELEGRAM_CHAT_ID` | Telegram | Chat or group ID (e.g. from `getUpdates` after messaging the bot) |
| `MB_LOG_HOOK_LEVEL` | All | Minimum level to send to hooks: `debug`, `info`, `warn`, `error` (optional) |
| `MB_LOGGER_TELEGRAM_API` | Telegram | Override Telegram API base URL (optional, default `https://api.telegram.org`) |

**Setting env vars when running**

**Windows (cmd):**
```cmd
set DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
set SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
set TELEGRAM_BOT_TOKEN=123456789:ABC...
set TELEGRAM_CHAT_ID=-1001234567890
set MB_LOG_HOOK_LEVEL=warn
node index.mjs
```

**Windows (PowerShell):**
```powershell
$env:DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
$env:SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
$env:TELEGRAM_BOT_TOKEN="123456789:ABC..."
$env:TELEGRAM_CHAT_ID="-1001234567890"
$env:MB_LOG_HOOK_LEVEL="warn"
node index.mjs
```

**Linux / macOS:**
```bash
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
export TELEGRAM_BOT_TOKEN="123456789:ABC..."
export TELEGRAM_CHAT_ID="-1001234567890"
export MB_LOG_HOOK_LEVEL="warn"
node index.mjs
```

Or use a `.env` file with a loader (e.g. `dotenv`) and load it before calling `config()`; never commit `.env` to version control.

### Configuration reference

```ts
import type { LoggerConfig } from '@slackgram/logger';

const cfg: LoggerConfig = {
  env: 'development', // 'development' | 'production' | 'test'
  minLevel: 'info', // 'debug' | 'info' | 'warn' | 'error'
  silent: false,
  debug: false,
  colors: true,

  levels: {
    debug: { enabled: true, emoji: '🐛' },
    info: { enabled: true, emoji: 'ℹ️' },
    warn: { enabled: true, emoji: '⚠️' },
    error: { enabled: true, emoji: '⛔' },
  },

  file: {
    enabled: true,
    filePath: 'logs/app.log',
    rotation: {
      strategy: '1D', // '1H' | '1D' | '1W'
      maxFiles: 7,
    },
    flushIntervalMs: 2000,
    prettyJson: true,
  },

  hooks: {
    minLevel: 'error',
    discord: { enabled: true, webhookUrl: '' },
    slack: { enabled: true, webhookUrl: '' },
    telegram: { enabled: false, botToken: '', chatId: '' },
  },

  timestampFn: () => new Date().toISOString(),
};
```

### TypeScript & JavaScript

- In **TypeScript**, import from the package name or file path; types are defined in `types.ts` and surfaced via the bundled declaration file.
- In **JavaScript**, you can still import the default logger and call the same methods; you just won’t get static type checking unless your tooling reads `.d.ts` files.