zumito-framework 1.22.2 → 1.23.1
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/ZumitoFramework.js +22 -5
- package/dist/definitions/Module.d.ts +11 -0
- package/dist/definitions/Module.js +9 -0
- package/dist/index.d.ts +2 -2
- package/dist/modules/core/baseModule/events/discord/MessageCreate.js +16 -0
- package/dist/services/handlers/InteractionHandler.js +45 -19
- package/dist/services/managers/CommandManager.js +2 -0
- package/dist/services/managers/ModuleManager.d.ts +14 -2
- package/dist/services/managers/ModuleManager.js +118 -1
- package/package.json +1 -1
package/dist/ZumitoFramework.js
CHANGED
|
@@ -316,27 +316,44 @@ export class ZumitoFramework {
|
|
|
316
316
|
modulesFolder = `${process.cwd()}/src/modules`;
|
|
317
317
|
}
|
|
318
318
|
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
319
|
+
const moduleEntries = [];
|
|
319
320
|
if (this.settings.bundles && this.settings.bundles.length > 0) {
|
|
320
321
|
for (const bundle of this.settings.bundles) {
|
|
321
|
-
|
|
322
|
+
moduleEntries.push({
|
|
323
|
+
rootPath: bundle.path,
|
|
324
|
+
options: bundle.options,
|
|
325
|
+
});
|
|
322
326
|
}
|
|
323
327
|
}
|
|
324
|
-
|
|
328
|
+
moduleEntries.push({
|
|
329
|
+
rootPath: path.join(__dirname, 'modules', 'core'),
|
|
330
|
+
name: 'baseModule',
|
|
331
|
+
});
|
|
325
332
|
if (fs.existsSync(`${process.cwd()}/node_modules/.zumitoBundles`)) {
|
|
326
333
|
const files = fs.readdirSync(`${process.cwd()}/node_modules/.zumitoBundles`);
|
|
327
334
|
for (const file of files) {
|
|
328
|
-
|
|
335
|
+
moduleEntries.push({
|
|
336
|
+
rootPath: path.join(process.cwd(), 'node_modules', '.zumitoBundles', file),
|
|
337
|
+
name: file,
|
|
338
|
+
});
|
|
329
339
|
}
|
|
330
340
|
}
|
|
331
341
|
if (modulesFolder) {
|
|
332
342
|
const files = fs.readdirSync(modulesFolder);
|
|
333
343
|
for (const file of files) {
|
|
334
|
-
|
|
344
|
+
moduleEntries.push({
|
|
345
|
+
rootPath: path.join(modulesFolder, file),
|
|
346
|
+
name: file,
|
|
347
|
+
});
|
|
335
348
|
}
|
|
336
349
|
}
|
|
337
350
|
else if (this.settings.srcMode == 'monoBundle') {
|
|
338
|
-
|
|
351
|
+
moduleEntries.push({
|
|
352
|
+
rootPath: path.join(process.cwd(), 'src'),
|
|
353
|
+
name: 'src',
|
|
354
|
+
});
|
|
339
355
|
}
|
|
356
|
+
await this.modules.resolveAndInstantiateAll(moduleEntries);
|
|
340
357
|
}
|
|
341
358
|
async registerModule(modulesFolder, moduleName, module) {
|
|
342
359
|
if (!module) {
|
|
@@ -8,11 +8,22 @@ export type ModuleRequeriments = {
|
|
|
8
8
|
services: Array<string>;
|
|
9
9
|
custom: Array<() => Promise<boolean>>;
|
|
10
10
|
};
|
|
11
|
+
export type ModuleDeclaration = {
|
|
12
|
+
moduleClass: typeof Module;
|
|
13
|
+
name: string;
|
|
14
|
+
rootPath: string;
|
|
15
|
+
options?: ModuleParameters;
|
|
16
|
+
requiredDeps: string[];
|
|
17
|
+
optionalDeps: string[];
|
|
18
|
+
};
|
|
11
19
|
export declare abstract class Module {
|
|
12
20
|
protected path: string;
|
|
13
21
|
protected parameters: ModuleParameters;
|
|
14
22
|
protected framework: ZumitoFramework;
|
|
15
23
|
protected events: Map<string, FrameworkEvent>;
|
|
24
|
+
static moduleName?: string;
|
|
25
|
+
static dependencies?: readonly string[];
|
|
26
|
+
static optionalDependencies?: readonly string[];
|
|
16
27
|
static requeriments: ModuleRequeriments;
|
|
17
28
|
protected errorHandler: ErrorHandler;
|
|
18
29
|
constructor(path: any, parameters?: ModuleParameters);
|
|
@@ -11,6 +11,9 @@ export class Module {
|
|
|
11
11
|
parameters;
|
|
12
12
|
framework;
|
|
13
13
|
events = new Map();
|
|
14
|
+
static moduleName;
|
|
15
|
+
static dependencies;
|
|
16
|
+
static optionalDependencies;
|
|
14
17
|
static requeriments;
|
|
15
18
|
errorHandler;
|
|
16
19
|
constructor(path, parameters) {
|
|
@@ -59,6 +62,8 @@ export class Module {
|
|
|
59
62
|
for (const file of files) {
|
|
60
63
|
if (file.endsWith('.d.ts'))
|
|
61
64
|
continue;
|
|
65
|
+
if (file.endsWith('.ts') && files.includes(file.replace(/\.ts$/, '.js')))
|
|
66
|
+
continue;
|
|
62
67
|
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
63
68
|
let event = await import('file://' + path.join(folderPath, file)).catch((e) => {
|
|
64
69
|
console.error(`[🔄🔴 ] Error loading ${file.slice(0, -3)} event on module ${this.constructor.name}`);
|
|
@@ -117,6 +122,8 @@ export class Module {
|
|
|
117
122
|
for (const file of files) {
|
|
118
123
|
if (file.endsWith('.d.ts'))
|
|
119
124
|
continue;
|
|
125
|
+
if (file.endsWith('.ts') && files.includes(file.replace(/\.ts$/, '.js')))
|
|
126
|
+
continue;
|
|
120
127
|
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
121
128
|
const mod = await import('file://' + path.join(modelsFolder, file)).catch((e) => {
|
|
122
129
|
this.errorHandler.handleError(e, {
|
|
@@ -149,6 +156,8 @@ export class Module {
|
|
|
149
156
|
for (const file of files) {
|
|
150
157
|
if (file.endsWith('.d.ts'))
|
|
151
158
|
continue;
|
|
159
|
+
if (file.endsWith('.ts') && files.includes(file.replace(/\.ts$/, '.js')))
|
|
160
|
+
continue;
|
|
152
161
|
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
153
162
|
let route = await import('file://' + path.join(folderPath, file)).catch((e) => {
|
|
154
163
|
this.errorHandler.handleError(e, {
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { DatabaseConfigLoader } from './services/utilities/DatabaseConfigLoader.
|
|
|
12
12
|
import { EmojiFallback } from './services/EmojiFallback.js';
|
|
13
13
|
import { FrameworkEvent } from './definitions/FrameworkEvent.js';
|
|
14
14
|
import { FrameworkSettings } from './definitions/FrameworkSettings.js';
|
|
15
|
-
import { Module } from './definitions/Module.js';
|
|
15
|
+
import { Module, ModuleDeclaration, ModuleRequeriments } from './definitions/Module.js';
|
|
16
16
|
import { SelectMenuParameters } from './definitions/parameters/SelectMenuParameters.js';
|
|
17
17
|
import { TextFormatter } from './services/utilities/TextFormatter.js';
|
|
18
18
|
import { Translation } from './definitions/Translation.js';
|
|
@@ -42,4 +42,4 @@ export { CommandBinds } from './definitions/commands/CommandBinds.js';
|
|
|
42
42
|
export { Injectable } from './definitions/decorators/Injectable.decorator.js';
|
|
43
43
|
export { LauncherConfig } from './definitions/config/LauncherConfig.js';
|
|
44
44
|
export { ModuleParameters } from './definitions/parameters/ModuleParameters.js';
|
|
45
|
-
export { ZumitoFramework, FrameworkSettings, Command, Module, CommandParameters, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, SelectMenuParameters, CommandType, CommandArgDefinition, CommandChoiceDefinition, ButtonPressed, ButtonPressedParams, TextFormatter, EmojiFallback, DatabaseConfigLoader, PresenceDataRule, RuledPresenceData, StatusManagerOptions, discord, EventParameters, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, ErrorHandler, ErrorType, Route, RouteMethod, InteractionHandler, CommandManager, InviteUrlGenerator, PrefixResolver, CommandExecutionChecker, DatabaseManager, };
|
|
45
|
+
export { ZumitoFramework, FrameworkSettings, Command, Module, ModuleDeclaration, ModuleRequeriments, CommandParameters, CommandArguments, FrameworkEvent, Translation, TranslationManager, ApiResponse, SelectMenuParameters, CommandType, CommandArgDefinition, CommandChoiceDefinition, ButtonPressed, ButtonPressedParams, TextFormatter, EmojiFallback, DatabaseConfigLoader, PresenceDataRule, RuledPresenceData, StatusManagerOptions, discord, EventParameters, ServiceContainer, GuildDataGetter, SlashCommandRefresher, CommandParser, ErrorHandler, ErrorType, Route, RouteMethod, InteractionHandler, CommandManager, InviteUrlGenerator, PrefixResolver, CommandExecutionChecker, DatabaseManager, };
|
|
@@ -76,6 +76,7 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
76
76
|
allowedMentions: { repliedUser: false },
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
|
+
const startTime = Date.now();
|
|
79
80
|
await commandInstance.execute({
|
|
80
81
|
message,
|
|
81
82
|
args: parsedArgs,
|
|
@@ -90,7 +91,22 @@ export class MessageCreate extends FrameworkEvent {
|
|
|
90
91
|
return this.framework.translations.get('command.' + commandInstance.name + '.' + key, guildSettings.lang, params);
|
|
91
92
|
}
|
|
92
93
|
},
|
|
94
|
+
}).then(() => {
|
|
95
|
+
this.framework.eventEmitter.emit('commandExecuted', {
|
|
96
|
+
guildId: message.guildId,
|
|
97
|
+
commandName: commandInstance.name,
|
|
98
|
+
type: 'prefix',
|
|
99
|
+
executionTimeMs: Date.now() - startTime,
|
|
100
|
+
success: true,
|
|
101
|
+
});
|
|
93
102
|
}).catch((error) => {
|
|
103
|
+
this.framework.eventEmitter.emit('commandExecuted', {
|
|
104
|
+
guildId: message.guildId,
|
|
105
|
+
commandName: commandInstance.name,
|
|
106
|
+
type: 'prefix',
|
|
107
|
+
executionTimeMs: Date.now() - startTime,
|
|
108
|
+
success: false,
|
|
109
|
+
});
|
|
94
110
|
const errorHandler = ServiceContainer.getService(ErrorHandler);
|
|
95
111
|
errorHandler.handleError(error, {
|
|
96
112
|
command: commandInstance,
|
|
@@ -112,31 +112,57 @@ export class InteractionHandler {
|
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
const trans = this.translationManager.getShortHandMethod('command.' + commandInstance.name, guildSettings?.lang);
|
|
115
|
+
const startTime = Date.now();
|
|
115
116
|
if (commandInstance.type === CommandType.separated ||
|
|
116
117
|
commandInstance.type === CommandType.slash) {
|
|
117
|
-
await commandInstance.executeSlashCommand({
|
|
118
|
-
client: this.client,
|
|
119
|
-
interaction, args, framework, guildSettings, trans,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
118
|
try {
|
|
124
|
-
await commandInstance.
|
|
119
|
+
await commandInstance.executeSlashCommand({
|
|
125
120
|
client: this.client,
|
|
126
121
|
interaction, args, framework, guildSettings, trans,
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
content: "An error ocurred while running this command.",
|
|
135
|
-
ephemeral: true
|
|
136
|
-
});
|
|
122
|
+
});
|
|
123
|
+
framework.eventEmitter.emit('commandExecuted', {
|
|
124
|
+
guildId: interaction.guildId,
|
|
125
|
+
commandName: commandInstance.name,
|
|
126
|
+
type: 'slash',
|
|
127
|
+
executionTimeMs: Date.now() - startTime,
|
|
128
|
+
success: true,
|
|
137
129
|
});
|
|
138
130
|
}
|
|
139
131
|
catch (error) {
|
|
132
|
+
framework.eventEmitter.emit('commandExecuted', {
|
|
133
|
+
guildId: interaction.guildId,
|
|
134
|
+
commandName: commandInstance.name,
|
|
135
|
+
type: 'slash',
|
|
136
|
+
executionTimeMs: Date.now() - startTime,
|
|
137
|
+
success: false,
|
|
138
|
+
});
|
|
139
|
+
this.errorHandler.handleError(error, {
|
|
140
|
+
command: commandInstance,
|
|
141
|
+
type: ErrorType.CommandRun,
|
|
142
|
+
interaction,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
await commandInstance.execute({
|
|
148
|
+
client: this.client,
|
|
149
|
+
interaction, args, framework, guildSettings, trans,
|
|
150
|
+
}).then(() => {
|
|
151
|
+
framework.eventEmitter.emit('commandExecuted', {
|
|
152
|
+
guildId: interaction.guildId,
|
|
153
|
+
commandName: commandInstance.name,
|
|
154
|
+
type: 'slash',
|
|
155
|
+
executionTimeMs: Date.now() - startTime,
|
|
156
|
+
success: true,
|
|
157
|
+
});
|
|
158
|
+
}).catch((error) => {
|
|
159
|
+
framework.eventEmitter.emit('commandExecuted', {
|
|
160
|
+
guildId: interaction.guildId,
|
|
161
|
+
commandName: commandInstance.name,
|
|
162
|
+
type: 'slash',
|
|
163
|
+
executionTimeMs: Date.now() - startTime,
|
|
164
|
+
success: false,
|
|
165
|
+
});
|
|
140
166
|
this.errorHandler.handleError(error, {
|
|
141
167
|
command: commandInstance,
|
|
142
168
|
type: ErrorType.CommandRun,
|
|
@@ -144,9 +170,9 @@ export class InteractionHandler {
|
|
|
144
170
|
});
|
|
145
171
|
interaction.reply({
|
|
146
172
|
content: "An error ocurred while running this command.",
|
|
147
|
-
ephemeral: true
|
|
173
|
+
ephemeral: true
|
|
148
174
|
});
|
|
149
|
-
}
|
|
175
|
+
});
|
|
150
176
|
}
|
|
151
177
|
}
|
|
152
178
|
async handleButtonInteraction(interaction, guildSettings) {
|
|
@@ -80,6 +80,8 @@ export class CommandManager {
|
|
|
80
80
|
for (const file of files) {
|
|
81
81
|
if (file.endsWith('.d.ts'))
|
|
82
82
|
continue;
|
|
83
|
+
if (file.endsWith('.ts') && files.includes(file.replace(/\.ts$/, '.js')))
|
|
84
|
+
continue;
|
|
83
85
|
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
84
86
|
const command = await this.loadCommandFile(path.join(folderPath, file), true);
|
|
85
87
|
if (command) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ZumitoFramework } from "../../ZumitoFramework.js";
|
|
2
|
-
import { Module } from "../../definitions/Module.js";
|
|
2
|
+
import { Module, ModuleDeclaration } from "../../definitions/Module.js";
|
|
3
3
|
import { ErrorHandler } from "../handlers/ErrorHandler.js";
|
|
4
4
|
import { ModuleParameters } from "../../definitions/parameters/ModuleParameters.js";
|
|
5
5
|
export declare class ModuleManager {
|
|
@@ -20,7 +20,19 @@ export declare class ModuleManager {
|
|
|
20
20
|
* @deprecated
|
|
21
21
|
*/
|
|
22
22
|
get size(): number;
|
|
23
|
-
|
|
23
|
+
resolveModuleName(moduleClass: typeof Module, fallbackName: string): string;
|
|
24
|
+
resolveModuleDeps(moduleClass: typeof Module): {
|
|
25
|
+
required: string[];
|
|
26
|
+
optional: string[];
|
|
27
|
+
};
|
|
28
|
+
buildDependencyGraph(declarations: ModuleDeclaration[]): Map<string, string[]>;
|
|
29
|
+
topologicalSort(declarations: ModuleDeclaration[]): ModuleDeclaration[];
|
|
30
|
+
resolveAndInstantiateAll(modulePaths: Array<{
|
|
31
|
+
rootPath: string;
|
|
32
|
+
options?: ModuleParameters;
|
|
33
|
+
name?: string;
|
|
34
|
+
}>): Promise<void>;
|
|
35
|
+
loadModuleFile(folderPath: string): Promise<typeof Module | undefined>;
|
|
24
36
|
registerModule(module: InstanceType<typeof Module>): void;
|
|
25
37
|
instanceModule(module: any, rootPath: string, name?: string, options?: ModuleParameters): Promise<Module | {
|
|
26
38
|
modules: string[];
|
|
@@ -30,6 +30,123 @@ export class ModuleManager {
|
|
|
30
30
|
get size() {
|
|
31
31
|
return this.modules.size;
|
|
32
32
|
}
|
|
33
|
+
resolveModuleName(moduleClass, fallbackName) {
|
|
34
|
+
return moduleClass.moduleName || fallbackName;
|
|
35
|
+
}
|
|
36
|
+
resolveModuleDeps(moduleClass) {
|
|
37
|
+
const required = new Set();
|
|
38
|
+
const optional = new Set();
|
|
39
|
+
if (moduleClass.dependencies) {
|
|
40
|
+
for (const d of moduleClass.dependencies)
|
|
41
|
+
required.add(d);
|
|
42
|
+
}
|
|
43
|
+
if (moduleClass.optionalDependencies) {
|
|
44
|
+
for (const d of moduleClass.optionalDependencies)
|
|
45
|
+
optional.add(d);
|
|
46
|
+
}
|
|
47
|
+
if (moduleClass.requeriments?.modules) {
|
|
48
|
+
for (const m of moduleClass.requeriments.modules)
|
|
49
|
+
required.add(m);
|
|
50
|
+
}
|
|
51
|
+
return { required: [...required], optional: [...optional] };
|
|
52
|
+
}
|
|
53
|
+
buildDependencyGraph(declarations) {
|
|
54
|
+
const nameSet = new Set(declarations.map((d) => d.name));
|
|
55
|
+
const graph = new Map();
|
|
56
|
+
for (const decl of declarations) {
|
|
57
|
+
const deps = [...decl.requiredDeps];
|
|
58
|
+
for (const opt of decl.optionalDeps) {
|
|
59
|
+
if (nameSet.has(opt))
|
|
60
|
+
deps.push(opt);
|
|
61
|
+
}
|
|
62
|
+
for (const dep of deps) {
|
|
63
|
+
if (!nameSet.has(dep)) {
|
|
64
|
+
throw new Error(`Module "${decl.name}" depends on "${dep}" which was not found`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
graph.set(decl.name, deps);
|
|
68
|
+
}
|
|
69
|
+
return graph;
|
|
70
|
+
}
|
|
71
|
+
topologicalSort(declarations) {
|
|
72
|
+
const graph = this.buildDependencyGraph(declarations);
|
|
73
|
+
const inDegree = new Map();
|
|
74
|
+
const adjacency = new Map();
|
|
75
|
+
for (const decl of declarations) {
|
|
76
|
+
const name = decl.name;
|
|
77
|
+
if (!inDegree.has(name))
|
|
78
|
+
inDegree.set(name, 0);
|
|
79
|
+
if (!adjacency.has(name))
|
|
80
|
+
adjacency.set(name, []);
|
|
81
|
+
}
|
|
82
|
+
for (const [name, deps] of graph) {
|
|
83
|
+
for (const dep of deps) {
|
|
84
|
+
if (!adjacency.has(dep))
|
|
85
|
+
adjacency.set(dep, []);
|
|
86
|
+
adjacency.get(dep).push(name);
|
|
87
|
+
inDegree.set(name, (inDegree.get(name) || 0) + 1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const queue = [];
|
|
91
|
+
for (const [name, degree] of inDegree) {
|
|
92
|
+
if (degree === 0)
|
|
93
|
+
queue.push(name);
|
|
94
|
+
}
|
|
95
|
+
const sorted = [];
|
|
96
|
+
while (queue.length > 0) {
|
|
97
|
+
const current = queue.shift();
|
|
98
|
+
sorted.push(current);
|
|
99
|
+
for (const neighbor of adjacency.get(current) || []) {
|
|
100
|
+
const newDegree = inDegree.get(neighbor) - 1;
|
|
101
|
+
inDegree.set(neighbor, newDegree);
|
|
102
|
+
if (newDegree === 0)
|
|
103
|
+
queue.push(neighbor);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (sorted.length < declarations.length) {
|
|
107
|
+
const unresolved = declarations
|
|
108
|
+
.filter((d) => !sorted.includes(d.name))
|
|
109
|
+
.map((d) => d.name);
|
|
110
|
+
throw new Error(`Circular dependency detected involving: ${unresolved.join(', ')}`);
|
|
111
|
+
}
|
|
112
|
+
const nameMap = new Map(declarations.map((d) => [d.name, d]));
|
|
113
|
+
return sorted.map((name) => nameMap.get(name));
|
|
114
|
+
}
|
|
115
|
+
async resolveAndInstantiateAll(modulePaths) {
|
|
116
|
+
const declarations = [];
|
|
117
|
+
for (const entry of modulePaths) {
|
|
118
|
+
const moduleClass = await this.loadModuleFile(entry.rootPath);
|
|
119
|
+
if (!moduleClass || moduleClass === Module)
|
|
120
|
+
continue;
|
|
121
|
+
const { required, optional } = this.resolveModuleDeps(moduleClass);
|
|
122
|
+
const name = this.resolveModuleName(moduleClass, entry.name || path.basename(entry.rootPath));
|
|
123
|
+
declarations.push({
|
|
124
|
+
moduleClass,
|
|
125
|
+
name,
|
|
126
|
+
rootPath: entry.rootPath,
|
|
127
|
+
options: entry.options,
|
|
128
|
+
requiredDeps: required,
|
|
129
|
+
optionalDeps: optional,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (declarations.length === 0)
|
|
133
|
+
return;
|
|
134
|
+
let sorted;
|
|
135
|
+
try {
|
|
136
|
+
sorted = this.topologicalSort(declarations);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
console.error(`[📦❌] ${err.message}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
for (const decl of sorted) {
|
|
143
|
+
const result = await this.instanceModule(decl.moduleClass, decl.rootPath, decl.name, decl.options);
|
|
144
|
+
if (result instanceof Module) {
|
|
145
|
+
console.log(`[📦✅] Module "${decl.name}" loaded successfully`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
await this.initializePendingModules();
|
|
149
|
+
}
|
|
33
150
|
async loadModuleFile(folderPath) {
|
|
34
151
|
let file;
|
|
35
152
|
if (fs.existsSync(path.join(folderPath, 'index.js'))) {
|
|
@@ -46,7 +163,7 @@ export class ModuleManager {
|
|
|
46
163
|
const moduleClass = exports.find((candidate) => {
|
|
47
164
|
return Object.getPrototypeOf(candidate).name === 'Module';
|
|
48
165
|
});
|
|
49
|
-
return moduleClass || exports[0];
|
|
166
|
+
return (moduleClass || exports[0]);
|
|
50
167
|
}
|
|
51
168
|
registerModule(module) {
|
|
52
169
|
// Register module events
|