zumito-framework 1.23.1 → 1.23.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.
@@ -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,16 +318,41 @@ 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
- moduleEntries.push({
323
- rootPath: bundle.path,
324
- options: bundle.options,
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({
329
- rootPath: path.join(__dirname, 'modules', 'core'),
355
+ rootPath: path.join(__dirname, 'modules', 'core', 'baseModule'),
330
356
  name: 'baseModule',
331
357
  });
332
358
  if (fs.existsSync(`${process.cwd()}/node_modules/.zumitoBundles`)) {
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * @deprecated
3
3
  */
4
- export { FrameworkSettings } from "./settings/FrameworkSettings";
4
+ export { FrameworkSettings, ModuleEntry } from "./settings/FrameworkSettings";
@@ -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();
@@ -92,7 +94,9 @@ export class Module {
92
94
  client: this.framework.client,
93
95
  };
94
96
  args.forEach((arg) => {
95
- finalArgs[arg.constructor.name.toLowerCase()] = arg;
97
+ if (arg && arg.constructor) {
98
+ finalArgs[arg.constructor.name.toLowerCase()] = arg;
99
+ }
96
100
  });
97
101
  const interaction = args.find((arg) => arg instanceof StringSelectMenuInteraction ||
98
102
  arg instanceof CommandInteraction ||
@@ -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
+ }
@@ -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
- [key: string]: string;
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
- bundles?: {
32
+ /**
33
+ * @deprecated Use `modules` instead.
34
+ */
35
+ bundles?: (string | {
22
36
  path: string;
23
- options?: ModuleParameters;
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,7 @@ 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 type { ModuleEntry } from './definitions/settings/FrameworkSettings.js';
44
46
  export { ModuleParameters } from './definitions/parameters/ModuleParameters.js';
45
47
  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,7 @@ 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';
31
32
  ServiceContainer.addService(TextFormatter, []);
32
33
  ServiceContainer.addService(EmojiFallback, [discord.Client.name, TranslationManager.name]);
33
34
  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(({ config: userConfig }) => {
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);
@@ -0,0 +1,4 @@
1
+ import { Module } from '../../../definitions/Module.js';
2
+ export declare class BaseModule extends Module {
3
+ initialize(): Promise<void>;
4
+ }
@@ -0,0 +1,6 @@
1
+ import { Module } from '../../../definitions/Module.js';
2
+ export class BaseModule extends Module {
3
+ async initialize() {
4
+ await super.initialize();
5
+ }
6
+ }
@@ -62,6 +62,7 @@ export class CommandManager {
62
62
  return command;
63
63
  }
64
64
  catch (error) {
65
+ console.error('[🆕🔴 ] Error instanciating command ' + chalk.blue(baseName) + ' from ' + filePath);
65
66
  this.errorHandler.handleError(error, {
66
67
  type: ErrorType.CommandInstance,
67
68
  command: command,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zumito-framework",
3
- "version": "1.23.1",
3
+ "version": "1.23.3",
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.3"
45
+ "zumito-db": "^2.0.4"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^22.0.0",