vimcord 1.0.35 → 1.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,39 @@
1
- # vimcord
1
+ <div align="center">
2
2
 
3
- **Vimcord** (pronounced as in _vhem-cord_) is a lightweight, opinionated framework for **Discord.js**. Built for developers who want to reduce the distance between an idea and a working command without fighting with the library.
3
+ ```
4
+ ██╗ ██╗██╗███╗ ███╗ ██████╗ ██████╗ ██████╗ ██████╗
5
+ ██║ ██║██║████╗ ████║██╔════╝██╔═══██╗██╔══██╗██╔══██╗
6
+ ██║ ██║██║██╔████╔██║██║ ██║ ██║██████╔╝██║ ██║
7
+ ╚██╗ ██╔╝██║██║╚██╔╝██║██║ ██║ ██║██╔══██╗██║ ██║
8
+ ╚████╔╝ ██║██║ ╚═╝ ██║╚██████╗╚██████╔╝██║ ██║██████╔╝
9
+ ╚═══╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝
10
+ ```
11
+
12
+ **vhem-cord** — the Discord.js framework that actually respects your time
13
+
14
+ [![npm version](https://img.shields.io/npm/v/vimcord?color=%235865F2&label=vimcord&logo=npm&style=flat-square)](https://www.npmjs.com/package/vimcord)
15
+ [![npm downloads](https://img.shields.io/npm/dm/vimcord?color=%2357F287&label=downloads&style=flat-square)](https://www.npmjs.com/package/vimcord)
16
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0%2B-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/)
17
+ [![License](https://img.shields.io/npm/l/vimcord?color=%23FEE75C&label=license&style=flat-square)](LICENSE)
18
+ [![Discord.js](https://img.shields.io/badge/discord.js-14.x-%235865F2?style=flat-square&logo=discord)](https://discord.js.org/)
19
+
20
+ [Installation](#installation) · [Quick Start](#quick-start) · [Features](#features) · [API](#api-reference) · [Examples](#examples)
21
+
22
+ </div>
23
+
24
+ ---
25
+
26
+ ## What's Vimcord?
27
+
28
+ **Vimcord** (pronounced _vhem-cord_) is a lightweight, opinionated framework for **Discord.js**. Built for developers who want to go from an idea to a working command without fighting boilerplate.
4
29
 
5
- ## 🚀 Installation
30
+ Think of it as Discord.js with the sharp edges sanded off — full TypeScript inference, automatic error boundaries, and utilities that actually make sense.
31
+
32
+ > "I just wanted to build a bot, not write a command handler for the 47th time." — _You, probably_
33
+
34
+ ---
35
+
36
+ ## Installation
6
37
 
7
38
  ```bash
8
39
  npm install vimcord discord.js
@@ -12,83 +43,400 @@ pnpm add vimcord discord.js
12
43
  yarn add vimcord discord.js
13
44
  ```
14
45
 
15
- ## 🛠 Quick Start
46
+ **Peer dependencies** (optional but recommended):
47
+
48
+ ```bash
49
+ npm install mongoose # Only if using MongoDB
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Quick Start
16
55
 
17
- Vimcord uses a `createClient` factory to initialize a pre-configured environment with optional feature flags.
56
+ ### The Absolute Minimum
18
57
 
19
58
  ```ts
20
- import { ActivityType, ClientOptions, GatewayIntentBits } from "discord.js";
21
- import { createClient, GatewayIntentBits, MongoDatabase, StatusType } from "vimcord";
59
+ import { createClient, GatewayIntentBits } from "vimcord";
60
+
61
+ const client = createClient({ intents: [GatewayIntentBits.Guilds] }, { useDefaultSlashCommandHandler: true });
62
+
63
+ client.start();
64
+ ```
65
+
66
+ ### The "I Actually Want Features" Setup
67
+
68
+ ```ts
69
+ import { GatewayIntentBits } from "discord.js";
70
+ import { createClient, MongoDatabase } from "vimcord";
22
71
 
23
72
  const client = createClient(
24
73
  {
25
- intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]
74
+ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent]
26
75
  },
27
76
  {
28
- useGlobalErrorHandlers: true,
77
+ // Auto-load modules from directories
78
+ importModules: {
79
+ events: "./events",
80
+ slashCommands: "./commands/slash",
81
+ prefixCommands: "./commands/prefix",
82
+ contextCommands: "./commands/context"
83
+ },
84
+
85
+ // Built-in handlers for each command type
29
86
  useDefaultSlashCommandHandler: true,
30
87
  useDefaultPrefixCommandHandler: true,
31
88
  useDefaultContextCommandHandler: true,
32
89
 
33
- // Automatically import the .env using dotEnv
34
- useEnv: true,
90
+ // Catch and log unhandled errors
91
+ useGlobalErrorHandlers: true
92
+ }
93
+ );
35
94
 
36
- // Automatically import event and command modules
37
- importModules: {
38
- events: "./events",
39
- slashCommands: "./commands/slash",
40
- prefixCommands: "./commands/prefix"
41
- contextCommands: "./commands/context"
95
+ client.start(async () => {
96
+ // Connect to MongoDB before login
97
+ await client.useDatabase(new MongoDatabase(client));
98
+ });
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Features
104
+
105
+ ### Command Management That Doesn't Suck
106
+
107
+ **Slash commands** with subcommand routing:
108
+
109
+ ```ts
110
+ import { SlashCommandBuilder } from "vimcord";
111
+
112
+ export default new SlashCommandBuilder({
113
+ builder: new SlashCommandBuilder()
114
+ .setName("manage")
115
+ .setDescription("Server management")
116
+ .addSubcommand(sub => sub.setName("ban").setDescription("Ban a user")),
117
+
118
+ // Route subcommands automatically
119
+ routes: [
120
+ {
121
+ name: "ban",
122
+ handler: async (client, interaction) => {
123
+ // Handle /manage ban
124
+ }
42
125
  }
126
+ ],
127
+
128
+ // Permission inference — Vimcord validates before executing
129
+ permissions: {
130
+ user: [PermissionFlagsBits.BanMembers],
131
+ bot: [PermissionFlagsBits.BanMembers]
43
132
  }
44
- );
133
+ });
134
+ ```
45
135
 
46
- client.start(async client => {
47
- // NOTE: This runs *BEFORE* the client logs in
136
+ **Prefix commands** with the same DX:
48
137
 
49
- // Use Mongo as our database
50
- await client.useDatabase(new MongoDatabase(client));
51
- })
138
+ ```ts
139
+ import { PrefixCommandBuilder } from "vimcord";
140
+
141
+ export default new PrefixCommandBuilder({
142
+ name: "ping",
143
+ aliases: ["p"],
144
+ execute: async (client, message, args) => {
145
+ await message.reply("Pong!");
146
+ }
147
+ });
148
+ ```
149
+
150
+ ### BetterEmbed: Stop Writing Boilerplate
151
+
152
+ ```ts
153
+ import { BetterEmbed } from "vimcord";
154
+
155
+ const embed = new BetterEmbed({
156
+ context: { interaction }, // Auto-context for tokens
157
+ title: "Welcome, $USER!",
158
+ description: ["Your avatar: $USER_AVATAR", "Today is $MONTH/$DAY/$YEAR"],
159
+ color: "#5865F2"
160
+ });
161
+
162
+ // ACF (Auto Context Formatting) tokens available:
163
+ // $USER, $USER_NAME, $DISPLAY_NAME, $USER_AVATAR
164
+ // $BOT_AVATAR, $YEAR, $MONTH, $DAY, $INVIS
165
+
166
+ await embed.send(interaction);
52
167
  ```
53
168
 
54
- ## 🛠 Features
169
+ ### The Paginator: Multi-Page Made Simple
55
170
 
56
- - **CommandManager**: Advanced managers for **Slash**, **Prefix**, and **Context** commands. Includes deep inference for permissions and automated error boundaries.
57
- - **DatabaseManager**: Seamless **MongoDB/Mongoose** integration via `createMongoSchema` and `useMongoDatabase`.
58
- - **DiscordTools**: High-level interaction helpers including the **Paginator**, **Prompt**, and **BetterModal** for stateful UI.
59
- - **DiscordUtils**: Essential Discord-first utilities like `dynaSend`, `fetchMember`, and `isMentionOrSnowflake`.
60
- - **Logger**: A fun, retro style console logger for clear, actionable terminal output.
171
+ ```ts
172
+ import { Paginator, PaginationType } from "vimcord";
173
+
174
+ const paginator = new Paginator({
175
+ type: PaginationType.LongJump, // first | back | jump | next | last
176
+ timeout: 60000
177
+ });
178
+
179
+ // Add chapters (groups of pages)
180
+ paginator
181
+ .addChapter([helpPage1, helpPage2, helpPage3], { label: "General Help", emoji: "📖" })
182
+ .addChapter([modPage1, modPage2], { label: "Moderation", emoji: "🛡️" });
183
+
184
+ // Send it anywhere
185
+ const message = await paginator.send(interaction);
61
186
 
62
- ## 💎 Useful Utilities
187
+ // Events for custom logic
188
+ paginator.on("pageChange", (page, index) => {
189
+ console.log(`User viewing page ${index.nested} of chapter ${index.chapter}`);
190
+ });
191
+ ```
192
+
193
+ ### Prompt: Confirmation Dialogs
63
194
 
64
- ### **The BetterEmbed & ACF**
195
+ ```ts
196
+ import { Prompt } from "vimcord";
65
197
 
66
- Stop writing boilerplate for user mentions and avatars. `BetterEmbed` supports **Shorthand Context Formatting (ACF)**, allowing you to use tokens like `$USER` and `$BOT_AVATAR` directly in strings. Vimcord resolves them at runtime.
198
+ const prompt = new Prompt({
199
+ embed: new BetterEmbed({
200
+ title: "Delete this message?",
201
+ description: "This action cannot be undone.",
202
+ context: { interaction }
203
+ }),
204
+ timeout: 30000
205
+ });
67
206
 
68
- ### **The Paginator (Chapters & Nested Pages)**
207
+ await prompt.send(interaction);
208
+ const result = await prompt.awaitResponse();
69
209
 
70
- Multi-page embeds shouldn't be a chore. The `Paginator` supports **Chapters**, enabling complex, nested page structures with built-in navigation logic and select menu support.
210
+ if (result.confirmed) {
211
+ await message.delete();
212
+ }
213
+ ```
71
214
 
72
- ### **The DynaSend: Smart Dispatch**
215
+ ### BetterModal: V2 Components Done Right
216
+
217
+ ```ts
218
+ import { BetterModal } from "vimcord";
219
+
220
+ const modal = new BetterModal({
221
+ title: "Create Ticket",
222
+ components: [
223
+ {
224
+ textInput: {
225
+ label: "Subject",
226
+ custom_id: "subject",
227
+ style: TextInputStyle.Short,
228
+ required: true
229
+ }
230
+ },
231
+ {
232
+ textInput: {
233
+ label: "Description",
234
+ custom_id: "description",
235
+ style: TextInputStyle.Paragraph
236
+ }
237
+ }
238
+ ]
239
+ });
240
+
241
+ // Show and await in one call
242
+ const result = await modal.showAndAwait(interaction);
243
+
244
+ if (result) {
245
+ const subject = result.getField("subject");
246
+ await result.reply({
247
+ content: `Ticket created: ${subject}`,
248
+ flags: "Ephemeral"
249
+ });
250
+ }
251
+ ```
252
+
253
+ ### DynaSend: One Method, Every Context
254
+
255
+ ```ts
256
+ import { dynaSend } from "vimcord";
257
+
258
+ // Works with: interactions, channels, messages, users
259
+ // Automatically decides: reply? editReply? followUp? channel.send?
260
+ await dynaSend(interaction, {
261
+ content: "Hello!",
262
+ embeds: [myEmbed],
263
+ components: [actionRow]
264
+ });
265
+ ```
266
+
267
+ ### Database: MongoDB Without the Pain
268
+
269
+ ```ts
270
+ import { createMongoSchema, MongoDatabase } from "vimcord";
271
+
272
+ // Define a schema with retry logic built-in
273
+ const UserSchema = createMongoSchema("Users", {
274
+ userId: { type: String, required: true, unique: true },
275
+ username: String,
276
+ balance: { type: Number, default: 0 },
277
+ createdAt: { type: Date, default: Date.now }
278
+ });
279
+
280
+ // CRUD operations with automatic retries
281
+ const user = await UserSchema.fetch({ userId: "123" });
282
+ await UserSchema.upsert({ userId: "123" }, { $inc: { balance: 100 } });
283
+
284
+ // Create plugins for reusable logic
285
+ const SoftDeletePlugin = createMongoPlugin(builder => {
286
+ builder.schema.add({ deletedAt: { type: Date, default: null } });
287
+ builder.extend({
288
+ async softDelete(filter) {
289
+ return this.update(filter, { deletedAt: new Date() });
290
+ }
291
+ });
292
+ });
293
+
294
+ UserSchema.use(SoftDeletePlugin);
295
+ ```
296
+
297
+ ### Logger: Terminal Output That Doesn't Suck
298
+
299
+ ```ts
300
+ import { Logger } from "vimcord";
301
+
302
+ const logger = new Logger({
303
+ prefix: "Economy",
304
+ prefixEmoji: "💰",
305
+ colors: { primary: "#57F287" }
306
+ });
307
+
308
+ logger.success("User purchased item");
309
+ logger.table("Stats", { users: 150, revenue: "$420.69" });
310
+
311
+ // Loader for async operations
312
+ const stopLoader = logger.loader("Connecting to database...");
313
+ await connectToDB();
314
+ stopLoader("Connected!");
315
+ ```
316
+
317
+ ---
318
+
319
+ ## API Reference
320
+
321
+ ### Client Creation
322
+
323
+ | Export | Description |
324
+ | --------------------------------------------- | ----------------------------- |
325
+ | `createClient(options, features?, config?)` | Create a new Vimcord instance |
326
+ | `Vimcord.create(options, features?, config?)` | Same as above |
327
+ | `Vimcord.getInstance(id?)` | Get existing instance by ID |
328
+ | `Vimcord.getReadyInstance(id?, timeout?)` | Wait for ready instance |
329
+
330
+ ### Feature Flags
331
+
332
+ ```ts
333
+ {
334
+ useDefaultSlashCommandHandler: boolean; // Auto-handle slash commands
335
+ useDefaultPrefixCommandHandler: boolean; // Auto-handle prefix commands
336
+ useDefaultContextCommandHandler: boolean; // Auto-handle context commands
337
+ useGlobalErrorHandlers: boolean; // Catch unhandled errors
338
+ importModules: {
339
+ events?: string | string[] | ModuleImportOptions;
340
+ slashCommands?: string | string[] | ModuleImportOptions;
341
+ prefixCommands?: string | string[] | ModuleImportOptions;
342
+ contextCommands?: string | string[] | ModuleImportOptions;
343
+ };
344
+ maxLoginAttempts?: number; // Retry login on failure (default: 3)
345
+ }
346
+ ```
347
+
348
+ ### Configuration
349
+
350
+ ```ts
351
+ client.configure("app", {
352
+ name: "MyBot", // Display name
353
+ version: "1.0.0", // Version string
354
+ devMode: false, // Use TOKEN_DEV env var
355
+ verbose: false // Extra logging
356
+ });
357
+
358
+ client.configure("staff", {
359
+ ownerId: "123456", // Bot owner
360
+ staffRoleIds: ["..."] // Staff roles
361
+ });
362
+ ```
363
+
364
+ ---
365
+
366
+ ## Examples
367
+
368
+ ### Status Rotation
369
+
370
+ ```ts
371
+ client.status.setRotation(
372
+ [
373
+ { name: "with commands", type: ActivityType.Playing },
374
+ { name: "over {guilds} servers", type: ActivityType.Watching }
375
+ ],
376
+ { interval: 30000 }
377
+ ); // Rotate every 30s
378
+ ```
379
+
380
+ ### Event Handler
381
+
382
+ ```ts
383
+ import { EventBuilder } from "vimcord";
384
+
385
+ export default new EventBuilder({
386
+ event: Events.MessageCreate,
387
+ execute: async (client, message) => {
388
+ if (message.author.bot) return;
389
+ // Handle message
390
+ }
391
+ });
392
+ ```
393
+
394
+ ### Error Handling
395
+
396
+ ```ts
397
+ // Vimcord automatically catches command errors and sends user-friendly messages
398
+ // Configure what happens on error:
399
+
400
+ client.configure("slashCommands", {
401
+ errorMessage: "❌ Something went wrong! Our team has been notified.",
402
+ logErrors: true
403
+ });
404
+
405
+ // Or handle specific errors:
406
+ process.on("unhandledRejection", error => {
407
+ client.logger.error("Unhandled rejection", error as Error);
408
+ });
409
+ ```
410
+
411
+ ---
412
+
413
+ ## Environment Variables
414
+
415
+ ```bash
416
+ # Required
417
+ TOKEN=your_production_bot_token
418
+ TOKEN_DEV=your_development_bot_token # Used when devMode: true
419
+
420
+ # MongoDB (optional)
421
+ MONGO_URI=mongodb://localhost:27017/discord-bot
422
+ ```
73
423
 
74
- `DynaSend` is an intelligent message delivery system. It automatically detects the interaction state to decide whether to `.reply()`, `.editReply()`, or `.followUp()`. You write one line and Vimcord handles the logic.
424
+ ---
75
425
 
76
- ### **MongoSchemaBuilder: Resilient DB Ops**
426
+ ## About
77
427
 
78
- The `execute` method on your schemas includes built-in **exponential backoff**. If the database is under load or reconnecting, Vimcord retries the operation instead of crashing your command.
428
+ Created by [**xsqu1znt**](https://github.com/xsqu1znt) with a simple goal: make Discord bot development enjoyable again.
79
429
 
80
- ## 👀 Mentionables
430
+ Built on top of [qznt](https://github.com/xsqu1znt/qznt) for that extra bit of utility magic.
81
431
 
82
- - **Strictly Typed**: Full TypeScript support with deep inference for command permissions, events, and database documents.
83
- - **Feature-Rich**: Includes a built-in CLI, automated status rotation, and sophisticated error boundaries.
84
- - **Developer-Centric**: Focused on performance and ergonomics.
432
+ **License:** MIT
85
433
 
86
- ## 👋 About
434
+ ---
87
435
 
88
- _Vimcord was created by **xsqu1znt**,_ and designed for developers who value performance and aesthetic code.
436
+ <div align="center">
89
437
 
90
- It also takes advantage of my lightweight library [qznt](https://github.com/xsqu1znt/qznt) for a smooth experience.
438
+ Built with 💜 for the Discord.js community
91
439
 
92
- ## **_Vimcord is still a work in progress. If you find any bugs, please let me know._**
440
+ Found a bug? [Open an issue](https://github.com/xsqu1znt/vimcord/issues)
93
441
 
94
- License: MIT
442
+ </div>