The @packages/discord-api package provides type-safe Discord API wrappers built with Effect and automatically generated from Discord’s OpenAPI specification.
Installation
npm install @packages/discord-api
Overview
This package provides:
- Auto-generated types from Discord OpenAPI spec
- Effect-based API for type-safe requests
- Schema validation using Effect Schema
- Type-safe Discord models (users, guilds, channels, etc.)
Auto-Generated Types
All types are generated from Discord’s OpenAPI specification:
import * as Discord from "@packages/discord-api/generated";
// Discord models with full type safety
type User = Discord.UserResponse;
type Guild = Discord.GuildResponse;
type Channel = Discord.ChannelResponse;
type Message = Discord.MessageResponse;
Core Types
Snowflake Type
import { SnowflakeType } from "@packages/discord-api/generated";
// Discord snowflake IDs
const userId: SnowflakeType = "123456789012345678";
const guildId: SnowflakeType = "987654321098765432";
Discord snowflake ID (string matching pattern ^(0|[1-9][0-9]*)$)
UserResponse
import { UserResponse } from "@packages/discord-api/generated";
const user: UserResponse = {
id: "123456789012345678",
username: "example_user",
discriminator: "0",
avatar: "a_abc123...",
global_name: "Example User",
public_flags: 0,
flags: 0,
};
User’s 4-digit discriminator (deprecated, now “0”)
Whether the user is a bot
Whether the user is an official Discord system user
Public flags on user’s account
OAuth2 Scopes
import { OAuth2Scopes } from "@packages/discord-api/generated";
const scopes: OAuth2Scopes[] = [
"identify",
"email",
"guilds",
"guilds.members.read",
"bot",
"applications.commands",
];
Available scopes:
identify - /users/@me without email
email - /users/@me with email
guilds - /users/@me/guilds
guilds.members.read - Read guild member data
bot - Add bot to guilds
applications.commands - Use application commands
- Many more (see Discord documentation)
ApplicationOAuth2InstallParamsResponse
import { ApplicationOAuth2InstallParamsResponse } from "@packages/discord-api/generated";
const installParams: ApplicationOAuth2InstallParamsResponse = {
scopes: ["applications.commands", "bot"],
permissions: "8", // Administrator
};
Array of OAuth2 scopes (“applications.commands” | “bot”)
Permission bitfield as string
Effect Schema Integration
All types are Effect Schema classes:
import { Schema as S } from "effect";
import { UserResponse } from "@packages/discord-api/generated";
import { Effect } from "effect";
// Parse and validate Discord user data
const parseUser = (data: unknown) =>
Effect.gen(function* () {
const user = yield* S.decodeUnknown(UserResponse)(data);
return user;
});
// Use in your application
const result = await Effect.runPromise(
parseUser({
id: "123456789",
username: "test",
discriminator: "0",
public_flags: 0,
flags: 0,
})
);
Common Patterns
Type-Safe API Calls
import { UserResponse, SnowflakeType } from "@packages/discord-api/generated";
import { Effect, Schema as S } from "effect";
const getDiscordUser = (userId: SnowflakeType) =>
Effect.gen(function* () {
const response = yield* Effect.tryPromise(() =>
fetch(`https://discord.com/api/v10/users/${userId}`, {
headers: {
Authorization: `Bot ${process.env.DISCORD_BOT_TOKEN}`,
},
})
);
const data = yield* Effect.tryPromise(() => response.json());
const user = yield* S.decodeUnknown(UserResponse)(data);
return user;
});
Validate Webhook Payloads
import { MessageResponse } from "@packages/discord-api/generated";
const validateMessage = (payload: unknown) =>
S.decodeUnknownSync(MessageResponse)(payload);
// In webhook handler
app.post("/webhook", (req, res) => {
try {
const message = validateMessage(req.body);
// Process validated message
} catch (error) {
res.status(400).send("Invalid payload");
}
});
Generating Types
The package includes scripts to regenerate types from Discord’s OpenAPI spec:
# Sync latest OpenAPI spec from Discord
bun run sync
# Generate TypeScript types
bun run gen
# Do both
bun run update
Generated Files
Auto-generated TypeScript types and Effect Schema classes
Discord OpenAPI specification
Exports
All auto-generated Discord API types and schemas
Example: Bot Integration
import { UserResponse, OAuth2Scopes } from "@packages/discord-api/generated";
import { Effect, Schema as S } from "effect";
class DiscordBot {
constructor(private token: string) {}
getCurrentUser() {
return Effect.gen(function* () {
const response = yield* Effect.tryPromise(() =>
fetch("https://discord.com/api/v10/users/@me", {
headers: { Authorization: `Bot ${this.token}` },
})
);
const data = yield* Effect.tryPromise(() => response.json());
const user = yield* S.decodeUnknown(UserResponse)(data);
return user;
});
}
}
const bot = new DiscordBot(process.env.DISCORD_BOT_TOKEN!);
const user = await Effect.runPromise(bot.getCurrentUser());
console.log(user.username);
Benefits
- Type Safety: Catch Discord API errors at compile time
- Auto-Updated: Regenerate types when Discord updates their API
- Effect Integration: Works seamlessly with Effect for error handling
- Schema Validation: Validate API responses at runtime
- IntelliSense: Full autocomplete for Discord API types
Dependencies
@effect/platform - Effect HTTP client
effect - Effect library for functional programming
@tim-smart/openapi-gen - OpenAPI type generation