zumito-framework 1.23.2 → 1.24.0
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 +30 -4
- package/dist/definitions/FrameworkSettings.d.ts +1 -1
- package/dist/definitions/Module.d.ts +1 -0
- package/dist/definitions/Module.js +2 -0
- package/dist/definitions/config/defineConfig.d.ts +9 -0
- package/dist/definitions/config/defineConfig.js +10 -0
- package/dist/definitions/config/moduleHelpers.d.ts +32 -0
- package/dist/definitions/config/moduleHelpers.js +71 -0
- package/dist/definitions/parameters/ModuleParameters.d.ts +7 -3
- package/dist/definitions/settings/FrameworkSettings.d.ts +36 -4
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/launcher.js +6 -1
- package/dist/services/managers/CommandManager.js +3 -0
- package/package.json +2 -2
package/dist/ZumitoFramework.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as url from 'url';
|
|
3
|
+
import { createRequire } from 'module';
|
|
3
4
|
import { Client, Events, } from 'discord.js';
|
|
4
5
|
import { ApiResponse } from './definitions/api/ApiResponse.js';
|
|
5
6
|
import { EventEmitter } from "tseep";
|
|
@@ -317,12 +318,37 @@ export class ZumitoFramework {
|
|
|
317
318
|
}
|
|
318
319
|
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
319
320
|
const moduleEntries = [];
|
|
321
|
+
const require = createRequire(import.meta.url);
|
|
322
|
+
// New format: modules as array of package names or ModuleEntry objects
|
|
323
|
+
if (this.settings.modules) {
|
|
324
|
+
for (const entry of this.settings.modules) {
|
|
325
|
+
if (typeof entry === 'string') {
|
|
326
|
+
const resolvedPath = require.resolve(entry, { paths: [process.cwd()] });
|
|
327
|
+
moduleEntries.push({ rootPath: resolvedPath + '/..', name: entry });
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const resolvedPath = entry.path ?? require.resolve(entry.name, { paths: [process.cwd()] });
|
|
331
|
+
moduleEntries.push({
|
|
332
|
+
rootPath: resolvedPath + '/..',
|
|
333
|
+
options: entry.config,
|
|
334
|
+
name: entry.name,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Backwards compat: old bundles format
|
|
320
340
|
if (this.settings.bundles && this.settings.bundles.length > 0) {
|
|
321
341
|
for (const bundle of this.settings.bundles) {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
342
|
+
if (typeof bundle === 'string') {
|
|
343
|
+
const resolvedPath = require.resolve(bundle, { paths: [process.cwd()] });
|
|
344
|
+
moduleEntries.push({ rootPath: resolvedPath + '/..', name: bundle });
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
moduleEntries.push({
|
|
348
|
+
rootPath: bundle.path,
|
|
349
|
+
options: bundle.options,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
326
352
|
}
|
|
327
353
|
}
|
|
328
354
|
moduleEntries.push({
|
|
@@ -19,6 +19,7 @@ export type ModuleDeclaration = {
|
|
|
19
19
|
export declare abstract class Module {
|
|
20
20
|
protected path: string;
|
|
21
21
|
protected parameters: ModuleParameters;
|
|
22
|
+
protected moduleConfig: Record<string, any>;
|
|
22
23
|
protected framework: ZumitoFramework;
|
|
23
24
|
protected events: Map<string, FrameworkEvent>;
|
|
24
25
|
static moduleName?: string;
|
|
@@ -9,6 +9,7 @@ import { getModelMetadata } from 'zumito-db';
|
|
|
9
9
|
export class Module {
|
|
10
10
|
path;
|
|
11
11
|
parameters;
|
|
12
|
+
moduleConfig;
|
|
12
13
|
framework;
|
|
13
14
|
events = new Map();
|
|
14
15
|
static moduleName;
|
|
@@ -21,6 +22,7 @@ export class Module {
|
|
|
21
22
|
this.parameters = parameters;
|
|
22
23
|
this.framework = ServiceContainer.getService(ZumitoFramework);
|
|
23
24
|
this.errorHandler = ServiceContainer.getService(ErrorHandler);
|
|
25
|
+
this.moduleConfig = parameters ?? {};
|
|
24
26
|
}
|
|
25
27
|
async initialize() {
|
|
26
28
|
await this.registerCommands();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LauncherConfig } from './LauncherConfig.js';
|
|
2
|
+
/**
|
|
3
|
+
* Type-safe helper for writing `zumito.config.ts`.
|
|
4
|
+
* Provides autocompletion for all framework settings and module-specific
|
|
5
|
+
* configs contributed via declaration merging on `ModuleConfigs`.
|
|
6
|
+
*
|
|
7
|
+
* Does not modify the config object — it's a pure identity function.
|
|
8
|
+
*/
|
|
9
|
+
export declare function defineConfig(config: LauncherConfig): LauncherConfig;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe helper for writing `zumito.config.ts`.
|
|
3
|
+
* Provides autocompletion for all framework settings and module-specific
|
|
4
|
+
* configs contributed via declaration merging on `ModuleConfigs`.
|
|
5
|
+
*
|
|
6
|
+
* Does not modify the config object — it's a pure identity function.
|
|
7
|
+
*/
|
|
8
|
+
export function defineConfig(config) {
|
|
9
|
+
return config;
|
|
10
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ZumitoFramework } from '../../ZumitoFramework.js';
|
|
2
|
+
import type { ModuleEntry } from '../settings/FrameworkSettings.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a type-safe factory function that returns a `ModuleEntry`.
|
|
5
|
+
* Reads the module name from the nearest `package.json` by walking up
|
|
6
|
+
* from the caller's location.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // admin/index.ts
|
|
11
|
+
* export const adminModule = createModuleEntry<AdminConfig>(import.meta.url);
|
|
12
|
+
*
|
|
13
|
+
* // Consumer's zumito.config.ts
|
|
14
|
+
* adminModule({ colors: { primary: '#ff0000' } })
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function createModuleEntry<T = Record<string, any>>(metaUrl: string): (config?: T) => ModuleEntry;
|
|
18
|
+
/**
|
|
19
|
+
* Retrieves the module-specific configuration from the framework settings
|
|
20
|
+
* by matching the module's package name against the `modules` array.
|
|
21
|
+
*
|
|
22
|
+
* Modules that are registered as plain strings in the `modules` array
|
|
23
|
+
* (without config) will return an empty object.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { getModuleConfig } from 'zumito-framework';
|
|
28
|
+
*
|
|
29
|
+
* const config = getModuleConfig<MyConfig>(framework, import.meta.url);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function getModuleConfig<T = Record<string, any>>(framework: ZumitoFramework | undefined, metaUrl: string): T;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, resolve } from 'path';
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
function findPackageJson(startPath) {
|
|
6
|
+
let dir = startPath;
|
|
7
|
+
for (let i = 0; i < 10; i++) {
|
|
8
|
+
const candidate = resolve(dir, 'package.json');
|
|
9
|
+
if (existsSync(candidate))
|
|
10
|
+
return candidate;
|
|
11
|
+
const parent = resolve(dir, '..');
|
|
12
|
+
if (parent === dir)
|
|
13
|
+
break;
|
|
14
|
+
dir = parent;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
function readModuleName(metaUrl) {
|
|
19
|
+
const filePath = fileURLToPath(metaUrl);
|
|
20
|
+
const callerDir = dirname(filePath);
|
|
21
|
+
const pkgPath = findPackageJson(callerDir);
|
|
22
|
+
if (!pkgPath)
|
|
23
|
+
return null;
|
|
24
|
+
const require = createRequire(pkgPath);
|
|
25
|
+
return require(pkgPath)?.name ?? null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a type-safe factory function that returns a `ModuleEntry`.
|
|
29
|
+
* Reads the module name from the nearest `package.json` by walking up
|
|
30
|
+
* from the caller's location.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* // admin/index.ts
|
|
35
|
+
* export const adminModule = createModuleEntry<AdminConfig>(import.meta.url);
|
|
36
|
+
*
|
|
37
|
+
* // Consumer's zumito.config.ts
|
|
38
|
+
* adminModule({ colors: { primary: '#ff0000' } })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function createModuleEntry(metaUrl) {
|
|
42
|
+
const name = readModuleName(metaUrl);
|
|
43
|
+
if (!name) {
|
|
44
|
+
throw new Error(`createModuleEntry: could not read 'name' from package.json near ${metaUrl}`);
|
|
45
|
+
}
|
|
46
|
+
return (config) => ({ name, config });
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Retrieves the module-specific configuration from the framework settings
|
|
50
|
+
* by matching the module's package name against the `modules` array.
|
|
51
|
+
*
|
|
52
|
+
* Modules that are registered as plain strings in the `modules` array
|
|
53
|
+
* (without config) will return an empty object.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* import { getModuleConfig } from 'zumito-framework';
|
|
58
|
+
*
|
|
59
|
+
* const config = getModuleConfig<MyConfig>(framework, import.meta.url);
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function getModuleConfig(framework, metaUrl) {
|
|
63
|
+
if (!framework)
|
|
64
|
+
return {};
|
|
65
|
+
const name = readModuleName(metaUrl);
|
|
66
|
+
if (!name)
|
|
67
|
+
return {};
|
|
68
|
+
const modules = framework.settings?.modules ?? [];
|
|
69
|
+
const entry = modules.find((m) => typeof m !== 'string' && m.name === name);
|
|
70
|
+
return (entry?.config ?? {});
|
|
71
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module parameters passed to the Module constructor.
|
|
3
|
+
* Includes base framework fields plus any module-specific config.
|
|
4
|
+
*/
|
|
1
5
|
export type ModuleParameters = {
|
|
6
|
+
path?: string;
|
|
2
7
|
commandWhitelist?: string[];
|
|
3
8
|
commandBlacklist?: string[];
|
|
4
|
-
commandRenames?:
|
|
5
|
-
|
|
6
|
-
};
|
|
9
|
+
commandRenames?: Record<string, string>;
|
|
10
|
+
[key: string]: any;
|
|
7
11
|
};
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import { ModuleParameters } from "../parameters/ModuleParameters";
|
|
2
1
|
import { StatusManagerOptions } from "../StatusManagerOptions";
|
|
3
2
|
import type { DatabaseConfig } from 'zumito-db';
|
|
3
|
+
/**
|
|
4
|
+
* A module entry returned by a module factory function like `adminModule()`.
|
|
5
|
+
* Provides typed configuration and optional path override.
|
|
6
|
+
*/
|
|
7
|
+
export interface ModuleEntry {
|
|
8
|
+
/** Package name or module identifier (e.g., '@zumito-team/admin-module'). */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Module-specific configuration. Typed by the factory function. */
|
|
11
|
+
config?: Record<string, any>;
|
|
12
|
+
/** Optional filesystem path override. Defaults to `require.resolve(name)`. */
|
|
13
|
+
path?: string;
|
|
14
|
+
}
|
|
4
15
|
export interface FrameworkSettings {
|
|
5
16
|
mongoQueryString?: string;
|
|
6
17
|
logLevel?: number;
|
|
@@ -18,10 +29,31 @@ export interface FrameworkSettings {
|
|
|
18
29
|
* @experimental
|
|
19
30
|
*/
|
|
20
31
|
srcMode?: 'multiBundle' | 'monoBundle' | undefined;
|
|
21
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Use `modules` instead.
|
|
34
|
+
*/
|
|
35
|
+
bundles?: (string | {
|
|
22
36
|
path: string;
|
|
23
|
-
options?:
|
|
24
|
-
}[];
|
|
37
|
+
options?: Record<string, any>;
|
|
38
|
+
})[];
|
|
39
|
+
/**
|
|
40
|
+
* Modules to load. Each entry is either a package name string or a
|
|
41
|
+
* `ModuleEntry` object returned by a module factory function (e.g., `adminModule({...})`).
|
|
42
|
+
*
|
|
43
|
+
* Strings are resolved via `require.resolve()`.
|
|
44
|
+
* Factory functions provide type-safe autocompletion for module-specific config.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { adminModule } from '@zumito-team/admin-module';
|
|
49
|
+
*
|
|
50
|
+
* modules: [
|
|
51
|
+
* adminModule({ colors: { primary: '#ff0000' } }),
|
|
52
|
+
* '@zumito-team/canvas-module',
|
|
53
|
+
* ]
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
modules?: (string | ModuleEntry)[];
|
|
25
57
|
webServer?: {
|
|
26
58
|
port?: number;
|
|
27
59
|
disableNotFoundHandler?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -41,5 +41,8 @@ export { ModalSubmitParameters } from './definitions/parameters/ModalSubmitParam
|
|
|
41
41
|
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
|
+
export { defineConfig } from './definitions/config/defineConfig.js';
|
|
45
|
+
export { createModuleEntry, getModuleConfig } from './definitions/config/moduleHelpers.js';
|
|
46
|
+
export type { ModuleEntry } from './definitions/settings/FrameworkSettings.js';
|
|
44
47
|
export { ModuleParameters } from './definitions/parameters/ModuleParameters.js';
|
|
45
48
|
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, };
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,8 @@ import { CommandExecutionChecker } from './services/CommandExecutionChecker.js';
|
|
|
28
28
|
import { DatabaseManager } from 'zumito-db';
|
|
29
29
|
export { Collection, Field, HasMany, BelongsTo, HasOne, Migration, Repository, QueryBuilder } from 'zumito-db';
|
|
30
30
|
export { Injectable } from './definitions/decorators/Injectable.decorator.js';
|
|
31
|
+
export { defineConfig } from './definitions/config/defineConfig.js';
|
|
32
|
+
export { createModuleEntry, getModuleConfig } from './definitions/config/moduleHelpers.js';
|
|
31
33
|
ServiceContainer.addService(TextFormatter, []);
|
|
32
34
|
ServiceContainer.addService(EmojiFallback, [discord.Client.name, TranslationManager.name]);
|
|
33
35
|
ServiceContainer.addService(GuildDataGetter, [ZumitoFramework.name]);
|
package/dist/launcher.js
CHANGED
|
@@ -29,7 +29,12 @@ if (!fs.existsSync(configFilePath)) {
|
|
|
29
29
|
process.exit(1);
|
|
30
30
|
}
|
|
31
31
|
import(pathToFileURL(configFilePath).href)
|
|
32
|
-
.then((
|
|
32
|
+
.then((mod) => {
|
|
33
|
+
const userConfig = mod.config ?? mod.default;
|
|
34
|
+
if (!userConfig) {
|
|
35
|
+
console.error(`Config file at ${configFilePath} must export 'config' (named) or 'default' (default export).`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
33
38
|
const config = RecursiveObjectMerger.merge(defaultConfig, userConfig);
|
|
34
39
|
new ZumitoFramework(config, (bot) => {
|
|
35
40
|
BotReadyLogger.log(bot);
|
|
@@ -42,6 +42,8 @@ export class CommandManager {
|
|
|
42
42
|
if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
|
+
if (filePath.endsWith('.d.ts'))
|
|
46
|
+
return;
|
|
45
47
|
const counter = (this.importCounters.get(filePath) || 0) + 1;
|
|
46
48
|
this.importCounters.set(filePath, counter);
|
|
47
49
|
const baseName = path.basename(filePath).split('.').slice(0, -1).join('.');
|
|
@@ -62,6 +64,7 @@ export class CommandManager {
|
|
|
62
64
|
return command;
|
|
63
65
|
}
|
|
64
66
|
catch (error) {
|
|
67
|
+
console.error('[🆕🔴 ] Error instanciating command ' + chalk.blue(baseName) + ' from ' + filePath);
|
|
65
68
|
this.errorHandler.handleError(error, {
|
|
66
69
|
type: ErrorType.CommandInstance,
|
|
67
70
|
command: command,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zumito-framework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"description": "Discord.js bot framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"source-fragment": "^1.1.0",
|
|
43
43
|
"tingodb": "^0.6.1",
|
|
44
44
|
"tseep": "^1.2.2",
|
|
45
|
-
"zumito-db": "^2.0.
|
|
45
|
+
"zumito-db": "^2.0.4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^22.0.0",
|