djs-next 1.0.0-dev.2 → 1.0.0-dev.3

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.

Potentially problematic release.


This version of djs-next might be problematic. Click here for more details.

package/README.md CHANGED
@@ -13,17 +13,18 @@
13
13
  ## ✨ Features
14
14
 
15
15
  - 📁 **Next.js File-Based Routing**: Auto-loads commands, events, components, and tasks natively. Supports Regex dynamic routes (e.g., `[id].ts` for components).
16
- - 🛠️ **Native Developer Tools (`dnxt`)**: A comprehensive, built-in developer suite. Live JS evaluation, module reloading, remote shell execution, and advanced block pagination!
16
+ - 🛠️ **Native Developer Tools (`dnxt`)**: A comprehensive, built-in developer suite. Live JS evaluation, remote shell execution, and instant Hot-Module Reloading!
17
17
  - 🔄 **Hot Module Replacement (HMR)**: Live-reload your commands, events, and logic on save without ever dropping your Discord Gateway connection.
18
- - 🗄️ **Strict Database Interop**: The entire framework `<DB>` generic safely propagates your ORM (Prisma, Mongoose, Supabase) universally without global ambient overrides.
18
+ - 🗄️ **Strict Database Interop**: Connect your ORM (Prisma, Mongoose) securely.
19
19
  - 🌍 **Localization (i18n)**: Out-of-the-box native string translations.
20
20
  - 🛡️ **Middleware Routing**: Global `beforeExecute` hooks for overarching permission checks and analytics.
21
- - 🚦 **Built-in Safety**: The interaction core automatically resolves `cooldowns`, `userPermissions`, `developerOnly`, and `guildOnly` rules before execution.
21
+ - 🚦 **Persistent Cooldowns**: Connect custom cache adapters (like Redis) for global persistent cooldown tracking.
22
+ - 📄 **PaginationBuilder**: A built-in class for creating robust interactive pagination menus.
22
23
 
23
24
  ## 📦 Installation
24
25
 
25
26
  ```bash
26
- npm install djs-next discord.js dotenv
27
+ npm install djs-next
27
28
  ```
28
29
  *(Or use `pnpm`, `yarn`, or `bun`)*
29
30
 
@@ -44,9 +45,7 @@ If you prefer to start manually, here's how to bootstrap `djs-next`:
44
45
 
45
46
  ### 1. The Entry Point (`index.js`)
46
47
  ```javascript
47
- require('dotenv').config();
48
- const { GatewayIntentBits } = require('discord.js');
49
- const { DJSNextClient } = require('djs-next');
48
+ const { GatewayIntentBits, DJSNextClient } = require('djs-next');
50
49
  const { PrismaClient } = require('@prisma/client'); // Optional Database
51
50
 
52
51
  const db = new PrismaClient();
@@ -54,12 +53,18 @@ const db = new PrismaClient();
54
53
  const client = new DJSNextClient({
55
54
  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent],
56
55
  developers: ['YOUR_DISCORD_ID'], // Required for Developer Tools
57
- prefixes: ['!', '?'], // Standard prefixes. Pass [''] for no-prefix commands!
58
- enableMentionPrefix: true // Allows "@Bot ping" to work natively
56
+
57
+ // Explicit Framework Toggles
58
+ enableSlashCommands: true,
59
+ enableTextCommands: true,
60
+ enableMentionPrefix: true,
61
+ enableNoPrefix: false,
62
+ prefixes: ['!', '?'], // Standard prefixes
63
+
64
+ // Connect your database (Mongoose, Prisma, etc.)
65
+ db: db,
59
66
  });
60
67
 
61
- // Attach your database for global framework availability
62
- client.db = db;
63
68
 
64
69
  // Enable Hot-Module Reloading (HMR) for dev
65
70
  client.enableHMR();
@@ -104,6 +109,25 @@ module.exports = {
104
109
  await interaction.reply(`Banning user ${targetId}...`);
105
110
  }
106
111
  };
112
+ ```
113
+
114
+ }
115
+ };
116
+ ```
117
+
118
+ ### 4. Interactive Pagination
119
+ You no longer need to write complex collectors for simple pagination menus. `djs-next` ships with a `PaginationBuilder`:
120
+ ```javascript
121
+ const { PaginationBuilder } = require('djs-next');
122
+ const { EmbedBuilder } = require('discord.js');
123
+
124
+ // Inside a command execute function:
125
+ const paginator = new PaginationBuilder()
126
+ .addPage(new EmbedBuilder().setDescription('Page 1'))
127
+ .addPage(new EmbedBuilder().setDescription('Page 2'))
128
+ .setTimeout(60000);
129
+
130
+ await paginator.build(interaction);
107
131
  ```
108
132
 
109
133
  ---
@@ -116,20 +140,18 @@ Because `djs-next` uses a global `<DB>` generic, you can natively bind any popul
116
140
 
117
141
  ```javascript
118
142
  // index.js
119
- require('dotenv').config();
120
143
  const mongoose = require('mongoose');
121
- const { DJSNextClient } = require('djs-next');
122
- const { GatewayIntentBits } = require('discord.js');
144
+ const { DJSNextClient, GatewayIntentBits } = require('djs-next');
123
145
 
124
146
  // Connect to Atlas
125
147
  mongoose.connect(process.env.MONGO_URI);
126
148
 
127
149
  // Initialize DJSNext
128
150
  const client = new DJSNextClient({
129
- intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages ]
151
+ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages ],
152
+ db: mongoose
130
153
  });
131
154
 
132
- client.db = mongoose;
133
155
  client.start(process.env.TOKEN);
134
156
  ```
135
157
 
@@ -152,18 +174,16 @@ module.exports = {
152
174
 
153
175
  ```javascript
154
176
  // index.js
155
- require('dotenv').config();
156
177
  const { createClient } = require('@supabase/supabase-js');
157
- const { DJSNextClient } = require('djs-next');
158
- const { GatewayIntentBits } = require('discord.js');
178
+ const { DJSNextClient, GatewayIntentBits } = require('djs-next');
159
179
 
160
180
  const supabase = createClient('https://xyz.supabase.co', process.env.SUPABASE_KEY);
161
181
 
162
182
  const client = new DJSNextClient({
163
- intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages ]
183
+ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages ],
184
+ db: supabase
164
185
  });
165
186
 
166
- client.db = supabase;
167
187
  client.start(process.env.TOKEN);
168
188
  ```
169
189
 
@@ -190,18 +210,15 @@ module.exports = {
190
210
 
191
211
  | Command | Action |
192
212
  | --- | --- |
193
- | `dnxt js <code>` | Evaluates Javascript live with pagination, async resolution, and timer tracing. |
194
- | `dnxt sh <cmd>` | Executes raw shell/terminal code on your host machine (e.g., `dnxt sh npm run build`). |
213
+ | `dnxt js <code>` | Evaluates Javascript live with async resolution. |
214
+ | `dnxt sh <cmd>` | Executes raw shell/terminal code on your host machine. |
195
215
  | `dnxt git <cmd>` | Executes standard git workflows (e.g., `dnxt git pull`). |
196
- | `dnxt su <id> <cmd>`| Triggers a mock message command mimicking another user's execution perspective. |
216
+ | `dnxt in <channelId> <text>`| Injects a message seamlessly into a specific channel as the bot. |
197
217
  | `dnxt reload <target>` | Hot-swaps the internal cache. (e.g., `dnxt reload commands`, `dnxt reload all`). |
198
- | `dnxt source <cmd>` | Directly `fs.readFileSync`s the underlying source code of an active command! |
199
218
  | `dnxt debug <cmd>` | Executes Javascript while explicitly tracking the Node.js V8 Heap Memory Delta. |
200
- | `dnxt tasks` | Views all running background `setInterval` tasks in the framework. |
201
- | `dnxt cancel <task>` | Forcefully kills a background interval process. |
202
219
  | `dnxt sync` | Manually forces a global Discord Slash Command synchronization. |
203
- | `dnxt sql <query>` | Attempts to execute a raw SQL query against your `client.db` connection. |
204
- | `dnxt vc` | Dumps VoiceChannel state and Voice Debugger information. |
220
+ | `dnxt restart` | Safely spawns a new background process and shuts down the current one. |
221
+ | `dnxt stop` or `dnxt shutdown` | Fully disconnects the client and kills the Node process. |
205
222
  | `dnxt` | Displays the Developer Dashboard tracking System RAM, Node Host status, and Process uptime. |
206
223
 
207
224
  ---
@@ -220,6 +237,11 @@ module.exports = {
220
237
  components: 'src/components',
221
238
  tasks: 'src/tasks',
222
239
  locales: 'src/locales'
240
+ },
241
+ // Optional Redis or persistent cache adapter for cooldowns
242
+ cooldownAdapter: {
243
+ get: async (cmdId, userId) => { /* return timestamp or null */ },
244
+ set: async (cmdId, userId, expiration) => { /* save to db */ }
223
245
  }
224
246
  };
225
247
  ```
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const projectDir = process.cwd();
7
+
8
+ console.log('🚀 Welcome to create-djs-next! Scaffolding your project...\n');
9
+
10
+ const dirsToCreate = [
11
+ 'src/commands',
12
+ 'src/events',
13
+ 'src/components',
14
+ 'src/tasks',
15
+ 'src/locales'
16
+ ];
17
+
18
+ for (const dir of dirsToCreate) {
19
+ const dirPath = path.join(projectDir, dir);
20
+ if (!fs.existsSync(dirPath)) {
21
+ fs.mkdirSync(dirPath, { recursive: true });
22
+ console.log(`✅ Created directory: ${dir}`);
23
+ }
24
+ }
25
+
26
+ const envContent = `DISCORD_TOKEN=your_token_here\nCLIENT_ID=your_client_id\nGUILD_ID=your_dev_guild_id`;
27
+ const envPath = path.join(projectDir, '.env');
28
+ if (!fs.existsSync(envPath)) {
29
+ fs.writeFileSync(envPath, envContent);
30
+ console.log('✅ Created .env file');
31
+ }
32
+
33
+ const indexContent = `const { GatewayIntentBits, DJSNextClient } = require('djs-next');
34
+
35
+ const client = new DJSNextClient({
36
+ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent],
37
+ developers: ['YOUR_DISCORD_USER_ID'],
38
+ clientId: process.env.CLIENT_ID,
39
+
40
+ // Framework Toggles
41
+ enableSlashCommands: true,
42
+ enableTextCommands: true,
43
+ enableMentionPrefix: true,
44
+ enableNoPrefix: false,
45
+ prefixes: ['!', '?'],
46
+
47
+ // Custom Middleware
48
+ middleware: (interactionOrMessage, client) => {
49
+ return true; // Return false to block execution
50
+ },
51
+
52
+ // Configuration
53
+ config: {
54
+ devGuildId: process.env.GUILD_ID,
55
+ locales: ['en'],
56
+ defaultLocale: 'en',
57
+ responses: {
58
+ developerOnly: '⛔ This command is restricted to bot developers.',
59
+ guildOnly: '⛔ This command can only be used inside a server.',
60
+ cooldown: '⏳ You are on cooldown! Please wait {time}.',
61
+ missingPerms: '⛔ You lack permissions.',
62
+ errorBoundary: '❌ An unexpected error occurred.',
63
+ }
64
+ }
65
+ });
66
+
67
+ client.enableHMR();
68
+ client.enableDevTools('dnxt'); // Enable 'dnxt' prefix dev commands
69
+ client.start(process.env.DISCORD_TOKEN);
70
+ \`;
71
+
72
+ const indexPath = path.join(projectDir, 'index.js');
73
+ if (!fs.existsSync(indexPath)) {
74
+ fs.writeFileSync(indexPath, indexContent);
75
+ console.log('✅ Created index.js');
76
+ }
77
+
78
+ console.log('\n🎉 Scaffolding complete! Run \`npm install djs-next\` and start coding!');
package/dist/index.d.mts CHANGED
@@ -1,9 +1,20 @@
1
- import * as discord_js from 'discord.js';
2
1
  import { ApplicationCommandOptionData, PermissionResolvable, ChatInputCommandInteraction, Client, Message, AutocompleteInteraction, MessageComponentInteraction, ModalSubmitInteraction, ClientOptions, Interaction, ClientEvents, Collection, CommandInteraction, EmbedBuilder } from 'discord.js';
3
2
  export * from 'discord.js';
4
3
 
4
+ interface CooldownAdapter {
5
+ get(commandId: string, userId: string): Promise<number | null> | number | null;
6
+ set(commandId: string, userId: string, expirationTime: number): Promise<void> | void;
7
+ }
5
8
  interface DJSNextConfig {
6
9
  devGuildId?: string;
10
+ errorLogChannelId?: string;
11
+ responses?: {
12
+ developerOnly?: string | null;
13
+ guildOnly?: string | null;
14
+ cooldown?: string | null;
15
+ missingPerms?: string | null;
16
+ errorBoundary?: string | null;
17
+ };
7
18
  locales?: string[];
8
19
  defaultLocale?: string;
9
20
  directories?: {
@@ -13,6 +24,7 @@ interface DJSNextConfig {
13
24
  tasks?: string;
14
25
  locales?: string;
15
26
  };
27
+ cooldownAdapter?: CooldownAdapter;
16
28
  }
17
29
  interface DJSNextClientOptions extends ClientOptions {
18
30
  commandsDir?: string;
@@ -23,9 +35,13 @@ interface DJSNextClientOptions extends ClientOptions {
23
35
  guildId?: string;
24
36
  developers?: string[];
25
37
  prefixes?: string[] | string;
26
- enableMentionPrefix?: boolean;
38
+ enableSlashCommands?: boolean;
39
+ enableTextCommands?: boolean;
40
+ enableMentionPrefix?: boolean | string[];
41
+ enableNoPrefix?: boolean | string[];
27
42
  middleware?: (interaction: Interaction | Message, client: Client) => Promise<boolean> | boolean;
28
43
  config?: DJSNextConfig;
44
+ db?: any;
29
45
  }
30
46
  interface FileTask<DB = any> {
31
47
  filepath?: string;
@@ -46,6 +62,7 @@ interface FileCommand<DB = any> {
46
62
  developerOnly?: boolean;
47
63
  guildOnly?: boolean;
48
64
  aliases?: string[];
65
+ preconditions?: string[];
49
66
  execute?: (interaction: ChatInputCommandInteraction, client: Client & {
50
67
  db: DB;
51
68
  t: Function;
@@ -65,6 +82,7 @@ interface FileCommand<DB = any> {
65
82
  interface FileComponent<DB = any> {
66
83
  filepath?: string;
67
84
  customId?: string;
85
+ preconditions?: string[];
68
86
  execute: (interaction: MessageComponentInteraction | ModalSubmitInteraction, client: Client & {
69
87
  db: DB;
70
88
  t: Function;
@@ -103,17 +121,41 @@ declare class DJSNextClient<DB = any> extends Client {
103
121
  private _developers;
104
122
  private _middleware?;
105
123
  private _prefixes;
124
+ private _enableSlashCommands;
125
+ private _enableTextCommands;
106
126
  private _enableMentionPrefix;
127
+ private _enableNoPrefix;
107
128
  constructor(options: DJSNextClientOptions);
108
129
  private attachCoreListeners;
109
130
  start(token: string): Promise<void>;
110
131
  enableDevTools(prefix?: 'dnxt' | 'nxt'): void;
111
132
  enableHMR(): Promise<void>;
133
+ private handleCommandError;
134
+ private handlePreconditions;
112
135
  }
113
136
 
114
- declare function paginate(interaction: CommandInteraction | MessageComponentInteraction, pages: EmbedBuilder[], time?: number): Promise<discord_js.Message<boolean> | undefined>;
137
+ declare function paginate(context: Message | CommandInteraction | MessageComponentInteraction, pages: EmbedBuilder[], time?: number): Promise<Message<boolean> | undefined>;
138
+
139
+ /**
140
+ * Sends a confirmation prompt (Yes/No) to the user.
141
+ * @param context The message or interaction context.
142
+ * @param content The text or embed to display in the prompt.
143
+ * @param time Time to wait for a response in milliseconds.
144
+ * @returns Boolean indicating true for Yes, false for No, or null if timed out.
145
+ */
146
+ declare function confirmPrompt(context: Message | CommandInteraction | MessageComponentInteraction, content: string | EmbedBuilder, time?: number): Promise<boolean | null>;
115
147
 
116
148
  declare function loadConfig(): Promise<DJSNextConfig>;
117
149
  declare function defineConfig(config: DJSNextConfig): DJSNextConfig;
118
150
 
119
- export { DJSNextClient, type DJSNextClientOptions, type DJSNextConfig, type Event as DJSNextEvent, type FileCommand, type FileComponent, type FileTask, defineConfig, getLocalesCache, loadConfig, loadLocales, paginate, translate };
151
+ declare class PaginationBuilder {
152
+ private pages;
153
+ private timeout;
154
+ constructor(pages?: EmbedBuilder[]);
155
+ addPage(embed: EmbedBuilder): this;
156
+ setPages(pages: EmbedBuilder[]): this;
157
+ setTimeout(ms: number): this;
158
+ build(target: CommandInteraction | Message): Promise<Message | null>;
159
+ }
160
+
161
+ export { type CooldownAdapter, DJSNextClient, type DJSNextClientOptions, type DJSNextConfig, type Event as DJSNextEvent, type FileCommand, type FileComponent, type FileTask, PaginationBuilder, confirmPrompt, defineConfig, getLocalesCache, loadConfig, loadLocales, paginate, translate };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,20 @@
1
- import * as discord_js from 'discord.js';
2
1
  import { ApplicationCommandOptionData, PermissionResolvable, ChatInputCommandInteraction, Client, Message, AutocompleteInteraction, MessageComponentInteraction, ModalSubmitInteraction, ClientOptions, Interaction, ClientEvents, Collection, CommandInteraction, EmbedBuilder } from 'discord.js';
3
2
  export * from 'discord.js';
4
3
 
4
+ interface CooldownAdapter {
5
+ get(commandId: string, userId: string): Promise<number | null> | number | null;
6
+ set(commandId: string, userId: string, expirationTime: number): Promise<void> | void;
7
+ }
5
8
  interface DJSNextConfig {
6
9
  devGuildId?: string;
10
+ errorLogChannelId?: string;
11
+ responses?: {
12
+ developerOnly?: string | null;
13
+ guildOnly?: string | null;
14
+ cooldown?: string | null;
15
+ missingPerms?: string | null;
16
+ errorBoundary?: string | null;
17
+ };
7
18
  locales?: string[];
8
19
  defaultLocale?: string;
9
20
  directories?: {
@@ -13,6 +24,7 @@ interface DJSNextConfig {
13
24
  tasks?: string;
14
25
  locales?: string;
15
26
  };
27
+ cooldownAdapter?: CooldownAdapter;
16
28
  }
17
29
  interface DJSNextClientOptions extends ClientOptions {
18
30
  commandsDir?: string;
@@ -23,9 +35,13 @@ interface DJSNextClientOptions extends ClientOptions {
23
35
  guildId?: string;
24
36
  developers?: string[];
25
37
  prefixes?: string[] | string;
26
- enableMentionPrefix?: boolean;
38
+ enableSlashCommands?: boolean;
39
+ enableTextCommands?: boolean;
40
+ enableMentionPrefix?: boolean | string[];
41
+ enableNoPrefix?: boolean | string[];
27
42
  middleware?: (interaction: Interaction | Message, client: Client) => Promise<boolean> | boolean;
28
43
  config?: DJSNextConfig;
44
+ db?: any;
29
45
  }
30
46
  interface FileTask<DB = any> {
31
47
  filepath?: string;
@@ -46,6 +62,7 @@ interface FileCommand<DB = any> {
46
62
  developerOnly?: boolean;
47
63
  guildOnly?: boolean;
48
64
  aliases?: string[];
65
+ preconditions?: string[];
49
66
  execute?: (interaction: ChatInputCommandInteraction, client: Client & {
50
67
  db: DB;
51
68
  t: Function;
@@ -65,6 +82,7 @@ interface FileCommand<DB = any> {
65
82
  interface FileComponent<DB = any> {
66
83
  filepath?: string;
67
84
  customId?: string;
85
+ preconditions?: string[];
68
86
  execute: (interaction: MessageComponentInteraction | ModalSubmitInteraction, client: Client & {
69
87
  db: DB;
70
88
  t: Function;
@@ -103,17 +121,41 @@ declare class DJSNextClient<DB = any> extends Client {
103
121
  private _developers;
104
122
  private _middleware?;
105
123
  private _prefixes;
124
+ private _enableSlashCommands;
125
+ private _enableTextCommands;
106
126
  private _enableMentionPrefix;
127
+ private _enableNoPrefix;
107
128
  constructor(options: DJSNextClientOptions);
108
129
  private attachCoreListeners;
109
130
  start(token: string): Promise<void>;
110
131
  enableDevTools(prefix?: 'dnxt' | 'nxt'): void;
111
132
  enableHMR(): Promise<void>;
133
+ private handleCommandError;
134
+ private handlePreconditions;
112
135
  }
113
136
 
114
- declare function paginate(interaction: CommandInteraction | MessageComponentInteraction, pages: EmbedBuilder[], time?: number): Promise<discord_js.Message<boolean> | undefined>;
137
+ declare function paginate(context: Message | CommandInteraction | MessageComponentInteraction, pages: EmbedBuilder[], time?: number): Promise<Message<boolean> | undefined>;
138
+
139
+ /**
140
+ * Sends a confirmation prompt (Yes/No) to the user.
141
+ * @param context The message or interaction context.
142
+ * @param content The text or embed to display in the prompt.
143
+ * @param time Time to wait for a response in milliseconds.
144
+ * @returns Boolean indicating true for Yes, false for No, or null if timed out.
145
+ */
146
+ declare function confirmPrompt(context: Message | CommandInteraction | MessageComponentInteraction, content: string | EmbedBuilder, time?: number): Promise<boolean | null>;
115
147
 
116
148
  declare function loadConfig(): Promise<DJSNextConfig>;
117
149
  declare function defineConfig(config: DJSNextConfig): DJSNextConfig;
118
150
 
119
- export { DJSNextClient, type DJSNextClientOptions, type DJSNextConfig, type Event as DJSNextEvent, type FileCommand, type FileComponent, type FileTask, defineConfig, getLocalesCache, loadConfig, loadLocales, paginate, translate };
151
+ declare class PaginationBuilder {
152
+ private pages;
153
+ private timeout;
154
+ constructor(pages?: EmbedBuilder[]);
155
+ addPage(embed: EmbedBuilder): this;
156
+ setPages(pages: EmbedBuilder[]): this;
157
+ setTimeout(ms: number): this;
158
+ build(target: CommandInteraction | Message): Promise<Message | null>;
159
+ }
160
+
161
+ export { type CooldownAdapter, DJSNextClient, type DJSNextClientOptions, type DJSNextConfig, type Event as DJSNextEvent, type FileCommand, type FileComponent, type FileTask, PaginationBuilder, confirmPrompt, defineConfig, getLocalesCache, loadConfig, loadLocales, paginate, translate };