@morojs/moro 1.0.0 → 1.0.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/README.md +1 -1
- package/dist/core/config/index.d.ts +5 -5
- package/dist/core/config/index.js +1 -1
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.d.ts +1 -1
- package/dist/core/config/loader.js +58 -82
- package/dist/core/config/loader.js.map +1 -1
- package/dist/core/config/schema.d.ts +1 -1
- package/dist/core/config/schema.js +52 -111
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +2 -2
- package/dist/core/config/utils.js +18 -18
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/database/adapters/drizzle.d.ts +1 -1
- package/dist/core/database/adapters/drizzle.js +39 -55
- package/dist/core/database/adapters/drizzle.js.map +1 -1
- package/dist/core/database/adapters/index.d.ts +7 -7
- package/dist/core/database/adapters/index.js +11 -11
- package/dist/core/database/adapters/index.js.map +1 -1
- package/dist/core/database/adapters/mongodb.d.ts +1 -1
- package/dist/core/database/adapters/mongodb.js +19 -23
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.d.ts +1 -1
- package/dist/core/database/adapters/mysql.js +31 -27
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.d.ts +1 -1
- package/dist/core/database/adapters/postgresql.js +27 -35
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.d.ts +1 -1
- package/dist/core/database/adapters/redis.js +24 -24
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/database/adapters/sqlite.d.ts +1 -1
- package/dist/core/database/adapters/sqlite.js +36 -36
- package/dist/core/database/adapters/sqlite.js.map +1 -1
- package/dist/core/database/index.d.ts +2 -2
- package/dist/core/docs/index.d.ts +7 -7
- package/dist/core/docs/index.js +13 -15
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/openapi-generator.d.ts +5 -5
- package/dist/core/docs/openapi-generator.js +93 -94
- package/dist/core/docs/openapi-generator.js.map +1 -1
- package/dist/core/docs/simple-docs.d.ts +1 -1
- package/dist/core/docs/simple-docs.js +25 -28
- package/dist/core/docs/simple-docs.js.map +1 -1
- package/dist/core/docs/swagger-ui.d.ts +2 -2
- package/dist/core/docs/swagger-ui.js +46 -51
- package/dist/core/docs/swagger-ui.js.map +1 -1
- package/dist/core/docs/zod-to-openapi.d.ts +1 -1
- package/dist/core/docs/zod-to-openapi.js +115 -125
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/events/event-bus.d.ts +1 -1
- package/dist/core/events/event-bus.js +15 -21
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/events/index.d.ts +2 -2
- package/dist/core/framework.d.ts +5 -5
- package/dist/core/framework.js +55 -60
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +2 -2
- package/dist/core/http/http-server.js +228 -261
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/index.d.ts +3 -3
- package/dist/core/http/router.d.ts +1 -1
- package/dist/core/http/router.js +15 -17
- package/dist/core/http/router.js.map +1 -1
- package/dist/core/logger/filters.d.ts +1 -1
- package/dist/core/logger/filters.js +16 -16
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/index.d.ts +3 -3
- package/dist/core/logger/logger.d.ts +1 -1
- package/dist/core/logger/logger.js +48 -59
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.d.ts +4 -4
- package/dist/core/logger/outputs.js +16 -20
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.js +19 -19
- package/dist/core/middleware/built-in/adapters/cache/file.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cache/index.js +3 -3
- package/dist/core/middleware/built-in/adapters/cache/index.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.js +5 -5
- package/dist/core/middleware/built-in/adapters/cache/memory.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/redis.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/redis.js +18 -18
- package/dist/core/middleware/built-in/adapters/cache/redis.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.js +8 -8
- package/dist/core/middleware/built-in/adapters/cdn/azure.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js +14 -14
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js +13 -15
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cdn/index.js +3 -3
- package/dist/core/middleware/built-in/adapters/index.d.ts +4 -4
- package/dist/core/middleware/built-in/auth.d.ts +1 -1
- package/dist/core/middleware/built-in/auth.js +14 -14
- package/dist/core/middleware/built-in/cache.d.ts +2 -2
- package/dist/core/middleware/built-in/cache.js +43 -45
- package/dist/core/middleware/built-in/cache.js.map +1 -1
- package/dist/core/middleware/built-in/cdn.d.ts +2 -2
- package/dist/core/middleware/built-in/cdn.js +27 -29
- package/dist/core/middleware/built-in/cdn.js.map +1 -1
- package/dist/core/middleware/built-in/cookie.d.ts +2 -2
- package/dist/core/middleware/built-in/cookie.js +17 -17
- package/dist/core/middleware/built-in/cookie.js.map +1 -1
- package/dist/core/middleware/built-in/cors.d.ts +1 -1
- package/dist/core/middleware/built-in/cors.js +13 -13
- package/dist/core/middleware/built-in/csp.d.ts +1 -1
- package/dist/core/middleware/built-in/csp.js +22 -25
- package/dist/core/middleware/built-in/csp.js.map +1 -1
- package/dist/core/middleware/built-in/csrf.d.ts +1 -1
- package/dist/core/middleware/built-in/csrf.js +21 -24
- package/dist/core/middleware/built-in/csrf.js.map +1 -1
- package/dist/core/middleware/built-in/error-tracker.js +2 -2
- package/dist/core/middleware/built-in/index.d.ts +14 -14
- package/dist/core/middleware/built-in/performance-monitor.js +2 -2
- package/dist/core/middleware/built-in/rate-limit.d.ts +1 -1
- package/dist/core/middleware/built-in/rate-limit.js +12 -12
- package/dist/core/middleware/built-in/request-logger.js.map +1 -1
- package/dist/core/middleware/built-in/session.d.ts +5 -5
- package/dist/core/middleware/built-in/session.js +35 -38
- package/dist/core/middleware/built-in/session.js.map +1 -1
- package/dist/core/middleware/built-in/sse.d.ts +1 -1
- package/dist/core/middleware/built-in/sse.js +20 -22
- package/dist/core/middleware/built-in/sse.js.map +1 -1
- package/dist/core/middleware/built-in/validation.d.ts +1 -1
- package/dist/core/middleware/built-in/validation.js +13 -13
- package/dist/core/middleware/index.d.ts +5 -5
- package/dist/core/middleware/index.js +16 -16
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/core/modules/auto-discovery.d.ts +2 -2
- package/dist/core/modules/auto-discovery.js +12 -13
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/index.d.ts +2 -2
- package/dist/core/modules/index.js.map +1 -1
- package/dist/core/modules/modules.d.ts +3 -3
- package/dist/core/modules/modules.js +3 -6
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/index.d.ts +2 -2
- package/dist/core/networking/index.js.map +1 -1
- package/dist/core/networking/service-discovery.d.ts +2 -2
- package/dist/core/networking/service-discovery.js +27 -27
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/core/networking/websocket-manager.d.ts +3 -3
- package/dist/core/networking/websocket-manager.js +15 -16
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/routing/app-integration.d.ts +2 -2
- package/dist/core/routing/app-integration.js +13 -13
- package/dist/core/routing/app-integration.js.map +1 -1
- package/dist/core/routing/index.d.ts +3 -3
- package/dist/core/routing/index.js +43 -52
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/runtime/aws-lambda-adapter.d.ts +3 -3
- package/dist/core/runtime/aws-lambda-adapter.js +14 -16
- package/dist/core/runtime/aws-lambda-adapter.js.map +1 -1
- package/dist/core/runtime/base-adapter.d.ts +2 -2
- package/dist/core/runtime/base-adapter.js +11 -12
- package/dist/core/runtime/base-adapter.js.map +1 -1
- package/dist/core/runtime/cloudflare-workers-adapter.d.ts +3 -3
- package/dist/core/runtime/cloudflare-workers-adapter.js +20 -21
- package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
- package/dist/core/runtime/index.d.ts +9 -9
- package/dist/core/runtime/index.js +4 -4
- package/dist/core/runtime/index.js.map +1 -1
- package/dist/core/runtime/node-adapter.d.ts +5 -5
- package/dist/core/runtime/node-adapter.js +35 -35
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/core/runtime/vercel-edge-adapter.d.ts +3 -3
- package/dist/core/runtime/vercel-edge-adapter.js +12 -15
- package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
- package/dist/core/utilities/circuit-breaker.js +6 -6
- package/dist/core/utilities/container.d.ts +1 -1
- package/dist/core/utilities/container.js +17 -22
- package/dist/core/utilities/container.js.map +1 -1
- package/dist/core/utilities/hooks.d.ts +3 -3
- package/dist/core/utilities/hooks.js +11 -11
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/core/utilities/index.d.ts +4 -4
- package/dist/core/validation/index.d.ts +3 -3
- package/dist/core/validation/index.js +15 -15
- package/dist/core/validation/index.js.map +1 -1
- package/dist/index.d.ts +31 -30
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +14 -14
- package/dist/moro.js +79 -88
- package/dist/moro.js.map +1 -1
- package/dist/types/cache.d.ts +1 -1
- package/dist/types/core.d.ts +2 -2
- package/dist/types/events.d.ts +19 -19
- package/dist/types/hooks.d.ts +1 -1
- package/dist/types/http.d.ts +2 -2
- package/dist/types/logger.d.ts +3 -3
- package/dist/types/module.d.ts +2 -2
- package/dist/types/runtime.d.ts +2 -2
- package/dist/types/session.d.ts +4 -4
- package/package.json +180 -164
- package/src/core/config/index.ts +7 -9
- package/src/core/config/loader.ts +86 -158
- package/src/core/config/schema.ts +59 -122
- package/src/core/config/utils.ts +27 -45
- package/src/core/database/adapters/drizzle.ts +53 -75
- package/src/core/database/adapters/index.ts +26 -29
- package/src/core/database/adapters/mongodb.ts +31 -54
- package/src/core/database/adapters/mysql.ts +40 -50
- package/src/core/database/adapters/postgresql.ts +32 -42
- package/src/core/database/adapters/redis.ts +31 -36
- package/src/core/database/adapters/sqlite.ts +43 -51
- package/src/core/database/index.ts +2 -2
- package/src/core/docs/index.ts +25 -39
- package/src/core/docs/openapi-generator.ts +104 -117
- package/src/core/docs/simple-docs.ts +29 -39
- package/src/core/docs/swagger-ui.ts +57 -76
- package/src/core/docs/zod-to-openapi.ts +121 -153
- package/src/core/events/event-bus.ts +22 -45
- package/src/core/events/index.ts +2 -2
- package/src/core/framework.ts +119 -197
- package/src/core/http/http-server.ts +260 -360
- package/src/core/http/index.ts +3 -8
- package/src/core/http/router.ts +19 -31
- package/src/core/logger/filters.ts +19 -22
- package/src/core/logger/index.ts +3 -3
- package/src/core/logger/logger.ts +59 -100
- package/src/core/logger/outputs.ts +23 -27
- package/src/core/middleware/built-in/adapters/cache/file.ts +21 -23
- package/src/core/middleware/built-in/adapters/cache/index.ts +11 -14
- package/src/core/middleware/built-in/adapters/cache/memory.ts +7 -7
- package/src/core/middleware/built-in/adapters/cache/redis.ts +21 -24
- package/src/core/middleware/built-in/adapters/cdn/azure.ts +10 -18
- package/src/core/middleware/built-in/adapters/cdn/cloudflare.ts +19 -36
- package/src/core/middleware/built-in/adapters/cdn/cloudfront.ts +17 -26
- package/src/core/middleware/built-in/adapters/cdn/index.ts +10 -10
- package/src/core/middleware/built-in/adapters/index.ts +4 -4
- package/src/core/middleware/built-in/auth.ts +16 -16
- package/src/core/middleware/built-in/cache.ts +50 -67
- package/src/core/middleware/built-in/cdn.ts +34 -61
- package/src/core/middleware/built-in/cookie.ts +23 -28
- package/src/core/middleware/built-in/cors.ts +17 -17
- package/src/core/middleware/built-in/csp.ts +25 -31
- package/src/core/middleware/built-in/csrf.ts +24 -29
- package/src/core/middleware/built-in/error-tracker.ts +3 -3
- package/src/core/middleware/built-in/index.ts +28 -28
- package/src/core/middleware/built-in/performance-monitor.ts +4 -4
- package/src/core/middleware/built-in/rate-limit.ts +15 -15
- package/src/core/middleware/built-in/request-logger.ts +1 -3
- package/src/core/middleware/built-in/session.ts +47 -70
- package/src/core/middleware/built-in/sse.ts +23 -28
- package/src/core/middleware/built-in/validation.ts +15 -15
- package/src/core/middleware/index.ts +26 -37
- package/src/core/modules/auto-discovery.ts +21 -31
- package/src/core/modules/index.ts +2 -5
- package/src/core/modules/modules.ts +11 -20
- package/src/core/networking/index.ts +2 -6
- package/src/core/networking/service-discovery.ts +41 -61
- package/src/core/networking/websocket-manager.ts +27 -36
- package/src/core/routing/app-integration.ts +19 -32
- package/src/core/routing/index.ts +57 -88
- package/src/core/runtime/aws-lambda-adapter.ts +20 -30
- package/src/core/runtime/base-adapter.ts +17 -27
- package/src/core/runtime/cloudflare-workers-adapter.ts +28 -42
- package/src/core/runtime/index.ts +21 -33
- package/src/core/runtime/node-adapter.ts +59 -73
- package/src/core/runtime/vercel-edge-adapter.ts +18 -29
- package/src/core/utilities/circuit-breaker.ts +7 -7
- package/src/core/utilities/container.ts +52 -89
- package/src/core/utilities/hooks.ts +17 -23
- package/src/core/utilities/index.ts +4 -4
- package/src/core/validation/index.ts +25 -51
- package/src/index.ts +58 -60
- package/src/moro.ts +119 -191
- package/src/types/cache.ts +1 -1
- package/src/types/core.ts +2 -2
- package/src/types/database.ts +2 -10
- package/src/types/events.ts +23 -31
- package/src/types/hooks.ts +1 -1
- package/src/types/http.ts +5 -8
- package/src/types/logger.ts +7 -23
- package/src/types/module.ts +2 -2
- package/src/types/runtime.ts +6 -21
- package/src/types/session.ts +4 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Auto-discovery system for Moro modules
|
|
2
|
-
import { readdirSync, statSync } from
|
|
3
|
-
import { join, extname } from
|
|
4
|
-
import { ModuleConfig } from
|
|
5
|
-
import { DiscoveryOptions } from
|
|
2
|
+
import { readdirSync, statSync } from 'fs';
|
|
3
|
+
import { join, extname } from 'path';
|
|
4
|
+
import { ModuleConfig } from '../../types/module';
|
|
5
|
+
import { DiscoveryOptions } from '../../types/discovery';
|
|
6
6
|
|
|
7
7
|
export class ModuleDiscovery {
|
|
8
8
|
private baseDir: string;
|
|
@@ -13,7 +13,7 @@ export class ModuleDiscovery {
|
|
|
13
13
|
this.options = {
|
|
14
14
|
pattern: /\.(module|config)\.(ts|js)$/,
|
|
15
15
|
recursive: true,
|
|
16
|
-
extensions: [
|
|
16
|
+
extensions: ['.ts', '.js'],
|
|
17
17
|
...options,
|
|
18
18
|
};
|
|
19
19
|
}
|
|
@@ -29,7 +29,7 @@ export class ModuleDiscovery {
|
|
|
29
29
|
if (module) {
|
|
30
30
|
modules.push(module);
|
|
31
31
|
console.log(
|
|
32
|
-
`Auto-discovered module: ${module.name}@${module.version} from ${modulePath}
|
|
32
|
+
`Auto-discovered module: ${module.name}@${module.version} from ${modulePath}`
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
} catch (error) {
|
|
@@ -41,9 +41,7 @@ export class ModuleDiscovery {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// Find modules by directory structure
|
|
44
|
-
async discoverModuleDirectories(
|
|
45
|
-
modulesDir: string = "src/modules",
|
|
46
|
-
): Promise<ModuleConfig[]> {
|
|
44
|
+
async discoverModuleDirectories(modulesDir: string = 'src/modules'): Promise<ModuleConfig[]> {
|
|
47
45
|
const modules: ModuleConfig[] = [];
|
|
48
46
|
const fullPath = join(this.baseDir, modulesDir);
|
|
49
47
|
|
|
@@ -58,21 +56,19 @@ export class ModuleDiscovery {
|
|
|
58
56
|
const itemPath = join(fullPath, item);
|
|
59
57
|
|
|
60
58
|
if (statSync(itemPath).isDirectory()) {
|
|
61
|
-
const indexPath = join(itemPath,
|
|
59
|
+
const indexPath = join(itemPath, 'index.ts');
|
|
62
60
|
|
|
63
61
|
try {
|
|
64
62
|
if (statSync(indexPath).isFile()) {
|
|
65
63
|
const module = await this.loadModule(indexPath);
|
|
66
64
|
if (module) {
|
|
67
65
|
modules.push(module);
|
|
68
|
-
console.log(
|
|
69
|
-
`Auto-discovered module directory: ${module.name} from ${item}/`,
|
|
70
|
-
);
|
|
66
|
+
console.log(`Auto-discovered module directory: ${module.name} from ${item}/`);
|
|
71
67
|
}
|
|
72
68
|
}
|
|
73
69
|
} catch {
|
|
74
70
|
// Try alternate patterns
|
|
75
|
-
const alternates = [
|
|
71
|
+
const alternates = ['module.ts', `${item}.module.ts`, 'config.ts'];
|
|
76
72
|
|
|
77
73
|
for (const alt of alternates) {
|
|
78
74
|
const altPath = join(itemPath, alt);
|
|
@@ -81,9 +77,7 @@ export class ModuleDiscovery {
|
|
|
81
77
|
const module = await this.loadModule(altPath);
|
|
82
78
|
if (module) {
|
|
83
79
|
modules.push(module);
|
|
84
|
-
console.log(
|
|
85
|
-
`Auto-discovered module: ${module.name} from ${item}/${alt}`,
|
|
86
|
-
);
|
|
80
|
+
console.log(`Auto-discovered module: ${module.name} from ${item}/${alt}`);
|
|
87
81
|
break;
|
|
88
82
|
}
|
|
89
83
|
}
|
|
@@ -105,7 +99,7 @@ export class ModuleDiscovery {
|
|
|
105
99
|
private findModuleFiles(): string[] {
|
|
106
100
|
const files: string[] = [];
|
|
107
101
|
this.scanDirectory(this.baseDir, files);
|
|
108
|
-
return files.filter(
|
|
102
|
+
return files.filter(file => this.options.pattern?.test(file));
|
|
109
103
|
}
|
|
110
104
|
|
|
111
105
|
// Recursively scan directories for module files
|
|
@@ -119,10 +113,7 @@ export class ModuleDiscovery {
|
|
|
119
113
|
|
|
120
114
|
if (stat.isDirectory()) {
|
|
121
115
|
// Skip node_modules and other common directories
|
|
122
|
-
if (
|
|
123
|
-
!["node_modules", ".git", "dist", "build"].includes(item) &&
|
|
124
|
-
this.options.recursive
|
|
125
|
-
) {
|
|
116
|
+
if (!['node_modules', '.git', 'dist', 'build'].includes(item) && this.options.recursive) {
|
|
126
117
|
this.scanDirectory(fullPath, files);
|
|
127
118
|
}
|
|
128
119
|
} else if (stat.isFile()) {
|
|
@@ -149,8 +140,7 @@ export class ModuleDiscovery {
|
|
|
149
140
|
module.config,
|
|
150
141
|
module,
|
|
151
142
|
...Object.values(module).filter(
|
|
152
|
-
|
|
153
|
-
exp && typeof exp === "object" && "name" in exp && "version" in exp,
|
|
143
|
+
exp => exp && typeof exp === 'object' && 'name' in exp && 'version' in exp
|
|
154
144
|
),
|
|
155
145
|
];
|
|
156
146
|
|
|
@@ -170,9 +160,9 @@ export class ModuleDiscovery {
|
|
|
170
160
|
private isValidModule(obj: any): boolean {
|
|
171
161
|
return (
|
|
172
162
|
obj &&
|
|
173
|
-
typeof obj ===
|
|
174
|
-
typeof obj.name ===
|
|
175
|
-
typeof obj.version ===
|
|
163
|
+
typeof obj === 'object' &&
|
|
164
|
+
typeof obj.name === 'string' &&
|
|
165
|
+
typeof obj.version === 'string' &&
|
|
176
166
|
(obj.routes === undefined || Array.isArray(obj.routes)) &&
|
|
177
167
|
(obj.websockets === undefined || Array.isArray(obj.websockets)) &&
|
|
178
168
|
(obj.services === undefined || Array.isArray(obj.services))
|
|
@@ -181,10 +171,10 @@ export class ModuleDiscovery {
|
|
|
181
171
|
|
|
182
172
|
// Watch for module changes (for development)
|
|
183
173
|
watchModules(callback: (modules: ModuleConfig[]) => void): void {
|
|
184
|
-
const fs = require(
|
|
174
|
+
const fs = require('fs');
|
|
185
175
|
const modulePaths = this.findModuleFiles();
|
|
186
176
|
|
|
187
|
-
modulePaths.forEach(
|
|
177
|
+
modulePaths.forEach(path => {
|
|
188
178
|
try {
|
|
189
179
|
fs.watchFile(path, async () => {
|
|
190
180
|
console.log(`Module file changed: ${path}`);
|
|
@@ -201,7 +191,7 @@ export class ModuleDiscovery {
|
|
|
201
191
|
// Convenience functions
|
|
202
192
|
export async function autoDiscoverModules(
|
|
203
193
|
baseDir?: string,
|
|
204
|
-
options?: DiscoveryOptions
|
|
194
|
+
options?: DiscoveryOptions
|
|
205
195
|
): Promise<ModuleConfig[]> {
|
|
206
196
|
const discovery = new ModuleDiscovery(baseDir, options);
|
|
207
197
|
return discovery.discoverModules();
|
|
@@ -209,7 +199,7 @@ export async function autoDiscoverModules(
|
|
|
209
199
|
|
|
210
200
|
export async function autoDiscoverModuleDirectories(
|
|
211
201
|
baseDir?: string,
|
|
212
|
-
modulesDir?: string
|
|
202
|
+
modulesDir?: string
|
|
213
203
|
): Promise<ModuleConfig[]> {
|
|
214
204
|
const discovery = new ModuleDiscovery(baseDir);
|
|
215
205
|
return discovery.discoverModuleDirectories(modulesDir);
|
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
// Module System - Centralized Exports
|
|
2
|
-
export { defineModule, ModuleLoader } from
|
|
3
|
-
export {
|
|
4
|
-
ModuleDiscovery,
|
|
5
|
-
autoDiscoverModuleDirectories,
|
|
6
|
-
} from "./auto-discovery";
|
|
2
|
+
export { defineModule, ModuleLoader } from './modules';
|
|
3
|
+
export { ModuleDiscovery, autoDiscoverModuleDirectories } from './auto-discovery';
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
// Module System - Definition and Loading
|
|
2
|
-
import { promises as fs } from
|
|
3
|
-
import path from
|
|
4
|
-
import { Container } from
|
|
5
|
-
import { ModuleConfig } from
|
|
6
|
-
import {
|
|
7
|
-
ModuleDefinition,
|
|
8
|
-
ModuleRoute,
|
|
9
|
-
ModuleSocket,
|
|
10
|
-
} from "../../types/module";
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { Container } from '../utilities';
|
|
5
|
+
import { ModuleConfig } from '../../types/module';
|
|
6
|
+
import { ModuleDefinition, ModuleRoute, ModuleSocket } from '../../types/module';
|
|
11
7
|
|
|
12
8
|
// Module Definition Function
|
|
13
9
|
export function defineModule(definition: ModuleDefinition): ModuleConfig {
|
|
@@ -35,7 +31,7 @@ export function defineModule(definition: ModuleDefinition): ModuleConfig {
|
|
|
35
31
|
acc[`route_handler_${index}`] = route.handler;
|
|
36
32
|
return acc;
|
|
37
33
|
},
|
|
38
|
-
{} as Record<string, Function
|
|
34
|
+
{} as Record<string, Function>
|
|
39
35
|
);
|
|
40
36
|
}
|
|
41
37
|
|
|
@@ -56,7 +52,7 @@ export function defineModule(definition: ModuleDefinition): ModuleConfig {
|
|
|
56
52
|
acc[`socket_handler_${index}`] = socket.handler;
|
|
57
53
|
return acc;
|
|
58
54
|
},
|
|
59
|
-
{} as Record<string, Function
|
|
55
|
+
{} as Record<string, Function>
|
|
60
56
|
);
|
|
61
57
|
}
|
|
62
58
|
|
|
@@ -81,7 +77,7 @@ export class ModuleLoader {
|
|
|
81
77
|
|
|
82
78
|
for (const entry of entries) {
|
|
83
79
|
if (entry.isDirectory()) {
|
|
84
|
-
const modulePath = path.join(moduleDir, entry.name,
|
|
80
|
+
const modulePath = path.join(moduleDir, entry.name, 'index.ts');
|
|
85
81
|
|
|
86
82
|
try {
|
|
87
83
|
await fs.access(modulePath);
|
|
@@ -90,25 +86,20 @@ export class ModuleLoader {
|
|
|
90
86
|
// Look for exported module config
|
|
91
87
|
for (const exportName of Object.keys(moduleExports)) {
|
|
92
88
|
const exported = moduleExports[exportName];
|
|
93
|
-
if (
|
|
94
|
-
exported &&
|
|
95
|
-
typeof exported === "object" &&
|
|
96
|
-
exported.name &&
|
|
97
|
-
exported.version
|
|
98
|
-
) {
|
|
89
|
+
if (exported && typeof exported === 'object' && exported.name && exported.version) {
|
|
99
90
|
modules.push(exported as ModuleConfig);
|
|
100
91
|
}
|
|
101
92
|
}
|
|
102
93
|
} catch (error) {
|
|
103
94
|
console.warn(
|
|
104
95
|
`⚠️ Could not load module from ${modulePath}:`,
|
|
105
|
-
error instanceof Error ? error.message : String(error)
|
|
96
|
+
error instanceof Error ? error.message : String(error)
|
|
106
97
|
);
|
|
107
98
|
}
|
|
108
99
|
}
|
|
109
100
|
}
|
|
110
101
|
} catch (error) {
|
|
111
|
-
console.error(
|
|
102
|
+
console.error('Failed to discover modules:', error);
|
|
112
103
|
}
|
|
113
104
|
|
|
114
105
|
return modules;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
// Networking System - Centralized Exports
|
|
2
|
-
export { WebSocketManager } from
|
|
3
|
-
export {
|
|
4
|
-
ServiceRegistry,
|
|
5
|
-
ServiceInfo,
|
|
6
|
-
ServiceDiscoveryOptions,
|
|
7
|
-
} from "./service-discovery";
|
|
2
|
+
export { WebSocketManager } from './websocket-manager';
|
|
3
|
+
export { ServiceRegistry, ServiceInfo, ServiceDiscoveryOptions } from './service-discovery';
|
|
@@ -12,7 +12,7 @@ export interface ServiceInfo {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface ServiceDiscoveryOptions {
|
|
15
|
-
type:
|
|
15
|
+
type: 'consul' | 'kubernetes' | 'memory';
|
|
16
16
|
consulUrl?: string;
|
|
17
17
|
kubernetesNamespace?: string;
|
|
18
18
|
healthCheckInterval?: number;
|
|
@@ -33,13 +33,13 @@ export class ServiceRegistry {
|
|
|
33
33
|
const { name } = service;
|
|
34
34
|
|
|
35
35
|
switch (this.options.type) {
|
|
36
|
-
case
|
|
36
|
+
case 'consul':
|
|
37
37
|
await this.registerWithConsul(service);
|
|
38
38
|
break;
|
|
39
|
-
case
|
|
39
|
+
case 'kubernetes':
|
|
40
40
|
await this.registerWithKubernetes(service);
|
|
41
41
|
break;
|
|
42
|
-
case
|
|
42
|
+
case 'memory':
|
|
43
43
|
this.registerInMemory(service);
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
@@ -49,11 +49,11 @@ export class ServiceRegistry {
|
|
|
49
49
|
|
|
50
50
|
async discover(serviceName: string): Promise<ServiceInfo[]> {
|
|
51
51
|
switch (this.options.type) {
|
|
52
|
-
case
|
|
52
|
+
case 'consul':
|
|
53
53
|
return this.discoverFromConsul(serviceName);
|
|
54
|
-
case
|
|
54
|
+
case 'kubernetes':
|
|
55
55
|
return this.discoverFromKubernetes(serviceName);
|
|
56
|
-
case
|
|
56
|
+
case 'memory':
|
|
57
57
|
return this.discoverFromMemory(serviceName);
|
|
58
58
|
default:
|
|
59
59
|
return [];
|
|
@@ -62,13 +62,13 @@ export class ServiceRegistry {
|
|
|
62
62
|
|
|
63
63
|
async deregister(serviceName: string): Promise<void> {
|
|
64
64
|
switch (this.options.type) {
|
|
65
|
-
case
|
|
65
|
+
case 'consul':
|
|
66
66
|
await this.deregisterFromConsul(serviceName);
|
|
67
67
|
break;
|
|
68
|
-
case
|
|
68
|
+
case 'kubernetes':
|
|
69
69
|
// K8s handles this automatically
|
|
70
70
|
break;
|
|
71
|
-
case
|
|
71
|
+
case 'memory':
|
|
72
72
|
this.services.delete(serviceName);
|
|
73
73
|
break;
|
|
74
74
|
}
|
|
@@ -79,9 +79,7 @@ export class ServiceRegistry {
|
|
|
79
79
|
// In-memory registry methods
|
|
80
80
|
private registerInMemory(service: ServiceInfo): void {
|
|
81
81
|
const existing = this.services.get(service.name) || [];
|
|
82
|
-
const updated = existing.filter(
|
|
83
|
-
(s) => s.host !== service.host || s.port !== service.port,
|
|
84
|
-
);
|
|
82
|
+
const updated = existing.filter(s => s.host !== service.host || s.port !== service.port);
|
|
85
83
|
updated.push(service);
|
|
86
84
|
this.services.set(service.name, updated);
|
|
87
85
|
}
|
|
@@ -93,7 +91,7 @@ export class ServiceRegistry {
|
|
|
93
91
|
// Consul integration
|
|
94
92
|
private async registerWithConsul(service: ServiceInfo): Promise<void> {
|
|
95
93
|
if (!this.options.consulUrl) {
|
|
96
|
-
throw new Error(
|
|
94
|
+
throw new Error('Consul URL required for consul service discovery');
|
|
97
95
|
}
|
|
98
96
|
|
|
99
97
|
const consulService = {
|
|
@@ -105,43 +103,38 @@ export class ServiceRegistry {
|
|
|
105
103
|
Check: service.health
|
|
106
104
|
? {
|
|
107
105
|
HTTP: `http://${service.host}:${service.port}${service.health}`,
|
|
108
|
-
Interval:
|
|
109
|
-
Timeout:
|
|
106
|
+
Interval: '30s',
|
|
107
|
+
Timeout: '10s',
|
|
110
108
|
}
|
|
111
109
|
: undefined,
|
|
112
110
|
Meta: service.metadata || {},
|
|
113
111
|
};
|
|
114
112
|
|
|
115
113
|
try {
|
|
116
|
-
const response = await fetch(
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
body: JSON.stringify(consulService),
|
|
122
|
-
},
|
|
123
|
-
);
|
|
114
|
+
const response = await fetch(`${this.options.consulUrl}/v1/agent/service/register`, {
|
|
115
|
+
method: 'PUT',
|
|
116
|
+
headers: { 'Content-Type': 'application/json' },
|
|
117
|
+
body: JSON.stringify(consulService),
|
|
118
|
+
});
|
|
124
119
|
|
|
125
120
|
if (!response.ok) {
|
|
126
121
|
throw new Error(`Consul registration failed: ${response.statusText}`);
|
|
127
122
|
}
|
|
128
123
|
} catch (error) {
|
|
129
|
-
console.error(
|
|
124
|
+
console.error('Failed to register with Consul:', error);
|
|
130
125
|
// Fallback to in-memory
|
|
131
126
|
this.registerInMemory(service);
|
|
132
127
|
}
|
|
133
128
|
}
|
|
134
129
|
|
|
135
|
-
private async discoverFromConsul(
|
|
136
|
-
serviceName: string,
|
|
137
|
-
): Promise<ServiceInfo[]> {
|
|
130
|
+
private async discoverFromConsul(serviceName: string): Promise<ServiceInfo[]> {
|
|
138
131
|
if (!this.options.consulUrl) {
|
|
139
132
|
return this.discoverFromMemory(serviceName);
|
|
140
133
|
}
|
|
141
134
|
|
|
142
135
|
try {
|
|
143
136
|
const response = await fetch(
|
|
144
|
-
`${this.options.consulUrl}/v1/health/service/${serviceName}?passing=true
|
|
137
|
+
`${this.options.consulUrl}/v1/health/service/${serviceName}?passing=true`
|
|
145
138
|
);
|
|
146
139
|
|
|
147
140
|
if (!response.ok) {
|
|
@@ -157,7 +150,7 @@ export class ServiceRegistry {
|
|
|
157
150
|
metadata: entry.Service.Meta,
|
|
158
151
|
}));
|
|
159
152
|
} catch (error) {
|
|
160
|
-
console.error(
|
|
153
|
+
console.error('Failed to discover from Consul:', error);
|
|
161
154
|
return this.discoverFromMemory(serviceName);
|
|
162
155
|
}
|
|
163
156
|
}
|
|
@@ -166,14 +159,11 @@ export class ServiceRegistry {
|
|
|
166
159
|
if (!this.options.consulUrl) return;
|
|
167
160
|
|
|
168
161
|
try {
|
|
169
|
-
await fetch(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
method: "PUT",
|
|
173
|
-
},
|
|
174
|
-
);
|
|
162
|
+
await fetch(`${this.options.consulUrl}/v1/agent/service/deregister/${serviceName}`, {
|
|
163
|
+
method: 'PUT',
|
|
164
|
+
});
|
|
175
165
|
} catch (error) {
|
|
176
|
-
console.error(
|
|
166
|
+
console.error('Failed to deregister from Consul:', error);
|
|
177
167
|
}
|
|
178
168
|
}
|
|
179
169
|
|
|
@@ -181,19 +171,15 @@ export class ServiceRegistry {
|
|
|
181
171
|
private async registerWithKubernetes(service: ServiceInfo): Promise<void> {
|
|
182
172
|
// In Kubernetes, services are registered via Service/Endpoints resources
|
|
183
173
|
// This would typically be handled by the K8s API, not application code
|
|
184
|
-
console.log(
|
|
185
|
-
`K8s service registration: ${service.name} (handled by Kubernetes)`,
|
|
186
|
-
);
|
|
174
|
+
console.log(`K8s service registration: ${service.name} (handled by Kubernetes)`);
|
|
187
175
|
|
|
188
176
|
// Fallback to in-memory for local development
|
|
189
177
|
this.registerInMemory(service);
|
|
190
178
|
}
|
|
191
179
|
|
|
192
|
-
private async discoverFromKubernetes(
|
|
193
|
-
serviceName: string,
|
|
194
|
-
): Promise<ServiceInfo[]> {
|
|
180
|
+
private async discoverFromKubernetes(serviceName: string): Promise<ServiceInfo[]> {
|
|
195
181
|
// In K8s, we can discover services via DNS or the K8s API
|
|
196
|
-
const namespace = this.options.kubernetesNamespace ||
|
|
182
|
+
const namespace = this.options.kubernetesNamespace || 'default';
|
|
197
183
|
|
|
198
184
|
try {
|
|
199
185
|
// Try K8s service DNS resolution
|
|
@@ -206,11 +192,11 @@ export class ServiceRegistry {
|
|
|
206
192
|
name: serviceName,
|
|
207
193
|
host,
|
|
208
194
|
port: 80, // Default port, should be discovered from service definition
|
|
209
|
-
metadata: { discovered:
|
|
195
|
+
metadata: { discovered: 'kubernetes' },
|
|
210
196
|
},
|
|
211
197
|
];
|
|
212
198
|
} catch (error) {
|
|
213
|
-
console.error(
|
|
199
|
+
console.error('Failed to discover from Kubernetes:', error);
|
|
214
200
|
return this.discoverFromMemory(serviceName);
|
|
215
201
|
}
|
|
216
202
|
}
|
|
@@ -220,7 +206,7 @@ export class ServiceRegistry {
|
|
|
220
206
|
if (this.options.healthCheckInterval) {
|
|
221
207
|
this.healthCheckInterval = setInterval(
|
|
222
208
|
() => this.performHealthChecks(),
|
|
223
|
-
this.options.healthCheckInterval
|
|
209
|
+
this.options.healthCheckInterval
|
|
224
210
|
);
|
|
225
211
|
}
|
|
226
212
|
}
|
|
@@ -234,13 +220,11 @@ export class ServiceRegistry {
|
|
|
234
220
|
`http://${service.host}:${service.port}${service.health}`,
|
|
235
221
|
{
|
|
236
222
|
timeout: 5000,
|
|
237
|
-
} as any
|
|
223
|
+
} as any
|
|
238
224
|
);
|
|
239
225
|
|
|
240
226
|
if (!response.ok) {
|
|
241
|
-
console.warn(
|
|
242
|
-
`Health check failed for ${serviceName}: ${response.statusText}`,
|
|
243
|
-
);
|
|
227
|
+
console.warn(`Health check failed for ${serviceName}: ${response.statusText}`);
|
|
244
228
|
// Remove unhealthy service
|
|
245
229
|
this.removeUnhealthyService(serviceName, service);
|
|
246
230
|
}
|
|
@@ -253,14 +237,10 @@ export class ServiceRegistry {
|
|
|
253
237
|
}
|
|
254
238
|
}
|
|
255
239
|
|
|
256
|
-
private removeUnhealthyService(
|
|
257
|
-
serviceName: string,
|
|
258
|
-
unhealthyService: ServiceInfo,
|
|
259
|
-
): void {
|
|
240
|
+
private removeUnhealthyService(serviceName: string, unhealthyService: ServiceInfo): void {
|
|
260
241
|
const services = this.services.get(serviceName) || [];
|
|
261
242
|
const filtered = services.filter(
|
|
262
|
-
|
|
263
|
-
s.host !== unhealthyService.host || s.port !== unhealthyService.port,
|
|
243
|
+
s => s.host !== unhealthyService.host || s.port !== unhealthyService.port
|
|
264
244
|
);
|
|
265
245
|
|
|
266
246
|
if (filtered.length === 0) {
|
|
@@ -273,7 +253,7 @@ export class ServiceRegistry {
|
|
|
273
253
|
// Load balancing
|
|
274
254
|
selectService(
|
|
275
255
|
serviceName: string,
|
|
276
|
-
strategy:
|
|
256
|
+
strategy: 'round-robin' | 'random' | 'least-connections' = 'round-robin'
|
|
277
257
|
): ServiceInfo | null {
|
|
278
258
|
const services = this.services.get(serviceName) || [];
|
|
279
259
|
|
|
@@ -282,12 +262,12 @@ export class ServiceRegistry {
|
|
|
282
262
|
}
|
|
283
263
|
|
|
284
264
|
switch (strategy) {
|
|
285
|
-
case
|
|
265
|
+
case 'random':
|
|
286
266
|
return services[Math.floor(Math.random() * services.length)];
|
|
287
|
-
case
|
|
267
|
+
case 'round-robin':
|
|
288
268
|
// Simple round-robin (in production, maintain state)
|
|
289
269
|
return services[Date.now() % services.length];
|
|
290
|
-
case
|
|
270
|
+
case 'least-connections':
|
|
291
271
|
// For demo, just return the first (in production, track connections)
|
|
292
272
|
return services[0];
|
|
293
273
|
default:
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
// src/core/websocket-manager.ts
|
|
2
|
-
import { Server as SocketIOServer, Socket, Namespace } from
|
|
3
|
-
import { Container } from
|
|
4
|
-
import { CircuitBreaker } from
|
|
5
|
-
import { ModuleConfig, WebSocketDefinition } from
|
|
2
|
+
import { Server as SocketIOServer, Socket, Namespace } from 'socket.io';
|
|
3
|
+
import { Container } from '../utilities';
|
|
4
|
+
import { CircuitBreaker } from '../utilities';
|
|
5
|
+
import { ModuleConfig, WebSocketDefinition } from '../../types/module';
|
|
6
6
|
|
|
7
7
|
export class WebSocketManager {
|
|
8
8
|
private circuitBreakers = new Map<string, CircuitBreaker>();
|
|
9
|
-
private rateLimiters = new Map<
|
|
10
|
-
string,
|
|
11
|
-
Map<string, { count: number; resetTime: number }>
|
|
12
|
-
>();
|
|
9
|
+
private rateLimiters = new Map<string, Map<string, { count: number; resetTime: number }>>();
|
|
13
10
|
private compressionEnabled = true;
|
|
14
11
|
private customIdGenerator?: () => string;
|
|
15
12
|
|
|
16
13
|
constructor(
|
|
17
14
|
private io: SocketIOServer,
|
|
18
|
-
private container: Container
|
|
15
|
+
private container: Container
|
|
19
16
|
) {
|
|
20
17
|
this.setupAdvancedFeatures();
|
|
21
18
|
}
|
|
@@ -60,7 +57,7 @@ export class WebSocketManager {
|
|
|
60
57
|
|
|
61
58
|
// Add heartbeat mechanism
|
|
62
59
|
(socket as any).heartbeat = () => {
|
|
63
|
-
socket.emit(
|
|
60
|
+
socket.emit('heartbeat', { timestamp: Date.now() });
|
|
64
61
|
};
|
|
65
62
|
|
|
66
63
|
next();
|
|
@@ -102,9 +99,9 @@ export class WebSocketManager {
|
|
|
102
99
|
async registerHandler(
|
|
103
100
|
namespace: Namespace,
|
|
104
101
|
wsConfig: WebSocketDefinition,
|
|
105
|
-
moduleConfig: ModuleConfig
|
|
102
|
+
moduleConfig: ModuleConfig
|
|
106
103
|
): Promise<void> {
|
|
107
|
-
namespace.on(
|
|
104
|
+
namespace.on('connection', (socket: Socket) => {
|
|
108
105
|
console.log(`WebSocket connected to /${moduleConfig.name}: ${socket.id}`);
|
|
109
106
|
this.setupSocketHandlers(socket, wsConfig, moduleConfig);
|
|
110
107
|
this.setupSocketMiddleware(socket, moduleConfig.name);
|
|
@@ -114,24 +111,21 @@ export class WebSocketManager {
|
|
|
114
111
|
private setupSocketHandlers(
|
|
115
112
|
socket: Socket,
|
|
116
113
|
wsConfig: WebSocketDefinition,
|
|
117
|
-
moduleConfig: ModuleConfig
|
|
114
|
+
moduleConfig: ModuleConfig
|
|
118
115
|
): void {
|
|
119
116
|
socket.on(wsConfig.event, async (data: any, callback?: Function) => {
|
|
120
117
|
const handlerKey = `${moduleConfig.name}.${wsConfig.handler}`;
|
|
121
118
|
|
|
122
119
|
try {
|
|
123
120
|
// Rate limiting
|
|
124
|
-
if (
|
|
125
|
-
wsConfig.rateLimit &&
|
|
126
|
-
!this.checkRateLimit(socket.id, handlerKey, wsConfig.rateLimit)
|
|
127
|
-
) {
|
|
121
|
+
if (wsConfig.rateLimit && !this.checkRateLimit(socket.id, handlerKey, wsConfig.rateLimit)) {
|
|
128
122
|
const error = {
|
|
129
123
|
success: false,
|
|
130
|
-
error:
|
|
131
|
-
code:
|
|
124
|
+
error: 'Rate limit exceeded',
|
|
125
|
+
code: 'RATE_LIMIT',
|
|
132
126
|
};
|
|
133
127
|
if (callback) callback(error);
|
|
134
|
-
else socket.emit(
|
|
128
|
+
else socket.emit('error', error);
|
|
135
129
|
return;
|
|
136
130
|
}
|
|
137
131
|
|
|
@@ -143,15 +137,15 @@ export class WebSocketManager {
|
|
|
143
137
|
if (validationError.issues) {
|
|
144
138
|
const error = {
|
|
145
139
|
success: false,
|
|
146
|
-
error:
|
|
140
|
+
error: 'Validation failed',
|
|
147
141
|
details: validationError.issues.map((issue: any) => ({
|
|
148
|
-
field: issue.path.length > 0 ? issue.path.join(
|
|
142
|
+
field: issue.path.length > 0 ? issue.path.join('.') : 'data',
|
|
149
143
|
message: issue.message,
|
|
150
144
|
code: issue.code,
|
|
151
145
|
})),
|
|
152
146
|
};
|
|
153
147
|
if (callback) callback(error);
|
|
154
|
-
else socket.emit(
|
|
148
|
+
else socket.emit('error', error);
|
|
155
149
|
return;
|
|
156
150
|
}
|
|
157
151
|
throw validationError;
|
|
@@ -175,9 +169,8 @@ export class WebSocketManager {
|
|
|
175
169
|
socket.emit(`${wsConfig.event}:response`, result);
|
|
176
170
|
}
|
|
177
171
|
} catch (error) {
|
|
178
|
-
const errorMessage =
|
|
179
|
-
|
|
180
|
-
const errorCode = (error as any)?.code || "INTERNAL_ERROR";
|
|
172
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
173
|
+
const errorCode = (error as any)?.code || 'INTERNAL_ERROR';
|
|
181
174
|
console.error(`WebSocket error in ${handlerKey}:`, errorMessage);
|
|
182
175
|
|
|
183
176
|
const errorResponse = {
|
|
@@ -189,29 +182,27 @@ export class WebSocketManager {
|
|
|
189
182
|
if (callback) {
|
|
190
183
|
callback(errorResponse);
|
|
191
184
|
} else {
|
|
192
|
-
socket.emit(
|
|
185
|
+
socket.emit('error', errorResponse);
|
|
193
186
|
}
|
|
194
187
|
}
|
|
195
188
|
});
|
|
196
189
|
}
|
|
197
190
|
|
|
198
191
|
private setupSocketMiddleware(socket: Socket, moduleName: string): void {
|
|
199
|
-
socket.on(
|
|
200
|
-
console.log(
|
|
201
|
-
`WebSocket disconnected from /${moduleName}: ${socket.id} (${reason})`,
|
|
202
|
-
);
|
|
192
|
+
socket.on('disconnect', reason => {
|
|
193
|
+
console.log(`WebSocket disconnected from /${moduleName}: ${socket.id} (${reason})`);
|
|
203
194
|
this.cleanup(socket.id);
|
|
204
195
|
});
|
|
205
196
|
|
|
206
|
-
socket.on(
|
|
207
|
-
socket.emit(
|
|
197
|
+
socket.on('ping', () => {
|
|
198
|
+
socket.emit('pong');
|
|
208
199
|
});
|
|
209
200
|
}
|
|
210
201
|
|
|
211
202
|
private checkRateLimit(
|
|
212
203
|
socketId: string,
|
|
213
204
|
handlerKey: string,
|
|
214
|
-
rateLimit: { requests: number; window: number }
|
|
205
|
+
rateLimit: { requests: number; window: number }
|
|
215
206
|
): boolean {
|
|
216
207
|
if (!this.rateLimiters.has(handlerKey)) {
|
|
217
208
|
this.rateLimiters.set(handlerKey, new Map());
|
|
@@ -245,14 +236,14 @@ export class WebSocketManager {
|
|
|
245
236
|
failureThreshold: 5,
|
|
246
237
|
resetTimeout: 30000,
|
|
247
238
|
monitoringPeriod: 10000,
|
|
248
|
-
})
|
|
239
|
+
})
|
|
249
240
|
);
|
|
250
241
|
}
|
|
251
242
|
return this.circuitBreakers.get(key)!;
|
|
252
243
|
}
|
|
253
244
|
|
|
254
245
|
private cleanup(socketId: string): void {
|
|
255
|
-
this.rateLimiters.forEach(
|
|
246
|
+
this.rateLimiters.forEach(limiter => {
|
|
256
247
|
limiter.delete(socketId);
|
|
257
248
|
});
|
|
258
249
|
}
|