conduithub 0.0.3 → 1.0.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.
Files changed (68) hide show
  1. package/dist/core/conduit-hub/index.cjs +188 -0
  2. package/dist/core/conduit-hub/index.d.cts +44 -0
  3. package/dist/core/conduit-hub/index.d.mts +44 -0
  4. package/dist/core/conduit-hub/index.d.ts +44 -0
  5. package/dist/core/conduit-hub/index.mjs +186 -0
  6. package/dist/core/config-manager/index.cjs +216 -0
  7. package/dist/core/config-manager/index.d.cts +7 -0
  8. package/dist/core/config-manager/index.d.mts +7 -0
  9. package/dist/core/config-manager/index.d.ts +7 -0
  10. package/dist/core/config-manager/index.mjs +214 -0
  11. package/dist/core/event-bus/index.cjs +154 -53
  12. package/dist/core/event-bus/index.d.cts +2 -42
  13. package/dist/core/event-bus/index.d.mts +2 -42
  14. package/dist/core/event-bus/index.d.ts +2 -42
  15. package/dist/core/event-bus/index.mjs +153 -52
  16. package/dist/core/hook/index.cjs +185 -148
  17. package/dist/core/hook/index.d.cts +28 -16
  18. package/dist/core/hook/index.d.mts +28 -16
  19. package/dist/core/hook/index.d.ts +28 -16
  20. package/dist/core/hook/index.mjs +183 -146
  21. package/dist/core/index.cjs +17 -1
  22. package/dist/core/index.d.cts +184 -3
  23. package/dist/core/index.d.mts +184 -3
  24. package/dist/core/index.d.ts +184 -3
  25. package/dist/core/index.mjs +12 -1
  26. package/dist/core/plugin/index.cjs +271 -0
  27. package/dist/core/plugin/index.d.cts +7 -0
  28. package/dist/core/plugin/index.d.mts +7 -0
  29. package/dist/core/plugin/index.d.ts +7 -0
  30. package/dist/core/plugin/index.mjs +268 -0
  31. package/dist/core/service-container/index.cjs +306 -0
  32. package/dist/core/service-container/index.d.cts +51 -0
  33. package/dist/core/service-container/index.d.mts +51 -0
  34. package/dist/core/service-container/index.d.ts +51 -0
  35. package/dist/core/service-container/index.mjs +304 -0
  36. package/dist/core/state-manager/index.cjs +195 -0
  37. package/dist/core/state-manager/index.d.cts +39 -0
  38. package/dist/core/state-manager/index.d.mts +39 -0
  39. package/dist/core/state-manager/index.d.ts +39 -0
  40. package/dist/core/state-manager/index.mjs +193 -0
  41. package/dist/index.cjs +34 -5
  42. package/dist/index.d.cts +54 -2
  43. package/dist/index.d.mts +54 -2
  44. package/dist/index.d.ts +54 -2
  45. package/dist/index.mjs +13 -1
  46. package/dist/shared/conduithub.BDwZXllF.mjs +63 -0
  47. package/dist/shared/{conduithub.CvMLTa-R.cjs → conduithub.BNQsddJO.cjs} +2 -9
  48. package/dist/shared/{conduithub.74V0wiLi.mjs → conduithub.BNefRQsK.mjs} +3 -9
  49. package/dist/shared/conduithub.BZQmkQy7.d.cts +52 -0
  50. package/dist/shared/conduithub.BqUYv04j.cjs +68 -0
  51. package/dist/shared/conduithub.Bq_7Xj0J.cjs +18 -0
  52. package/dist/shared/conduithub.BzLwccre.d.mts +52 -0
  53. package/dist/shared/conduithub.CkOQG3cD.mjs +14 -0
  54. package/dist/shared/conduithub.CmZo_Vuc.cjs +38 -0
  55. package/dist/shared/conduithub.DQO1dRnn.cjs +33 -0
  56. package/dist/shared/conduithub.DQOWQ-Bx.d.ts +52 -0
  57. package/dist/shared/conduithub.DsOOeNwU.cjs +269 -0
  58. package/dist/shared/conduithub.DyQQrHW9.mjs +267 -0
  59. package/dist/shared/conduithub.G7ICpZIy.mjs +36 -0
  60. package/dist/shared/conduithub.alPiaJax.mjs +29 -0
  61. package/dist/shared/conduithub.bsiNMTVD.mjs +59 -0
  62. package/dist/shared/conduithub.gF2DFc43.cjs +76 -0
  63. package/dist/utils/index.cjs +18 -5
  64. package/dist/utils/index.d.cts +33 -2
  65. package/dist/utils/index.d.mts +33 -2
  66. package/dist/utils/index.d.ts +33 -2
  67. package/dist/utils/index.mjs +7 -1
  68. package/package.json +52 -1
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ class ConduithubError extends Error {
4
+ code;
5
+ details;
6
+ timestamp;
7
+ constructor(message, context) {
8
+ super(message);
9
+ this.name = "ConduithubError";
10
+ this.code = context?.code;
11
+ this.details = context?.details;
12
+ this.timestamp = context?.timestamp ?? Date.now();
13
+ Error.captureStackTrace?.(this, ConduithubError);
14
+ }
15
+ toJSON() {
16
+ return {
17
+ name: this.name,
18
+ message: this.message,
19
+ code: this.code,
20
+ details: this.details,
21
+ timestamp: this.timestamp,
22
+ stack: this.stack
23
+ };
24
+ }
25
+ }
26
+ class PackageManagerRegistry {
27
+ manager = "";
28
+ set(manager) {
29
+ if (!this.isValidManager(manager)) {
30
+ throw new ConduithubError(`Invalid package manager: ${manager}`, {
31
+ code: "INVALID_PACKAGE_MANAGER",
32
+ details: { manager, validManagers: ["npm", "pnpm", "yarn", "bun"] }
33
+ });
34
+ }
35
+ this.manager = manager;
36
+ }
37
+ get() {
38
+ return this.manager;
39
+ }
40
+ isValidManager(manager) {
41
+ return ["npm", "pnpm", "yarn", "bun"].includes(manager);
42
+ }
43
+ }
44
+ const packageManagerRegistry = new PackageManagerRegistry();
45
+ function setPkgManager(manager) {
46
+ packageManagerRegistry.set(manager);
47
+ }
48
+ function getPkgManager() {
49
+ return packageManagerRegistry.get();
50
+ }
51
+ class MissingDependencyError extends ConduithubError {
52
+ constructor(pkgName) {
53
+ const manager = getPkgManager() || "npm";
54
+ const message = `The package ${pkgName} is missing from the dependencies. Please install it using "${manager} add ${pkgName}"`;
55
+ super(message, {
56
+ code: "MISSING_DEPENDENCY",
57
+ details: {
58
+ packageName: pkgName,
59
+ suggestedCommand: `${manager} add ${pkgName}`
60
+ }
61
+ });
62
+ }
63
+ }
64
+
65
+ exports.ConduithubError = ConduithubError;
66
+ exports.MissingDependencyError = MissingDependencyError;
67
+ exports.getPkgManager = getPkgManager;
68
+ exports.setPkgManager = setPkgManager;
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ const uuid = require('uuid');
4
+
5
+ function generateUuid() {
6
+ return uuid.v4();
7
+ }
8
+ function generateShortId() {
9
+ return generateUuid().split("-")[0];
10
+ }
11
+ function isValidUuid(value) {
12
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
13
+ return uuidRegex.test(value);
14
+ }
15
+
16
+ exports.generateShortId = generateShortId;
17
+ exports.generateUuid = generateUuid;
18
+ exports.isValidUuid = isValidUuid;
@@ -0,0 +1,52 @@
1
+ import { a as Logger } from './conduithub.B7aryjPG.mjs';
2
+
3
+ interface EventData<T extends string, P> {
4
+ type: T;
5
+ payload: P;
6
+ timestamp: number;
7
+ source: string;
8
+ context?: Record<string, unknown>;
9
+ }
10
+
11
+ interface EventBusOptions<EM extends Record<string, unknown>> {
12
+ readonly logger?: Logger;
13
+ readonly maxHandlersPerEvent?: number;
14
+ readonly handlerTimeoutMs?: number;
15
+ readonly onError?: (err: unknown, eventType: keyof EM) => void;
16
+ }
17
+ interface EventBusStats<EM extends Record<string, unknown>> {
18
+ readonly totalEvents: number;
19
+ readonly totalListeners: number;
20
+ readonly eventNames: (keyof EM)[];
21
+ readonly listenerCount: Record<keyof EM, number>;
22
+ }
23
+ declare class EventBus<EM extends Record<string, unknown>> {
24
+ private readonly handlers;
25
+ private readonly locks;
26
+ private initialized;
27
+ private readonly logger;
28
+ private readonly maxHandlersPerEvent;
29
+ private readonly handlerTimeoutMs;
30
+ private readonly onError?;
31
+ constructor(options?: EventBusOptions<EM>);
32
+ private withEventLock;
33
+ private ensureInitialized;
34
+ private sanitizeLog;
35
+ initialize(): Promise<void>;
36
+ shutdown(): Promise<void>;
37
+ private getTotalHandlerCount;
38
+ private clearAllHandlers;
39
+ on<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>, context?: Record<string, unknown>, signal?: AbortSignal) => Promise<void> | void, priority?: number, customId?: string): string;
40
+ once<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>, context?: Record<string, unknown>, signal?: AbortSignal) => Promise<void> | void, priority?: number, customId?: string): string;
41
+ private registerHandler;
42
+ off<K extends keyof EM>(type: K, id?: string): void;
43
+ emit<K extends keyof EM>(type: K, payload: EM[K], source?: string, context?: Record<string, unknown>): Promise<void>;
44
+ removeAllListeners<K extends keyof EM>(type?: K): void;
45
+ listenerCount<K extends keyof EM>(type: K): number;
46
+ eventNames(): Array<keyof EM>;
47
+ getStats(): EventBusStats<EM>;
48
+ get isInitialized(): boolean;
49
+ }
50
+
51
+ export { EventBus as E };
52
+ export type { EventData as a };
@@ -0,0 +1,14 @@
1
+ import { v4 } from 'uuid';
2
+
3
+ function generateUuid() {
4
+ return v4();
5
+ }
6
+ function generateShortId() {
7
+ return generateUuid().split("-")[0];
8
+ }
9
+ function isValidUuid(value) {
10
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
11
+ return uuidRegex.test(value);
12
+ }
13
+
14
+ export { generateShortId as a, generateUuid as g, isValidUuid as i };
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const ERROR_CODE = {
4
+ // Configuration errors
5
+ INVALID_JSON: "Invalid JSON format",
6
+ INVALID_CONFIG: "Configuration validation failed",
7
+ UNSUPPORTED_CONFIG_FORMAT: "JavaScript config files are not supported. Use JSON format.",
8
+ // Initialization errors
9
+ STATE_MANAGER_NOT_INITIALIZED: "StateManager is not initialized",
10
+ SERVICE_CONTAINER_NOT_INITIALIZED: "Service Container is not initialized",
11
+ EVENT_BUS_NOT_INITIALIZED: "EventBus is not initialized",
12
+ HOOK_SYSTEM_NOT_INITIALIZED: "Hook system is not initialized",
13
+ // Handler limit errors
14
+ EVENT_HANDLER_LIMIT_EXCEEDED: "Handler limit exceeded for event",
15
+ HOOK_HANDLER_LIMIT_EXCEEDED: "Handler limit exceeded for hook",
16
+ // Duplicate ID errors
17
+ DUPLICATE_EVENT_HANDLER_ID: "Duplicate custom ID for event",
18
+ DUPLICATE_HOOK_HANDLER_ID: "Duplicate custom ID for hook",
19
+ // State management errors
20
+ INVALID_STATE_JSON_FORMAT: "Invalid state JSON format",
21
+ // Execution errors
22
+ HOOK_EXECUTION_FAILED: "Hook execution failed",
23
+ UNKNOWN_ERROR: "Unknown error",
24
+ // Service container errors
25
+ CIRCULAR_DEPENDENCY_DETECTED: "Circular dependency detected",
26
+ SERVICE_NOT_FOUND: "Service not found",
27
+ SERVICE_CREATION_FAILED: "Service creation failed",
28
+ SERVICE_IS_SINGLETON: "Service is a singleton and cannot be registered again",
29
+ // Plugin errors
30
+ PLUGIN_NOT_INITIALIZED: "Plugin is not initialized",
31
+ PLUGIN_ALREADY_INITIALIZED: "Plugin is already initialized",
32
+ PLUGIN_NOT_RUNNING: "Plugin is not running",
33
+ // ConfigManager errors
34
+ CONFIG_MANAGER_NOT_INITIALIZED: "ConfigManager is not initialized",
35
+ CONFIG_MANAGER_ALREADY_INITIALIZED: "ConfigManager is already initialized"
36
+ };
37
+
38
+ exports.ERROR_CODE = ERROR_CODE;
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ const ISO8601_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
4
+ function parseJson(data) {
5
+ try {
6
+ return JSON.parse(data, dateReviver);
7
+ } catch {
8
+ return null;
9
+ }
10
+ }
11
+ function stringifyJson(value, replacer, space) {
12
+ return JSON.stringify(value, replacer, space);
13
+ }
14
+ function safeStringifyJson(value) {
15
+ try {
16
+ return JSON.stringify(value);
17
+ } catch {
18
+ return "[Circular or Non-Serializable Object]";
19
+ }
20
+ }
21
+ function dateReviver(_, value) {
22
+ if (typeof value === "string" && ISO8601_REGEX.test(value)) {
23
+ const date = new Date(value);
24
+ if (!Number.isNaN(date.getTime())) {
25
+ return date;
26
+ }
27
+ }
28
+ return value;
29
+ }
30
+
31
+ exports.parseJson = parseJson;
32
+ exports.safeStringifyJson = safeStringifyJson;
33
+ exports.stringifyJson = stringifyJson;
@@ -0,0 +1,52 @@
1
+ import { a as Logger } from './conduithub.B7aryjPG.js';
2
+
3
+ interface EventData<T extends string, P> {
4
+ type: T;
5
+ payload: P;
6
+ timestamp: number;
7
+ source: string;
8
+ context?: Record<string, unknown>;
9
+ }
10
+
11
+ interface EventBusOptions<EM extends Record<string, unknown>> {
12
+ readonly logger?: Logger;
13
+ readonly maxHandlersPerEvent?: number;
14
+ readonly handlerTimeoutMs?: number;
15
+ readonly onError?: (err: unknown, eventType: keyof EM) => void;
16
+ }
17
+ interface EventBusStats<EM extends Record<string, unknown>> {
18
+ readonly totalEvents: number;
19
+ readonly totalListeners: number;
20
+ readonly eventNames: (keyof EM)[];
21
+ readonly listenerCount: Record<keyof EM, number>;
22
+ }
23
+ declare class EventBus<EM extends Record<string, unknown>> {
24
+ private readonly handlers;
25
+ private readonly locks;
26
+ private initialized;
27
+ private readonly logger;
28
+ private readonly maxHandlersPerEvent;
29
+ private readonly handlerTimeoutMs;
30
+ private readonly onError?;
31
+ constructor(options?: EventBusOptions<EM>);
32
+ private withEventLock;
33
+ private ensureInitialized;
34
+ private sanitizeLog;
35
+ initialize(): Promise<void>;
36
+ shutdown(): Promise<void>;
37
+ private getTotalHandlerCount;
38
+ private clearAllHandlers;
39
+ on<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>, context?: Record<string, unknown>, signal?: AbortSignal) => Promise<void> | void, priority?: number, customId?: string): string;
40
+ once<K extends keyof EM>(type: K, handler: (event: EventData<K & string, EM[K]>, context?: Record<string, unknown>, signal?: AbortSignal) => Promise<void> | void, priority?: number, customId?: string): string;
41
+ private registerHandler;
42
+ off<K extends keyof EM>(type: K, id?: string): void;
43
+ emit<K extends keyof EM>(type: K, payload: EM[K], source?: string, context?: Record<string, unknown>): Promise<void>;
44
+ removeAllListeners<K extends keyof EM>(type?: K): void;
45
+ listenerCount<K extends keyof EM>(type: K): number;
46
+ eventNames(): Array<keyof EM>;
47
+ getStats(): EventBusStats<EM>;
48
+ get isInitialized(): boolean;
49
+ }
50
+
51
+ export { EventBus as E };
52
+ export type { EventData as a };
@@ -0,0 +1,269 @@
1
+ 'use strict';
2
+
3
+ class PluginManager {
4
+ constructor(eventBus, logger, serviceContainer, stateManager, hookSystem, configManager) {
5
+ this.eventBus = eventBus;
6
+ this.logger = logger;
7
+ this.serviceContainer = serviceContainer;
8
+ this.stateManager = stateManager;
9
+ this.hookSystem = hookSystem;
10
+ this.configManager = configManager;
11
+ }
12
+ plugins = /* @__PURE__ */ new Map();
13
+ pluginStatuses = /* @__PURE__ */ new Map();
14
+ pluginConfigs = /* @__PURE__ */ new Map();
15
+ log(level, message, ...args) {
16
+ const l = this.logger;
17
+ if (l && typeof l.log === "function") {
18
+ l.log(level, message, ...args);
19
+ return;
20
+ }
21
+ const anyLogger = l;
22
+ const fn = anyLogger?.[level];
23
+ if (typeof fn === "function") fn(message, ...args);
24
+ }
25
+ async registerPlugin(plugin, config) {
26
+ const pluginName = plugin.constructor.name;
27
+ if (this.plugins.has(pluginName)) {
28
+ throw new Error(`Plugin ${pluginName} already registered`);
29
+ }
30
+ try {
31
+ const existing = this.pluginConfigs.get(pluginName) ?? await this.configManager.getPluginConfig(pluginName);
32
+ const metaVersion = plugin.getMetadata().version;
33
+ const pluginConfig = {
34
+ name: pluginName,
35
+ version: config?.version ?? existing?.version ?? metaVersion,
36
+ enabled: config?.enabled ?? existing?.enabled ?? true,
37
+ dependencies: config?.dependencies ?? existing?.dependencies ?? [],
38
+ config: { ...existing?.config ?? {}, ...config?.config ?? {} }
39
+ };
40
+ plugin.updateConfig(pluginConfig);
41
+ this.plugins.set(pluginName, plugin);
42
+ this.pluginConfigs.set(pluginName, pluginConfig);
43
+ this.pluginStatuses.set(pluginName, {
44
+ name: pluginName,
45
+ version: pluginConfig.version,
46
+ status: "registered",
47
+ config: pluginConfig,
48
+ lastActivity: Date.now()
49
+ });
50
+ this.log("info", `Plugin ${pluginName} registered successfully`);
51
+ await this.hookSystem.executeHook("plugin:registered", {
52
+ plugin: pluginName,
53
+ config: pluginConfig
54
+ });
55
+ await this.eventBus.emit("plugin:registered", {
56
+ plugin: pluginName,
57
+ config: pluginConfig
58
+ });
59
+ } catch (error) {
60
+ this.log("error", `Failed to register plugin ${pluginName}`, error);
61
+ throw error;
62
+ }
63
+ }
64
+ async unregisterPlugin(pluginName) {
65
+ const plugin = this.plugins.get(pluginName);
66
+ if (!plugin) {
67
+ throw new Error(`Plugin ${pluginName} is not registered`);
68
+ }
69
+ try {
70
+ if (plugin.isPluginRunning()) {
71
+ await this.stopPlugin(pluginName);
72
+ }
73
+ if (plugin.isPluginInitialized()) {
74
+ await plugin.destroy();
75
+ }
76
+ this.plugins.delete(pluginName);
77
+ this.pluginConfigs.delete(pluginName);
78
+ this.pluginStatuses.delete(pluginName);
79
+ this.log("info", `Plugin ${pluginName} unregistered successfully`);
80
+ await this.eventBus.emit("plugin:unregistered", {
81
+ plugin: pluginName
82
+ });
83
+ await this.hookSystem.executeHook("plugin:unregistered", {
84
+ plugin: pluginName
85
+ });
86
+ } catch (error) {
87
+ this.log("error", `Failed to unregister plugin ${pluginName}`, error);
88
+ throw error;
89
+ }
90
+ }
91
+ async initializePlugin(pluginName) {
92
+ const plugin = this.plugins.get(pluginName);
93
+ if (!plugin) {
94
+ throw new Error(`Plugin ${pluginName} is not registered`);
95
+ }
96
+ const status = this.pluginStatuses.get(pluginName);
97
+ if (status?.status === "initialized" || status?.status === "running") {
98
+ return;
99
+ }
100
+ try {
101
+ const context = {
102
+ eventBus: this.eventBus,
103
+ logger: this.logger,
104
+ config: this.pluginConfigs.get(pluginName),
105
+ serviceContainer: this.serviceContainer,
106
+ stateManager: this.stateManager,
107
+ hookSystem: this.hookSystem
108
+ };
109
+ await plugin.initialize(context);
110
+ this.pluginStatuses.set(pluginName, {
111
+ ...status,
112
+ status: "initialized",
113
+ lastActivity: Date.now()
114
+ });
115
+ this.log("info", `Plugin ${pluginName} initialized successfully`);
116
+ await this.eventBus.emit("plugin:initialized", { plugin: pluginName });
117
+ await this.hookSystem.executeHook("plugin:initialized", {
118
+ plugin: pluginName
119
+ });
120
+ } catch (error) {
121
+ this.log("error", `Failed to initialize plugin ${pluginName}`, error);
122
+ throw error;
123
+ }
124
+ }
125
+ async startPlugin(pluginName) {
126
+ const plugin = this.plugins.get(pluginName);
127
+ if (!plugin) {
128
+ throw new Error(`Plugin ${pluginName} is not registered`);
129
+ }
130
+ const status = this.pluginStatuses.get(pluginName);
131
+ if (status?.status === "running") {
132
+ return;
133
+ }
134
+ try {
135
+ if (!plugin.isPluginInitialized()) {
136
+ await this.initializePlugin(pluginName);
137
+ }
138
+ await plugin.start();
139
+ this.pluginStatuses.set(pluginName, {
140
+ ...status,
141
+ status: "running",
142
+ lastActivity: Date.now()
143
+ });
144
+ this.log("info", `Plugin ${pluginName} started successfully`);
145
+ await this.eventBus.emit("plugin:started", { plugin: pluginName });
146
+ await this.hookSystem.executeHook("plugin:started", {
147
+ plugin: pluginName
148
+ });
149
+ } catch (error) {
150
+ this.pluginStatuses.set(pluginName, {
151
+ ...this.pluginStatuses.get(pluginName),
152
+ status: "error",
153
+ error: error instanceof Error ? error.message : String(error),
154
+ lastActivity: Date.now()
155
+ });
156
+ this.log("error", `Failed to start plugin ${pluginName}`, error);
157
+ throw error;
158
+ }
159
+ }
160
+ async stopPlugin(pluginName) {
161
+ const plugin = this.plugins.get(pluginName);
162
+ if (!plugin) {
163
+ throw new Error(`Plugin ${pluginName} is not registered`);
164
+ }
165
+ const status = this.pluginStatuses.get(pluginName);
166
+ if (status?.status !== "running") {
167
+ return;
168
+ }
169
+ try {
170
+ await plugin.stop();
171
+ this.pluginStatuses.set(pluginName, {
172
+ ...status,
173
+ status: "stopped",
174
+ lastActivity: Date.now()
175
+ });
176
+ this.log("info", `Plugin ${pluginName} stopped successfully`);
177
+ await this.eventBus.emit("plugin:stopped", { plugin: pluginName });
178
+ await this.hookSystem.executeHook("plugin:stopped", {
179
+ plugin: pluginName
180
+ });
181
+ } catch (error) {
182
+ this.pluginStatuses.set(pluginName, {
183
+ ...this.pluginStatuses.get(pluginName),
184
+ status: "error",
185
+ error: error instanceof Error ? error.message : String(error),
186
+ lastActivity: Date.now()
187
+ });
188
+ }
189
+ }
190
+ async shutdownAll() {
191
+ this.log("info", "Shutting down all plugins...");
192
+ const shutdownPromises = Array.from(this.plugins.keys()).map(
193
+ async (pluginName) => {
194
+ try {
195
+ await this.unregisterPlugin(pluginName);
196
+ } catch (error) {
197
+ this.log("error", `Failed to shutdown plugin ${pluginName}`, error);
198
+ }
199
+ }
200
+ );
201
+ await Promise.all(shutdownPromises);
202
+ this.log("info", "All plugins shutdown successfully");
203
+ }
204
+ isPluginRegistered(pluginName) {
205
+ return this.plugins.has(pluginName);
206
+ }
207
+ isPluginRunning(pluginName) {
208
+ const status = this.pluginStatuses.get(pluginName);
209
+ return status?.status === "running";
210
+ }
211
+ getPluginStatus(pluginName) {
212
+ return this.pluginStatuses.get(pluginName);
213
+ }
214
+ listPlugins() {
215
+ return Array.from(this.plugins.keys());
216
+ }
217
+ getAllPluginStatuses() {
218
+ return Array.from(this.pluginStatuses.values());
219
+ }
220
+ getPlugin(pluginName) {
221
+ return this.plugins.get(pluginName);
222
+ }
223
+ getPluginConfig(pluginName) {
224
+ return this.pluginConfigs.get(pluginName);
225
+ }
226
+ async updatePluginConfig(pluginName, config) {
227
+ const plugin = this.plugins.get(pluginName);
228
+ if (!plugin) {
229
+ throw new Error(`Plugin ${pluginName} is not registered`);
230
+ }
231
+ try {
232
+ const currentConfig = this.pluginConfigs.get(pluginName);
233
+ if (!currentConfig) {
234
+ throw new Error(`Plugin config not found for ${pluginName}`);
235
+ }
236
+ const newConfig = {
237
+ name: currentConfig.name,
238
+ version: config?.version ?? currentConfig.version,
239
+ enabled: config?.enabled ?? currentConfig.enabled,
240
+ dependencies: config?.dependencies ?? currentConfig.dependencies ?? [],
241
+ config: { ...currentConfig.config ?? {}, ...config?.config ?? {} }
242
+ };
243
+ this.pluginConfigs.set(pluginName, newConfig);
244
+ plugin.updateConfig(newConfig);
245
+ const status = this.pluginStatuses.get(pluginName);
246
+ if (status) {
247
+ this.pluginStatuses.set(pluginName, {
248
+ ...status,
249
+ config: newConfig,
250
+ lastActivity: Date.now()
251
+ });
252
+ }
253
+ this.log("info", `Plugin ${pluginName} config updated successfully`);
254
+ await this.eventBus.emit("plugin:configUpdated", {
255
+ plugin: pluginName,
256
+ config: newConfig
257
+ });
258
+ await this.hookSystem.executeHook("plugin:configUpdated", {
259
+ plugin: pluginName,
260
+ config: newConfig
261
+ });
262
+ } catch (error) {
263
+ this.log("error", `Failed to update plugin ${pluginName} config`, error);
264
+ throw error;
265
+ }
266
+ }
267
+ }
268
+
269
+ exports.PluginManager = PluginManager;