reciple 6.0.0-dev.14 → 6.0.0-dev.16

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/dist/lib/bin.mjs CHANGED
@@ -32,13 +32,22 @@ const client = new RecipleClient({ config: config, ...config.client });
32
32
  if (!client.isClientLogsSilent)
33
33
  client.logger.info('Starting Reciple client v' + rawVersion);
34
34
  client.addCommandListeners();
35
- await client.modules.startModules(await client.modules.getModulesFromFiles({
36
- files: await client.modules.getModulePaths({
37
- filter: file => file.endsWith('.js') || file.endsWith('.cjs') || file.endsWith('.mjs'),
35
+ await client.modules.startModules({
36
+ modules: await client.modules.resolveModuleFiles({
37
+ files: await client.modules.getModulePaths({
38
+ filter: file => file.endsWith('.js') || file.endsWith('.cjs') || file.endsWith('.mjs'),
39
+ }),
38
40
  }),
39
- }));
41
+ });
40
42
  client.on('ready', async () => {
41
- await client.modules.loadModules(client.modules.modules.toJSON(), true);
43
+ await client.modules.loadModules();
44
+ const unloadModulesAndStopProcess = async (signal) => {
45
+ await client.modules.unloadModules({ reason: 'ProcessExit' });
46
+ client.logger.warn(`Exitting process${signal === 'SIGINT' ? ': keyboard interrupt' : signal === 'SIGTERM' ? ': terminate' : signal}`);
47
+ process.exit();
48
+ };
49
+ process.once('SIGINT', signal => unloadModulesAndStopProcess(signal));
50
+ process.once('SIGTERM', signal => unloadModulesAndStopProcess(signal));
42
51
  if (!client.isClientLogsSilent)
43
52
  client.logger.log(`Loaded ${client.commands.slashCommands.size} slash commands`, `Loaded ${client.commands.messageCommands.size} message commands`);
44
53
  if (client.config.commands.slashCommand.registerCommands && (client.config.commands.slashCommand.allowRegisterEmptyCommandList || client.commands.applicationCommandsSize)) {
@@ -28,9 +28,9 @@ class RecipleModule {
28
28
  if (resolveCommands)
29
29
  this.resolveCommands();
30
30
  }
31
- async unLoad(reason) {
32
- if (typeof this.script.onUnLoad === 'function')
33
- await this.script.onUnLoad(reason, this.client);
31
+ async unload(reason) {
32
+ if (typeof this.script.onUnload === 'function')
33
+ await this.script.onUnload(reason, this.client);
34
34
  }
35
35
  async registerSlashCommands(...guilds) {
36
36
  for (const command of this.commands) {
@@ -7,6 +7,11 @@ class ApplicationCommandManager {
7
7
  constructor(client) {
8
8
  this.client = client;
9
9
  }
10
+ /**
11
+ * Sets application commands globally or in guilds
12
+ * @param commands Application commands
13
+ * @param guilds set only to guilds
14
+ */
10
15
  async set(commands, ...guilds) {
11
16
  guilds = (0, discord_js_1.normalizeArray)(guilds);
12
17
  if (!this.client.isReady())
@@ -27,9 +32,14 @@ class ApplicationCommandManager {
27
32
  else {
28
33
  await this.client.application.commands.set(commands, guild);
29
34
  if (!this.client.isClientLogsSilent)
30
- this.client.logger.log(`Registered ${this.client.commands.applicationCommandsSize} application command(s) to guild ${guild}...`);
35
+ this.client.logger.log(`Registered ${this.client.commands.applicationCommandsSize} application command(s) to guild ${guild}`);
31
36
  }
32
37
  }
38
+ /**
39
+ * Add command globally or in guilds
40
+ * @param command Application command
41
+ * @param guilds add only in guilds
42
+ */
33
43
  async add(command, ...guilds) {
34
44
  guilds = (0, discord_js_1.normalizeArray)(guilds);
35
45
  if (!this.client.isReady())
@@ -55,6 +65,11 @@ class ApplicationCommandManager {
55
65
  this.client.logger.log(`Created application command '${command.name}' to guild ${guild}`);
56
66
  }
57
67
  }
68
+ /**
69
+ * Remove application command globally or in guilds
70
+ * @param command id of application commmand or ApplicationCommand class
71
+ * @param guilds Remove from guilds
72
+ */
58
73
  async remove(command, ...guilds) {
59
74
  guilds = (0, discord_js_1.normalizeArray)(guilds);
60
75
  if (!this.client.isReady())
@@ -80,6 +95,12 @@ class ApplicationCommandManager {
80
95
  this.client.logger.log(`Removed application command '${typeof command === 'string' ? command : command.name}' from guild ${guild}`);
81
96
  }
82
97
  }
98
+ /**
99
+ * Edit application command globally or in guilds
100
+ * @param command id of application command or ApplicationCommand class
101
+ * @param newCommand new application command data
102
+ * @param guilds Edit only from guilds
103
+ */
83
104
  async edit(command, newCommand, ...guilds) {
84
105
  guilds = (0, discord_js_1.normalizeArray)(guilds);
85
106
  if (!this.client.isReady())
@@ -105,18 +126,33 @@ class ApplicationCommandManager {
105
126
  this.client.logger.log(`Removed application command '${typeof command === 'string' ? command : command.name}' from guild ${guild}`);
106
127
  }
107
128
  }
129
+ /**
130
+ * Get application command from cache by application command data, builder, id, or name globally or from guid
131
+ * @param command application command data, builder, id, or name
132
+ * @param guild get command from guild
133
+ */
108
134
  get(command, guild) {
109
135
  const commands = guild ? this.client.guilds.resolve(guild)?.commands.cache : this.client.application?.commands.cache;
110
136
  if (!commands)
111
137
  throw new Error('Guild not found in cache');
112
138
  return commands.find(cmd => (typeof command === 'string' ? cmd.id === command || cmd.name === command : cmd.name === command.name || (command instanceof discord_js_1.ApplicationCommand && cmd.id === command.id)));
113
139
  }
140
+ /**
141
+ * Fetch application command by id globally or from guild
142
+ * @param commandId command id
143
+ * @param guild fetch from guild
144
+ */
114
145
  async fetch(commandId, guild) {
115
146
  const manager = guild ? this.client.guilds.resolve(guild)?.commands : this.client.application?.commands;
116
147
  if (!manager)
117
148
  throw new Error('Guild not found in cache');
118
149
  return manager.fetch(commandId);
119
150
  }
151
+ /**
152
+ * Parse application command builders to command data
153
+ * @param commands Application command builders
154
+ * @param setPermissions set slash commands permissions
155
+ */
120
156
  parseCommands(commands, setPermissions = true) {
121
157
  return commands.map(cmd => {
122
158
  if (cmd?.toJSON === undefined)
@@ -17,8 +17,14 @@ class ClientModuleManager {
17
17
  this.client = options.client;
18
18
  options.modules?.forEach(m => (m instanceof RecipleModule_1.RecipleModule ? m : new RecipleModule_1.RecipleModule({ client: this.client, script: m })));
19
19
  }
20
- async startModules(modules, ignoreErrors = true) {
21
- for (const module_ of modules) {
20
+ /**
21
+ * Start modules
22
+ * @param options start modules options
23
+ * @returns started modules
24
+ */
25
+ async startModules(options) {
26
+ const startedModules = [];
27
+ for (const module_ of options.modules) {
22
28
  if (!this.client.isClientLogsSilent)
23
29
  this.client.logger.log(`Starting module '${module_}'`);
24
30
  try {
@@ -34,64 +40,88 @@ class ClientModuleManager {
34
40
  this.client.logger.error(`Module '${module_}' returned false onStart`);
35
41
  continue;
36
42
  }
37
- this.modules.set(module_.id, module_);
43
+ if (options.addToModulesCollection !== false)
44
+ this.modules.set(module_.id, module_);
45
+ startedModules.push(module_);
38
46
  }
39
47
  catch (err) {
40
- if (!ignoreErrors)
48
+ if (options?.ignoreErrors === false)
41
49
  throw err;
42
50
  if (!this.client.isClientLogsSilent)
43
51
  this.client.logger.error(`Failed to start module '${module_}': `, err);
44
52
  }
45
53
  }
46
- return modules;
54
+ return startedModules;
47
55
  }
48
- async loadModules(modules, addModuleCommandsToClient = true, ignoreErrors = true) {
49
- for (const module_ of this.modules.toJSON()) {
56
+ /**
57
+ * Load modules
58
+ * @param options load modules options
59
+ * @returns loaded modules
60
+ */
61
+ async loadModules(options) {
62
+ const loadedModules = [];
63
+ for (const module_ of options?.modules ?? this.modules.toJSON()) {
50
64
  try {
51
65
  await module_.load().catch(err => {
52
66
  throw err;
53
67
  });
54
- if (!this.client.isClientLogsSilent)
55
- this.client.logger.log(`Loaded module '${module_}'`);
56
- if (addModuleCommandsToClient) {
68
+ if (options?.resolveCommands !== false) {
69
+ module_.resolveCommands();
57
70
  this.client.commands.add(module_.commands);
58
71
  }
72
+ loadedModules.push(module_);
73
+ if (!this.client.isClientLogsSilent)
74
+ this.client.logger.log(`Loaded module '${module_}'`);
59
75
  }
60
76
  catch (err) {
61
- if (!ignoreErrors)
77
+ if (options?.ignoreErrors === false)
62
78
  throw err;
63
79
  if (!this.client.isClientLogsSilent)
64
80
  this.client.logger.error(`Failed to load module '${module_}': `, err);
65
81
  }
66
82
  }
67
- return modules;
83
+ return loadedModules;
68
84
  }
69
- async unLoadModules(modules, removeUnloadedModules = true, ignoreErrors = true) {
70
- for (const module_ of this.modules.toJSON()) {
85
+ /**
86
+ * Unload modules
87
+ * @param options unload modules options
88
+ * @returns unloaded modules
89
+ */
90
+ async unloadModules(options) {
91
+ const unloadedModules = [];
92
+ for (const module_ of options?.modules ?? this.modules.toJSON()) {
71
93
  try {
72
- await module_.unLoad().catch(err => {
94
+ await module_.unload().catch(err => {
73
95
  throw err;
74
96
  });
75
- if (removeUnloadedModules)
76
- this.modules.delete(module_.id);
97
+ unloadedModules.push(module_);
77
98
  if (!this.client.isClientLogsSilent)
78
99
  this.client.logger.log(`Unloaded module '${module_}'`);
79
100
  }
80
101
  catch (err) {
81
- if (!ignoreErrors)
102
+ if (options?.ignoreErrors === false)
82
103
  throw err;
83
104
  if (!this.client.isClientLogsSilent)
84
105
  this.client.logger.error(`Failed to unLoad module '${module_}': `, err);
85
106
  }
86
107
  }
87
- return modules;
108
+ return unloadedModules;
88
109
  }
89
- async getModulesFromFiles(options) {
110
+ /**
111
+ * Resolve modules from file paths
112
+ * @param options resolve module files options
113
+ * @returns resolved modules
114
+ */
115
+ async resolveModuleFiles(options) {
90
116
  const modules = [];
91
117
  for (const file of options.files) {
92
118
  try {
93
119
  const resolveFile = await import(file);
94
- let script = resolveFile?.default ?? resolveFile;
120
+ let script = resolveFile instanceof RecipleModule_1.RecipleModule || ClientModuleManager.validateScript(resolveFile)
121
+ ? resolveFile
122
+ : resolveFile?.default?.default instanceof RecipleModule_1.RecipleModule || ClientModuleManager.validateScript(resolveFile?.default?.default)
123
+ ? resolveFile.default.default
124
+ : resolveFile?.default;
95
125
  if (script instanceof RecipleModule_1.RecipleModule) {
96
126
  modules.push(script);
97
127
  continue;
@@ -105,7 +135,7 @@ class ClientModuleManager {
105
135
  }));
106
136
  }
107
137
  catch (err) {
108
- if (options.dontSkipError)
138
+ if (options.ignoreErrors === false)
109
139
  throw err;
110
140
  if (!this.client.isClientLogsSilent)
111
141
  this.client.logger.error(`Can't resolve module from: ${file}`, err);
@@ -113,6 +143,11 @@ class ClientModuleManager {
113
143
  }
114
144
  return modules;
115
145
  }
146
+ /**
147
+ * Validate module script
148
+ * @param script module script
149
+ * @returns `true` if script is valid
150
+ */
116
151
  static validateScript(script) {
117
152
  const s = script;
118
153
  if (typeof s !== 'object')
@@ -123,10 +158,15 @@ class ClientModuleManager {
123
158
  return false;
124
159
  if (s.onLoad && typeof s.onLoad !== 'function')
125
160
  return false;
126
- if (s.onUnLoad && typeof s.onUnLoad !== 'function')
161
+ if (s.onUnload && typeof s.onUnload !== 'function')
127
162
  return false;
128
163
  return true;
129
164
  }
165
+ /**
166
+ * Get module file paths from folders
167
+ * @param options get module paths options
168
+ * @returns module paths
169
+ */
130
170
  async getModulePaths(options) {
131
171
  const modules = [];
132
172
  for (const dir of options?.folders ?? (0, discord_js_1.normalizeArray)([this.client.config.modulesFolder])) {
@@ -28,7 +28,7 @@ export interface RecipleScript {
28
28
  * @param reason Unload reason
29
29
  * @param client Bot client
30
30
  */
31
- onUnLoad?(reason: unknown, client: RecipleClient<true>): void | Promise<void>;
31
+ onUnload?(reason: unknown, client: RecipleClient<true>): void | Promise<void>;
32
32
  }
33
33
  export interface RecipleModuleOptions<M = unknown> {
34
34
  client: RecipleClient;
@@ -47,7 +47,7 @@ export declare class RecipleModule<M = unknown> {
47
47
  constructor(options: RecipleModuleOptions<M>);
48
48
  start(): Promise<boolean>;
49
49
  load(resolveCommands?: boolean): Promise<void>;
50
- unLoad(reason?: any): Promise<void>;
50
+ unload(reason?: any): Promise<void>;
51
51
  registerSlashCommands(...guilds: RestOrArray<GuildResolvable>): Promise<void>;
52
52
  unregisterSlashCommands(...guilds: RestOrArray<GuildResolvable>): Promise<void>;
53
53
  updateSlashCommands(...guilds: RestOrArray<GuildResolvable>): Promise<void>;
@@ -5,11 +5,47 @@ export declare type ApplicationCommandBuilder = AnySlashCommandBuilder | Context
5
5
  export declare class ApplicationCommandManager {
6
6
  readonly client: RecipleClient;
7
7
  constructor(client: RecipleClient);
8
+ /**
9
+ * Sets application commands globally or in guilds
10
+ * @param commands Application commands
11
+ * @param guilds set only to guilds
12
+ */
8
13
  set(commands: (ApplicationCommandBuilder | ApplicationCommandData)[], ...guilds: RestOrArray<GuildResolvable>): Promise<void>;
14
+ /**
15
+ * Add command globally or in guilds
16
+ * @param command Application command
17
+ * @param guilds add only in guilds
18
+ */
9
19
  add(command: ApplicationCommandBuilder | ApplicationCommandData, ...guilds: RestOrArray<GuildResolvable>): Promise<void>;
20
+ /**
21
+ * Remove application command globally or in guilds
22
+ * @param command id of application commmand or ApplicationCommand class
23
+ * @param guilds Remove from guilds
24
+ */
10
25
  remove(command: string | ApplicationCommand, ...guilds: RestOrArray<GuildResolvable>): Promise<void>;
26
+ /**
27
+ * Edit application command globally or in guilds
28
+ * @param command id of application command or ApplicationCommand class
29
+ * @param newCommand new application command data
30
+ * @param guilds Edit only from guilds
31
+ */
11
32
  edit(command: string | ApplicationCommand, newCommand: ApplicationCommandBuilder | ApplicationCommandData, ...guilds: RestOrArray<GuildResolvable>): Promise<void>;
33
+ /**
34
+ * Get application command from cache by application command data, builder, id, or name globally or from guid
35
+ * @param command application command data, builder, id, or name
36
+ * @param guild get command from guild
37
+ */
12
38
  get(command: ApplicationCommandData | ApplicationCommandBuilder | string, guild?: GuildResolvable): ApplicationCommand | undefined;
39
+ /**
40
+ * Fetch application command by id globally or from guild
41
+ * @param commandId command id
42
+ * @param guild fetch from guild
43
+ */
13
44
  fetch(commandId: string, guild?: GuildResolvable): Promise<ApplicationCommand>;
45
+ /**
46
+ * Parse application command builders to command data
47
+ * @param commands Application command builders
48
+ * @param setPermissions set slash commands permissions
49
+ */
14
50
  protected parseCommands(commands: (ApplicationCommandData | ApplicationCommandBuilder | RESTPostAPIApplicationCommandsJSONBody)[], setPermissions?: boolean): (ApplicationCommandData | RESTPostAPIApplicationCommandsJSONBody)[];
15
51
  }
@@ -1,5 +1,5 @@
1
1
  import { Collection } from 'discord.js';
2
- import { ClientModuleManagerGetModulePathsOptions, ClientModuleManagerGetModulesFromFilesOptions } from '../../types/paramOptions';
2
+ import { ClientModuleManagerGetModulePathsOptions, ClientModuleManagerLoadModulesOptions, ClientModuleManagerResolveModuleFilesOptions, ClientModuleManagerStartModulesOptions, ClientModuleManagerUnloadModulesOptions } from '../../types/paramOptions';
3
3
  import { RecipleClient } from '../RecipleClient';
4
4
  import { RecipleModule, RecipleScript } from '../RecipleModule';
5
5
  export interface ClientModuleManagerOptions {
@@ -10,10 +10,40 @@ export declare class ClientModuleManager {
10
10
  readonly client: RecipleClient;
11
11
  readonly modules: Collection<string, RecipleModule>;
12
12
  constructor(options: ClientModuleManagerOptions);
13
- startModules(modules: RecipleModule[], ignoreErrors?: boolean): Promise<RecipleModule[]>;
14
- loadModules(modules: RecipleModule[], addModuleCommandsToClient?: boolean, ignoreErrors?: boolean): Promise<RecipleModule[]>;
15
- unLoadModules(modules: RecipleModule[], removeUnloadedModules?: boolean, ignoreErrors?: boolean): Promise<RecipleModule[]>;
16
- getModulesFromFiles(options: ClientModuleManagerGetModulesFromFilesOptions): Promise<RecipleModule[]>;
13
+ /**
14
+ * Start modules
15
+ * @param options start modules options
16
+ * @returns started modules
17
+ */
18
+ startModules(options: ClientModuleManagerStartModulesOptions): Promise<RecipleModule[]>;
19
+ /**
20
+ * Load modules
21
+ * @param options load modules options
22
+ * @returns loaded modules
23
+ */
24
+ loadModules(options?: ClientModuleManagerLoadModulesOptions): Promise<RecipleModule[]>;
25
+ /**
26
+ * Unload modules
27
+ * @param options unload modules options
28
+ * @returns unloaded modules
29
+ */
30
+ unloadModules(options?: ClientModuleManagerUnloadModulesOptions): Promise<RecipleModule[]>;
31
+ /**
32
+ * Resolve modules from file paths
33
+ * @param options resolve module files options
34
+ * @returns resolved modules
35
+ */
36
+ resolveModuleFiles(options: ClientModuleManagerResolveModuleFilesOptions): Promise<RecipleModule[]>;
37
+ /**
38
+ * Validate module script
39
+ * @param script module script
40
+ * @returns `true` if script is valid
41
+ */
17
42
  static validateScript(script: unknown): script is RecipleScript;
43
+ /**
44
+ * Get module file paths from folders
45
+ * @param options get module paths options
46
+ * @returns module paths
47
+ */
18
48
  getModulePaths(options?: ClientModuleManagerGetModulePathsOptions): Promise<string[]>;
19
49
  }
@@ -1,6 +1,7 @@
1
1
  import { ConfigCommandPermissions } from '../classes/RecipleConfig';
2
2
  import { Awaitable, PermissionsBitField } from 'discord.js';
3
3
  import { AnyCommandBuilder } from './builders';
4
+ import { RecipleModule } from '../classes/RecipleModule';
4
5
  export interface UserHasCommandPermissionsOptions {
5
6
  /**
6
7
  * Command builder
@@ -18,13 +19,83 @@ export interface UserHasCommandPermissionsOptions {
18
19
  commands: ConfigCommandPermissions[];
19
20
  };
20
21
  }
21
- export interface ClientModuleManagerGetModulesFromFilesOptions {
22
+ export interface ClientModuleManagerResolveModuleFilesOptions {
23
+ /**
24
+ * valid reciple module (ESM or CJS) Javascript file paths
25
+ */
22
26
  files: string[];
27
+ /**
28
+ * Allow loading unsupported module versions
29
+ * @default false
30
+ */
23
31
  disabeVersionCheck?: boolean;
24
- dontSkipError?: boolean;
32
+ /**
33
+ * Ignore errors
34
+ * @dafault true
35
+ */
36
+ ignoreErrors?: boolean;
25
37
  }
26
38
  export interface ClientModuleManagerGetModulePathsOptions {
39
+ /**
40
+ * Get javascript module file paths from folders
41
+ */
27
42
  folders?: string[];
43
+ /**
44
+ * Add ignored files (wildcard)
45
+ * @example _*.js // Ignores _module.js and _hi.js
46
+ */
28
47
  ignoredFiles?: string[];
48
+ /**
49
+ * Filter found javascript files
50
+ * @param file Loaded javascript file
51
+ * @returns `true` if the path is acceptable
52
+ */
29
53
  filter?: (file: string) => Awaitable<boolean>;
30
54
  }
55
+ export interface ClientModuleManagerStartModulesOptions {
56
+ /**
57
+ * Modules to start
58
+ */
59
+ modules: RecipleModule[];
60
+ /**
61
+ * Add modules to Client modules collection
62
+ * @default true
63
+ */
64
+ addToModulesCollection?: boolean;
65
+ /**
66
+ * Ignore errors
67
+ * @default true
68
+ */
69
+ ignoreErrors?: boolean;
70
+ }
71
+ export interface ClientModuleManagerLoadModulesOptions {
72
+ /**
73
+ * Modules to execute `load` method
74
+ */
75
+ modules?: RecipleModule[];
76
+ /**
77
+ * Add commands to client
78
+ * @default true
79
+ */
80
+ resolveCommands?: boolean;
81
+ /**
82
+ * Ignore errors
83
+ * @default true
84
+ */
85
+ ignoreErrors?: boolean;
86
+ }
87
+ export interface ClientModuleManagerUnloadModulesOptions {
88
+ /**
89
+ * Modules to execute `unload` method
90
+ */
91
+ modules?: RecipleModule[];
92
+ /**
93
+ * Reason for unloading modules
94
+ */
95
+ reason?: string;
96
+ /**
97
+ * Ignore errors
98
+ * @default true
99
+ */
100
+ ignoreErrors?: boolean;
101
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reciple",
3
- "version": "6.0.0-dev.14",
3
+ "version": "6.0.0-dev.16",
4
4
  "bin": "./dist/lib/bin.mjs",
5
5
  "license": "GPL-3.0",
6
6
  "type": "commonjs",