first commit
This commit is contained in:
100
docs/communication/messaging/discord-client/README.md
Normal file
100
docs/communication/messaging/discord-client/README.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# @suaveplan/discord-client - Generic Discord API client for webhooks, bot messaging, and embeds with injectable fetch, OpenTelemetry instrumentation, and structured error codes
|
||||
|
||||
Generic Discord API client for webhooks, bot messaging, and embeds. Runtime-agnostic via injectable `fetch` and `clock`. Maps every documented Discord failure mode to a stable `DISCORD.*` error code and emits OpenTelemetry counters and histograms for every request.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [bot-client](./src/core/bot-client/discord-bot-client.md) — Implements the bot-token half of `@suaveplan/discord-client`. Wraps the Discord Bot REST API (`/channels/:id/messages`,…
|
||||
- [discord-bot-client](./src/core/bot-client/discord-bot-client.md) — Implements the bot-token half of `@suaveplan/discord-client`. Wraps the Discord Bot REST API (`/channels/:id/messages`,…
|
||||
- [webhook](./src/core/webhook/discord-webhook.md) — Implements the webhook half of `@suaveplan/discord-client`. Discord webhooks are URLs that anyone with the URL can POST…
|
||||
- [discord-webhook](./src/core/webhook/discord-webhook.md) — Implements the webhook half of `@suaveplan/discord-client`. Discord webhooks are URLs that anyone with the URL can POST…
|
||||
- [errors](./src/errors/discord-client-error.md) — Defines the namespaced, frozen error-code registry and the typed `DiscordClientError` class used by every runtime failu…
|
||||
- [discord-client-error](./src/errors/discord-client-error.md) — Defines the namespaced, frozen error-code registry and the typed `DiscordClientError` class used by every runtime failu…
|
||||
- [http](./src/utils/http.md) — Single funnel through which every Discord API and webhook request flows. It maps Discord response codes onto the `Disco…
|
||||
- [rate-limit](./src/utils/rate-limit.md) — Parses Discord's three rate-limit response headers into a single millisecond back-off duration that callers can use to…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/discord-client
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```ts
|
||||
import { DiscordBotClient, DiscordWebhook } from "@suaveplan/discord-client";
|
||||
|
||||
const bot = new DiscordBotClient({ token: process.env.DISCORD_BOT_TOKEN! });
|
||||
await bot.sendMessage("123", { content: "hello from the bot" });
|
||||
|
||||
const hook = new DiscordWebhook({
|
||||
webhookUrl: "https://discord.com/api/webhooks/123/abc",
|
||||
});
|
||||
await hook.sendText("hello from a webhook");
|
||||
```
|
||||
|
||||
## Modules
|
||||
|
||||
| Module | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| Bot Client | [src/core/bot-client/discord-bot-client.md](src/core/bot-client/discord-bot-client.md) | `DiscordBotClient` — send/edit/delete messages, reactions, channels, guilds |
|
||||
| Webhook | [src/core/webhook/discord-webhook.md](src/core/webhook/discord-webhook.md) | `DiscordWebhook` — webhook-URL delivery with structured reports |
|
||||
| HTTP Helper | [src/utils/http.md](src/utils/http.md) | Shared request funnel: error mapping, timeout, OTel metrics |
|
||||
| Rate-Limit | [src/utils/rate-limit.md](src/utils/rate-limit.md) | `parseRetryAfterMs` parser for Discord's three rate-limit headers |
|
||||
| Errors | [src/errors/discord-client-error.md](src/errors/discord-client-error.md) | `DISCORD_CODES` registry and `DiscordClientError` |
|
||||
| Types | [src/types/discord-client.types.md](src/types/discord-client.types.md) | Public type surface + Zod boundary schemas |
|
||||
|
||||
## Subpath Exports
|
||||
|
||||
```ts
|
||||
import { DiscordBotClient } from "@suaveplan/discord-client/bot";
|
||||
import { DiscordWebhook } from "@suaveplan/discord-client/webhook";
|
||||
import { DISCORD_CODES } from "@suaveplan/discord-client/errors";
|
||||
import { DiscordMessageSchema } from "@suaveplan/discord-client/types";
|
||||
```
|
||||
|
||||
## Error Codes
|
||||
|
||||
| Code | HTTP | Meaning |
|
||||
|------|------|---------|
|
||||
| `DISCORD.API_ERROR` | 502 | Generic non-2xx bot response |
|
||||
| `DISCORD.AUTH_ERROR` | 401 | Token rejected |
|
||||
| `DISCORD.RATE_LIMITED` | 429 | Honour `error.context.retryAfterMs` |
|
||||
| `DISCORD.CHANNEL_NOT_FOUND` | 404 | Channel missing or bot lacks access |
|
||||
| `DISCORD.GUILD_NOT_FOUND` | 404 | Guild missing or bot is not a member |
|
||||
| `DISCORD.CONFIG_MISSING` | 500 | Required config value missing |
|
||||
| `DISCORD.INVALID_CONFIG` | 500 | Config failed Zod validation |
|
||||
| `DISCORD.INVALID_MESSAGE` | 400 | Message payload failed Zod validation |
|
||||
| `DISCORD.WEBHOOK_FAILED` | 502 | Webhook delivery rejected |
|
||||
| `DISCORD.TIMEOUT` | 504 | Request aborted by timeout |
|
||||
| `DISCORD.FORBIDDEN` | 403 | Caller lacks permissions |
|
||||
|
||||
## Injectable Fetch & Clock
|
||||
|
||||
Both `DiscordBotClient` and `DiscordWebhook` accept `fetch` and `clock` injectables — pass deterministic stubs in tests, omit them in production to use `globalThis.fetch` and `Date.now`.
|
||||
|
||||
```ts
|
||||
import { DiscordBotClient, type FetchLike } from "@suaveplan/discord-client";
|
||||
|
||||
const stubFetch: FetchLike = async () => ({
|
||||
ok: true, status: 200, statusText: "OK",
|
||||
headers: { get: () => null },
|
||||
text: async () => "", json: async () => ({ id: "1", channelId: "1", content: "x", timestamp: "" }),
|
||||
});
|
||||
|
||||
new DiscordBotClient({
|
||||
token: "abc",
|
||||
fetch: stubFetch,
|
||||
clock: () => 1_700_000_000_000,
|
||||
});
|
||||
```
|
||||
|
||||
## OTel Metrics
|
||||
|
||||
| Metric | Type | Labels |
|
||||
|--------|------|--------|
|
||||
| `discord_client.request.total` | Counter | `kind`, `method`, `outcome`, `status` |
|
||||
| `discord_client.request.duration_ms` | Histogram | `kind`, `method`, `outcome` |
|
||||
|
||||
Reference in New Issue
Block a user