zumito-framework 1.24.0 → 1.25.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.
@@ -25,6 +25,7 @@ import { ErrorType } from './definitions/ErrorType.js';
25
25
  import { MongoService } from './services/MongoService.js';
26
26
  import { registerDefaultExecutionRules } from './modules/core/baseModule/defaultRules.js';
27
27
  import { DatabaseManager } from 'zumito-db';
28
+ import { registerFrameworkInspector, startInspectorFileWriter } from './utils/Inspector.js';
28
29
  // import better-logging
29
30
  betterLogging(console);
30
31
  /**
@@ -148,6 +149,7 @@ export class ZumitoFramework {
148
149
  ServiceContainer.addService(CommandManager, [], true, this.commands);
149
150
  ServiceContainer.addService(EventManager, [], true, this.eventManager);
150
151
  ServiceContainer.addService(SlashCommandRefresher, [], true, new SlashCommandRefresher(this));
152
+ registerFrameworkInspector(this);
151
153
  if (settings.logLevel) {
152
154
  console.logLevel = settings.logLevel;
153
155
  }
@@ -155,6 +157,7 @@ export class ZumitoFramework {
155
157
  .then(() => {
156
158
  if (callback)
157
159
  callback(this);
160
+ startInspectorFileWriter(this);
158
161
  })
159
162
  .catch((err) => {
160
163
  console.error(err, err.message, err.stack, err.name);
@@ -188,7 +191,7 @@ export class ZumitoFramework {
188
191
  }
189
192
  }
190
193
  async initializeDatabase() {
191
- const mongoUri = this.settings?.mongoQueryString || process.env.MONGO_URI;
194
+ const mongoUri = this.settings?.mongoQueryString || process.env.DATABASE_URI;
192
195
  const dbSettings = this.settings.database;
193
196
  let config;
194
197
  if (dbSettings?.default) {
@@ -208,7 +211,7 @@ export class ZumitoFramework {
208
211
  else {
209
212
  console.error('[🗄️🔴] No database configured.');
210
213
  console.error(' Set database.default in zumito.config.ts (memory, tingo, mongo, sqlite)');
211
- console.error(' or set MONGO_URI / mongoQueryString for MongoDB.');
214
+ console.error(' or set DATABASE_URI / mongoQueryString for MongoDB.');
212
215
  process.exit(1);
213
216
  }
214
217
  if (this.settings.models) {
@@ -5,6 +5,12 @@ declare class ServiceContainerManager {
5
5
  getServiceByName<T>(serviceName: string): T;
6
6
  addInstance(serviceClass: any, instance: any): void;
7
7
  hasService(serviceClass: any): boolean;
8
+ getAllServiceEntries(): Array<{
9
+ name: string;
10
+ dependencies: string[];
11
+ singleton: boolean;
12
+ hasInstance: boolean;
13
+ }>;
8
14
  }
9
15
  export declare const ServiceContainer: ServiceContainerManager;
10
16
  export {};
@@ -62,6 +62,18 @@ class ServiceContainerManager {
62
62
  const serviceName = typeof serviceClass == 'string' ? serviceClass : serviceClass.name;
63
63
  return this.services.has(serviceName);
64
64
  }
65
+ getAllServiceEntries() {
66
+ const entries = [];
67
+ for (const [name, svc] of this.services) {
68
+ entries.push({
69
+ name,
70
+ dependencies: svc.dependencies,
71
+ singleton: svc.singleton,
72
+ hasInstance: svc.instance !== undefined,
73
+ });
74
+ }
75
+ return entries;
76
+ }
65
77
  }
66
78
  if (!global.ServiceContainer)
67
79
  global.ServiceContainer = new ServiceContainerManager();
@@ -0,0 +1,61 @@
1
+ import { ZumitoFramework } from '../ZumitoFramework.js';
2
+ export interface FrameworkSnapshot {
3
+ version: string;
4
+ uptime: number;
5
+ discord: {
6
+ status: 'connected' | 'disconnected';
7
+ user: {
8
+ id: string;
9
+ tag: string;
10
+ } | null;
11
+ guildCount: number;
12
+ };
13
+ database: {
14
+ connected: boolean;
15
+ driver: string;
16
+ };
17
+ commands: {
18
+ total: number;
19
+ items: Array<{
20
+ name: string;
21
+ type: string;
22
+ description: string;
23
+ aliases: string[];
24
+ categories: string[];
25
+ hidden: boolean;
26
+ }>;
27
+ };
28
+ modules: {
29
+ total: number;
30
+ items: Array<{
31
+ name: string;
32
+ displayName: string;
33
+ status: string;
34
+ dependencies: string[];
35
+ commandCount: number;
36
+ eventCount: number;
37
+ }>;
38
+ };
39
+ services: {
40
+ total: number;
41
+ items: Array<{
42
+ name: string;
43
+ singleton: boolean;
44
+ hasInstance: boolean;
45
+ dependencies: string[];
46
+ }>;
47
+ };
48
+ events: {
49
+ total: number;
50
+ items: Array<{
51
+ name: string;
52
+ source: string;
53
+ }>;
54
+ };
55
+ }
56
+ /**
57
+ * Write the inspector snapshot to .zumito/inspector-state.json in the current
58
+ * working directory. Returns a cleanup function that stops the write interval.
59
+ */
60
+ export declare function startInspectorFileWriter(framework: ZumitoFramework): () => void;
61
+ export declare function registerFrameworkInspector(framework: ZumitoFramework): void;
@@ -0,0 +1,194 @@
1
+ import { createRequire } from 'module';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { ServiceContainer } from '../services/ServiceContainer.js';
5
+ const require = createRequire(import.meta.url);
6
+ /**
7
+ * Write the inspector snapshot to .zumito/inspector-state.json in the current
8
+ * working directory. Returns a cleanup function that stops the write interval.
9
+ */
10
+ export function startInspectorFileWriter(framework) {
11
+ const startTime = Date.now();
12
+ let pkg = {};
13
+ try {
14
+ pkg = require('../../package.json');
15
+ }
16
+ catch { /* ignore */ }
17
+ let lastJson = '';
18
+ let timer;
19
+ const write = () => {
20
+ const state = {
21
+ version: pkg.version || 'unknown',
22
+ uptime: Date.now() - startTime,
23
+ discord: {
24
+ status: framework.client?.isReady() ? 'connected' : 'disconnected',
25
+ user: framework.client?.user
26
+ ? { id: framework.client.user.id, tag: framework.client.user.tag }
27
+ : null,
28
+ guildCount: framework.client?.guilds?.cache?.size ?? 0,
29
+ },
30
+ database: {
31
+ connected: !!framework.db,
32
+ driver: framework.db ? getDriverName(framework) : 'none',
33
+ },
34
+ commands: serializeCommands(framework),
35
+ modules: serializeModules(framework),
36
+ services: serializeServices(),
37
+ events: serializeEvents(framework),
38
+ };
39
+ const json = JSON.stringify(state);
40
+ if (json === lastJson) {
41
+ return;
42
+ }
43
+ lastJson = json;
44
+ try {
45
+ const dir = path.join(process.cwd(), '.zumito');
46
+ if (!fs.existsSync(dir)) {
47
+ fs.mkdirSync(dir, { recursive: true });
48
+ }
49
+ fs.writeFileSync(path.join(dir, 'inspector-state.json'), json, 'utf-8');
50
+ }
51
+ catch {
52
+ // can't write – silently ignore
53
+ }
54
+ };
55
+ // Write immediately, then every 3s
56
+ write();
57
+ timer = setInterval(write, 3000);
58
+ return () => {
59
+ if (timer) {
60
+ clearInterval(timer);
61
+ timer = undefined;
62
+ }
63
+ };
64
+ }
65
+ export function registerFrameworkInspector(framework) {
66
+ const startTime = Date.now();
67
+ let pkg = {};
68
+ try {
69
+ pkg = require('../../package.json');
70
+ }
71
+ catch {
72
+ // fallback if package.json can't be read
73
+ }
74
+ const inspector = {
75
+ getSnapshot() {
76
+ const state = {
77
+ version: pkg.version || 'unknown',
78
+ uptime: Date.now() - startTime,
79
+ discord: {
80
+ status: framework.client?.isReady() ? 'connected' : 'disconnected',
81
+ user: framework.client?.user
82
+ ? { id: framework.client.user.id, tag: framework.client.user.tag }
83
+ : null,
84
+ guildCount: framework.client?.guilds?.cache?.size ?? 0,
85
+ },
86
+ database: {
87
+ connected: !!framework.db,
88
+ driver: framework.db ? getDriverName(framework) : 'none',
89
+ },
90
+ commands: serializeCommands(framework),
91
+ modules: serializeModules(framework),
92
+ services: serializeServices(),
93
+ events: serializeEvents(framework),
94
+ };
95
+ return JSON.stringify(state);
96
+ },
97
+ getCommands() {
98
+ return JSON.stringify(serializeCommands(framework));
99
+ },
100
+ getModules() {
101
+ return JSON.stringify(serializeModules(framework));
102
+ },
103
+ getServices() {
104
+ return JSON.stringify(serializeServices());
105
+ },
106
+ getEvents() {
107
+ return JSON.stringify(serializeEvents(framework));
108
+ },
109
+ };
110
+ try {
111
+ globalThis.__ZUMITO_INSPECT__ = inspector;
112
+ }
113
+ catch {
114
+ // globalThis not available (non-Node environment?)
115
+ }
116
+ }
117
+ function getDriverName(framework) {
118
+ try {
119
+ const driver = framework.db.getDriver?.();
120
+ if (driver) {
121
+ return driver.constructor?.name || 'custom';
122
+ }
123
+ }
124
+ catch {
125
+ // ignore
126
+ }
127
+ return 'unknown';
128
+ }
129
+ function serializeCommands(framework) {
130
+ const items = [];
131
+ const allCommands = framework.commands?.getAll();
132
+ if (allCommands) {
133
+ for (const [, cmd] of allCommands) {
134
+ items.push({
135
+ name: cmd.name,
136
+ type: cmd.type || 'any',
137
+ description: cmd.description || '',
138
+ aliases: cmd.aliases || [],
139
+ categories: cmd.categories || [],
140
+ hidden: cmd.hidden === true,
141
+ });
142
+ }
143
+ }
144
+ return { total: items.length, items };
145
+ }
146
+ function serializeModules(framework) {
147
+ const items = [];
148
+ const allModules = framework.modules?.getAll();
149
+ if (allModules) {
150
+ for (const [name, mod] of allModules) {
151
+ const modClass = Object.getPrototypeOf(mod)?.constructor;
152
+ items.push({
153
+ name,
154
+ displayName: modClass?.moduleName || name,
155
+ status: 'loaded',
156
+ dependencies: Array.from(modClass?.dependencies || []),
157
+ commandCount: mod.getCommands?.()?.size ?? 0,
158
+ eventCount: mod.events?.size ?? 0,
159
+ });
160
+ }
161
+ }
162
+ return { total: items.length, items };
163
+ }
164
+ function serializeServices() {
165
+ const items = [];
166
+ try {
167
+ const entries = ServiceContainer.getAllServiceEntries();
168
+ for (const entry of entries) {
169
+ items.push({
170
+ name: entry.name,
171
+ singleton: entry.singleton,
172
+ hasInstance: entry.hasInstance,
173
+ dependencies: entry.dependencies,
174
+ });
175
+ }
176
+ }
177
+ catch {
178
+ // service container not ready
179
+ }
180
+ return { total: items.length, items };
181
+ }
182
+ function serializeEvents(framework) {
183
+ const items = [];
184
+ const allEvents = framework.events;
185
+ if (allEvents) {
186
+ for (const [, evt] of allEvents) {
187
+ items.push({
188
+ name: evt.name || 'unknown',
189
+ source: evt.source || evt.emitter || 'framework',
190
+ });
191
+ }
192
+ }
193
+ return { total: items.length, items };
194
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zumito-framework",
3
- "version": "1.24.0",
3
+ "version": "1.25.0",
4
4
  "description": "Discord.js bot framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",