@expressive-tea/core 2.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.
- package/.gitattributes +4 -0
- package/.swcrc +61 -0
- package/LICENSE +201 -0
- package/README.md +627 -0
- package/banner.png +0 -0
- package/classes/Boot.d.ts +145 -0
- package/classes/Boot.js +223 -0
- package/classes/Engine.d.ts +63 -0
- package/classes/Engine.js +90 -0
- package/classes/EngineRegistry.d.ts +154 -0
- package/classes/EngineRegistry.js +247 -0
- package/classes/LoadBalancer.d.ts +8 -0
- package/classes/LoadBalancer.js +28 -0
- package/classes/ProxyRoute.d.ts +14 -0
- package/classes/ProxyRoute.js +40 -0
- package/classes/Settings.d.ts +128 -0
- package/classes/Settings.js +172 -0
- package/decorators/annotations.d.ts +91 -0
- package/decorators/annotations.js +132 -0
- package/decorators/env.d.ts +145 -0
- package/decorators/env.js +177 -0
- package/decorators/health.d.ts +115 -0
- package/decorators/health.js +124 -0
- package/decorators/module.d.ts +34 -0
- package/decorators/module.js +39 -0
- package/decorators/proxy.d.ts +28 -0
- package/decorators/proxy.js +60 -0
- package/decorators/router.d.ts +199 -0
- package/decorators/router.js +252 -0
- package/decorators/server.d.ts +92 -0
- package/decorators/server.js +247 -0
- package/engines/constants/constants.d.ts +2 -0
- package/engines/constants/constants.js +5 -0
- package/engines/health/index.d.ts +120 -0
- package/engines/health/index.js +179 -0
- package/engines/http/index.d.ts +12 -0
- package/engines/http/index.js +59 -0
- package/engines/index.d.ts +32 -0
- package/engines/index.js +112 -0
- package/engines/socketio/index.d.ts +7 -0
- package/engines/socketio/index.js +30 -0
- package/engines/teacup/index.d.ts +27 -0
- package/engines/teacup/index.js +136 -0
- package/engines/teapot/index.d.ts +32 -0
- package/engines/teapot/index.js +167 -0
- package/engines/websocket/index.d.ts +9 -0
- package/engines/websocket/index.js +39 -0
- package/eslint.config.mjs +138 -0
- package/exceptions/BootLoaderExceptions.d.ts +26 -0
- package/exceptions/BootLoaderExceptions.js +31 -0
- package/exceptions/RequestExceptions.d.ts +75 -0
- package/exceptions/RequestExceptions.js +89 -0
- package/helpers/boot-helper.d.ts +7 -0
- package/helpers/boot-helper.js +84 -0
- package/helpers/decorators.d.ts +1 -0
- package/helpers/decorators.js +15 -0
- package/helpers/promise-helper.d.ts +1 -0
- package/helpers/promise-helper.js +6 -0
- package/helpers/server.d.ts +35 -0
- package/helpers/server.js +141 -0
- package/helpers/teapot-helper.d.ts +18 -0
- package/helpers/teapot-helper.js +88 -0
- package/helpers/websocket-helper.d.ts +3 -0
- package/helpers/websocket-helper.js +20 -0
- package/images/announcement-01.png +0 -0
- package/images/logo-sticky-01.png +0 -0
- package/images/logo-wp-01.png +0 -0
- package/images/logo.png +0 -0
- package/images/zero-oneit.png +0 -0
- package/interfaces/index.d.ts +4 -0
- package/interfaces/index.js +2 -0
- package/inversify.config.d.ts +9 -0
- package/inversify.config.js +8 -0
- package/libs/classNames.d.ts +1 -0
- package/libs/classNames.js +4 -0
- package/libs/utilities.d.ts +21910 -0
- package/libs/utilities.js +420 -0
- package/mixins/module.d.ts +45 -0
- package/mixins/module.js +71 -0
- package/mixins/proxy.d.ts +46 -0
- package/mixins/proxy.js +86 -0
- package/mixins/route.d.ts +48 -0
- package/mixins/route.js +96 -0
- package/package.json +137 -0
- package/services/DependencyInjection.d.ts +159 -0
- package/services/DependencyInjection.js +201 -0
- package/services/WebsocketService.d.ts +18 -0
- package/services/WebsocketService.js +47 -0
- package/types/core.d.ts +14 -0
- package/types/core.js +2 -0
- package/types/injection-types.d.ts +6 -0
- package/types/injection-types.js +10 -0
- package/types/inversify.d.ts +5 -0
- package/types/inversify.js +3 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import ExpressiveTeaEngine from '../../classes/Engine';
|
|
2
|
+
/**
|
|
3
|
+
* Health check status
|
|
4
|
+
* @since 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
export type HealthStatus = 'pass' | 'fail' | 'warn';
|
|
7
|
+
/**
|
|
8
|
+
* Individual health check result
|
|
9
|
+
* @since 2.0.0
|
|
10
|
+
*/
|
|
11
|
+
export interface HealthCheckResult {
|
|
12
|
+
/** Check status */
|
|
13
|
+
status: HealthStatus;
|
|
14
|
+
/** Optional details about the check */
|
|
15
|
+
details?: Record<string, any>;
|
|
16
|
+
/** Optional error message if failed */
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Health check function
|
|
21
|
+
* @since 2.0.0
|
|
22
|
+
*/
|
|
23
|
+
export type HealthCheckFunction = () => Promise<HealthCheckResult> | HealthCheckResult;
|
|
24
|
+
/**
|
|
25
|
+
* Health check definition
|
|
26
|
+
* @since 2.0.0
|
|
27
|
+
*/
|
|
28
|
+
export interface HealthCheck {
|
|
29
|
+
/** Unique name for this health check */
|
|
30
|
+
name: string;
|
|
31
|
+
/** The check function to execute */
|
|
32
|
+
check: HealthCheckFunction;
|
|
33
|
+
/** Whether this check is critical for readiness */
|
|
34
|
+
critical?: boolean;
|
|
35
|
+
/** Optional timeout in milliseconds */
|
|
36
|
+
timeout?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Health Check Engine
|
|
40
|
+
*
|
|
41
|
+
* Provides standardized health check endpoints for monitoring and orchestration:
|
|
42
|
+
* - `/health` - Detailed health status with all checks
|
|
43
|
+
* - `/health/live` - Liveness probe (always 200 if server is running)
|
|
44
|
+
* - `/health/ready` - Readiness probe (200 only if all critical checks pass)
|
|
45
|
+
*
|
|
46
|
+
* Compatible with Kubernetes liveness and readiness probes.
|
|
47
|
+
*
|
|
48
|
+
* @class HealthCheckEngine
|
|
49
|
+
* @extends ExpressiveTeaEngine
|
|
50
|
+
* @since 2.0.0
|
|
51
|
+
* @summary Standardized health check endpoints for monitoring
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // Enable health checks with custom checks
|
|
55
|
+
* @HealthCheck({
|
|
56
|
+
* checks: [
|
|
57
|
+
* {
|
|
58
|
+
* name: 'database',
|
|
59
|
+
* check: async () => {
|
|
60
|
+
* const isConnected = await db.ping();
|
|
61
|
+
* return { status: isConnected ? 'pass' : 'fail' };
|
|
62
|
+
* },
|
|
63
|
+
* critical: true,
|
|
64
|
+
* timeout: 5000
|
|
65
|
+
* },
|
|
66
|
+
* {
|
|
67
|
+
* name: 'cache',
|
|
68
|
+
* check: async () => {
|
|
69
|
+
* const isReady = await redis.ping();
|
|
70
|
+
* return {
|
|
71
|
+
* status: isReady ? 'pass' : 'warn',
|
|
72
|
+
* details: { connected: isReady }
|
|
73
|
+
* };
|
|
74
|
+
* }
|
|
75
|
+
* }
|
|
76
|
+
* ]
|
|
77
|
+
* })
|
|
78
|
+
* class MyApp extends Boot {}
|
|
79
|
+
*/
|
|
80
|
+
export default class HealthCheckEngine extends ExpressiveTeaEngine {
|
|
81
|
+
private checks;
|
|
82
|
+
/**
|
|
83
|
+
* Register a health check
|
|
84
|
+
* @param check - Health check configuration
|
|
85
|
+
* @since 2.0.0
|
|
86
|
+
*/
|
|
87
|
+
registerCheck(check: HealthCheck): void;
|
|
88
|
+
/**
|
|
89
|
+
* Execute a single health check with timeout
|
|
90
|
+
* @param check - Health check to execute
|
|
91
|
+
* @returns Check result
|
|
92
|
+
* @private
|
|
93
|
+
*/
|
|
94
|
+
private executeCheck;
|
|
95
|
+
/**
|
|
96
|
+
* Initialize health check routes
|
|
97
|
+
* @since 2.0.0
|
|
98
|
+
*/
|
|
99
|
+
init(): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Start the health check engine
|
|
102
|
+
* @since 2.0.0
|
|
103
|
+
*/
|
|
104
|
+
start(): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Stop the health check engine
|
|
107
|
+
* @since 2.0.0
|
|
108
|
+
*/
|
|
109
|
+
stop(): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Determine if this engine should be registered
|
|
112
|
+
*
|
|
113
|
+
* Health checks are enabled by default for all applications.
|
|
114
|
+
* To disable, set `enableHealthChecks: false` in ServerSettings.
|
|
115
|
+
*
|
|
116
|
+
* @returns true if health checks should be enabled
|
|
117
|
+
* @since 2.0.0
|
|
118
|
+
*/
|
|
119
|
+
static canRegister(): boolean;
|
|
120
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const inversify_1 = require("inversify");
|
|
5
|
+
const Engine_1 = require("../../classes/Engine");
|
|
6
|
+
/**
|
|
7
|
+
* Health Check Engine
|
|
8
|
+
*
|
|
9
|
+
* Provides standardized health check endpoints for monitoring and orchestration:
|
|
10
|
+
* - `/health` - Detailed health status with all checks
|
|
11
|
+
* - `/health/live` - Liveness probe (always 200 if server is running)
|
|
12
|
+
* - `/health/ready` - Readiness probe (200 only if all critical checks pass)
|
|
13
|
+
*
|
|
14
|
+
* Compatible with Kubernetes liveness and readiness probes.
|
|
15
|
+
*
|
|
16
|
+
* @class HealthCheckEngine
|
|
17
|
+
* @extends ExpressiveTeaEngine
|
|
18
|
+
* @since 2.0.0
|
|
19
|
+
* @summary Standardized health check endpoints for monitoring
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Enable health checks with custom checks
|
|
23
|
+
* @HealthCheck({
|
|
24
|
+
* checks: [
|
|
25
|
+
* {
|
|
26
|
+
* name: 'database',
|
|
27
|
+
* check: async () => {
|
|
28
|
+
* const isConnected = await db.ping();
|
|
29
|
+
* return { status: isConnected ? 'pass' : 'fail' };
|
|
30
|
+
* },
|
|
31
|
+
* critical: true,
|
|
32
|
+
* timeout: 5000
|
|
33
|
+
* },
|
|
34
|
+
* {
|
|
35
|
+
* name: 'cache',
|
|
36
|
+
* check: async () => {
|
|
37
|
+
* const isReady = await redis.ping();
|
|
38
|
+
* return {
|
|
39
|
+
* status: isReady ? 'pass' : 'warn',
|
|
40
|
+
* details: { connected: isReady }
|
|
41
|
+
* };
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* ]
|
|
45
|
+
* })
|
|
46
|
+
* class MyApp extends Boot {}
|
|
47
|
+
*/
|
|
48
|
+
let HealthCheckEngine = class HealthCheckEngine extends Engine_1.default {
|
|
49
|
+
constructor() {
|
|
50
|
+
super(...arguments);
|
|
51
|
+
this.checks = [];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Register a health check
|
|
55
|
+
* @param check - Health check configuration
|
|
56
|
+
* @since 2.0.0
|
|
57
|
+
*/
|
|
58
|
+
registerCheck(check) {
|
|
59
|
+
this.checks.push(check);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Execute a single health check with timeout
|
|
63
|
+
* @param check - Health check to execute
|
|
64
|
+
* @returns Check result
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
async executeCheck(check) {
|
|
68
|
+
const timeout = check.timeout || 5000;
|
|
69
|
+
try {
|
|
70
|
+
const result = await Promise.race([
|
|
71
|
+
Promise.resolve(check.check()),
|
|
72
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Health check timeout')), timeout)),
|
|
73
|
+
]);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
status: 'fail',
|
|
79
|
+
error: error instanceof Error ? error.message : String(error),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Initialize health check routes
|
|
85
|
+
* @since 2.0.0
|
|
86
|
+
*/
|
|
87
|
+
async init() {
|
|
88
|
+
const app = this.context.getApplication();
|
|
89
|
+
// Detailed health endpoint
|
|
90
|
+
app.get('/health', async (_req, res) => {
|
|
91
|
+
const results = {};
|
|
92
|
+
let overallStatus = 'pass';
|
|
93
|
+
// Execute all checks in parallel
|
|
94
|
+
await Promise.all(this.checks.map(async (check) => {
|
|
95
|
+
const result = await this.executeCheck(check);
|
|
96
|
+
results[check.name] = result;
|
|
97
|
+
// Update overall status
|
|
98
|
+
if (result.status === 'fail') {
|
|
99
|
+
overallStatus = 'fail';
|
|
100
|
+
}
|
|
101
|
+
else if (result.status === 'warn' && overallStatus === 'pass') {
|
|
102
|
+
overallStatus = 'warn';
|
|
103
|
+
}
|
|
104
|
+
}));
|
|
105
|
+
const statusCode = overallStatus === 'pass' ? 200 : overallStatus === 'warn' ? 200 : 503;
|
|
106
|
+
res.status(statusCode).json({
|
|
107
|
+
status: overallStatus,
|
|
108
|
+
timestamp: new Date().toISOString(),
|
|
109
|
+
checks: results,
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
// Liveness probe - always returns 200 if server is running
|
|
113
|
+
app.get('/health/live', (_req, res) => {
|
|
114
|
+
res.status(200).json({
|
|
115
|
+
status: 'pass',
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
// Readiness probe - returns 200 only if all critical checks pass
|
|
120
|
+
app.get('/health/ready', async (_req, res) => {
|
|
121
|
+
const criticalChecks = this.checks.filter((c) => c.critical);
|
|
122
|
+
if (criticalChecks.length === 0) {
|
|
123
|
+
// No critical checks, always ready
|
|
124
|
+
res.status(200).json({
|
|
125
|
+
status: 'pass',
|
|
126
|
+
timestamp: new Date().toISOString(),
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const results = {};
|
|
131
|
+
let isReady = true;
|
|
132
|
+
// Execute only critical checks
|
|
133
|
+
await Promise.all(criticalChecks.map(async (check) => {
|
|
134
|
+
const result = await this.executeCheck(check);
|
|
135
|
+
results[check.name] = result;
|
|
136
|
+
if (result.status === 'fail') {
|
|
137
|
+
isReady = false;
|
|
138
|
+
}
|
|
139
|
+
}));
|
|
140
|
+
res.status(isReady ? 200 : 503).json({
|
|
141
|
+
status: isReady ? 'pass' : 'fail',
|
|
142
|
+
timestamp: new Date().toISOString(),
|
|
143
|
+
checks: results,
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Start the health check engine
|
|
149
|
+
* @since 2.0.0
|
|
150
|
+
*/
|
|
151
|
+
async start() {
|
|
152
|
+
// Nothing to start - routes are already registered
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Stop the health check engine
|
|
156
|
+
* @since 2.0.0
|
|
157
|
+
*/
|
|
158
|
+
async stop() {
|
|
159
|
+
// Clear checks on shutdown
|
|
160
|
+
this.checks = [];
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Determine if this engine should be registered
|
|
164
|
+
*
|
|
165
|
+
* Health checks are enabled by default for all applications.
|
|
166
|
+
* To disable, set `enableHealthChecks: false` in ServerSettings.
|
|
167
|
+
*
|
|
168
|
+
* @returns true if health checks should be enabled
|
|
169
|
+
* @since 2.0.0
|
|
170
|
+
*/
|
|
171
|
+
static canRegister() {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
HealthCheckEngine = tslib_1.__decorate([
|
|
176
|
+
(0, inversify_1.injectable)(),
|
|
177
|
+
(0, inversify_1.injectFromBase)({ extendConstructorArguments: true })
|
|
178
|
+
], HealthCheckEngine);
|
|
179
|
+
exports.default = HealthCheckEngine;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as http from 'node:http';
|
|
2
|
+
import * as https from 'node:https';
|
|
3
|
+
import { BOOT_STAGES } from '@expressive-tea/commons';
|
|
4
|
+
import ExpressiveTeaEngine from '../../classes/Engine';
|
|
5
|
+
export default class HTTPEngine extends ExpressiveTeaEngine {
|
|
6
|
+
private listen;
|
|
7
|
+
start(): Promise<(http.Server | https.Server)[]>;
|
|
8
|
+
init(): Promise<void>;
|
|
9
|
+
resolveStages(stages: BOOT_STAGES[], ...extraArgs: unknown[]): Promise<unknown[]>;
|
|
10
|
+
resolveProxyContainers(): void;
|
|
11
|
+
static canRegister(): boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const inversify_1 = require("inversify");
|
|
5
|
+
const boot_helper_1 = require("../../helpers/boot-helper");
|
|
6
|
+
const commons_1 = require("@expressive-tea/commons");
|
|
7
|
+
const commons_2 = require("@expressive-tea/commons");
|
|
8
|
+
const commons_3 = require("@expressive-tea/commons");
|
|
9
|
+
const Engine_1 = require("../../classes/Engine");
|
|
10
|
+
let HTTPEngine = class HTTPEngine extends Engine_1.default {
|
|
11
|
+
async listen(server, port) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
server.listen(port);
|
|
14
|
+
server.on('error', error => {
|
|
15
|
+
reject(error);
|
|
16
|
+
});
|
|
17
|
+
server.on('listening', () => {
|
|
18
|
+
console.log(`Running HTTP Server on [${port}]`);
|
|
19
|
+
resolve(server);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async start() {
|
|
24
|
+
const servers = [
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
26
|
+
await this.listen(this.server, this.settings.get('port')),
|
|
27
|
+
(this.serverSecure) ? await this.listen(this.serverSecure, this.settings.get('securePort')) : null
|
|
28
|
+
];
|
|
29
|
+
const listenerServers = servers.filter((server) => server !== null);
|
|
30
|
+
await this.resolveStages([commons_1.BOOT_STAGES.START], ...listenerServers);
|
|
31
|
+
return listenerServers;
|
|
32
|
+
}
|
|
33
|
+
async init() {
|
|
34
|
+
(0, boot_helper_1.resolveDirectives)(this.context, this.context.getApplication());
|
|
35
|
+
(0, boot_helper_1.resolveStatic)(this.context, this.context.getApplication());
|
|
36
|
+
// HTTP Engine Resolve Stages
|
|
37
|
+
this.resolveProxyContainers();
|
|
38
|
+
await this.resolveStages(commons_1.BOOT_ORDER);
|
|
39
|
+
await this.resolveStages([commons_1.BOOT_STAGES.AFTER_APPLICATION_MIDDLEWARES, commons_1.BOOT_STAGES.ON_HTTP_CREATION], this.server, this.serverSecure);
|
|
40
|
+
}
|
|
41
|
+
async resolveStages(stages, ...extraArgs) {
|
|
42
|
+
return Promise.all(stages.map(async (s) => (0, boot_helper_1.resolveStage)(s, this.context, this.context.getApplication(), ...extraArgs)));
|
|
43
|
+
}
|
|
44
|
+
resolveProxyContainers() {
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
46
|
+
const ProxyContainers = commons_3.Metadata.get(commons_1.ROUTER_PROXIES_KEY, (0, commons_2.getClass)(this.context)) || [];
|
|
47
|
+
for (const Container of ProxyContainers) {
|
|
48
|
+
(0, boot_helper_1.resolveProxy)(Container, this.context.getApplication());
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
static canRegister() {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
HTTPEngine = tslib_1.__decorate([
|
|
56
|
+
(0, inversify_1.injectable)(),
|
|
57
|
+
(0, inversify_1.injectFromBase)({ extendConstructorArguments: true })
|
|
58
|
+
], HTTPEngine);
|
|
59
|
+
exports.default = HTTPEngine;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Engine Registration
|
|
3
|
+
*
|
|
4
|
+
* Automatically registers all core Expressive Tea engines with the EngineRegistry.
|
|
5
|
+
* Import this file to enable all core engines with proper dependency order.
|
|
6
|
+
*
|
|
7
|
+
* Engine Priority Order:
|
|
8
|
+
* - 0: HTTPEngine (base engine, no dependencies)
|
|
9
|
+
* - 5: HealthCheckEngine (health endpoints, depends on http)
|
|
10
|
+
* - 10: SocketIOEngine, WebsocketEngine (depend on http)
|
|
11
|
+
* - 20: TeapotEngine, TeacupEngine (depend on http, socketio)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import '@expressive-tea/core/engines'; // Registers all core engines
|
|
16
|
+
* import Boot from '@expressive-tea/core';
|
|
17
|
+
*
|
|
18
|
+
* class MyApp extends Boot {}
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @module engines
|
|
22
|
+
* @since 2.0.0
|
|
23
|
+
*/
|
|
24
|
+
import EngineRegistry from '../classes/EngineRegistry';
|
|
25
|
+
import HTTPEngine from './http';
|
|
26
|
+
import HealthCheckEngine from './health';
|
|
27
|
+
import SocketIOEngine from './socketio';
|
|
28
|
+
import WebsocketEngine from './websocket';
|
|
29
|
+
import TeapotEngine from './teapot';
|
|
30
|
+
import TeacupEngine from './teacup';
|
|
31
|
+
export { HTTPEngine, HealthCheckEngine, SocketIOEngine, WebsocketEngine, TeapotEngine, TeacupEngine };
|
|
32
|
+
export default EngineRegistry;
|
package/engines/index.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Core Engine Registration
|
|
4
|
+
*
|
|
5
|
+
* Automatically registers all core Expressive Tea engines with the EngineRegistry.
|
|
6
|
+
* Import this file to enable all core engines with proper dependency order.
|
|
7
|
+
*
|
|
8
|
+
* Engine Priority Order:
|
|
9
|
+
* - 0: HTTPEngine (base engine, no dependencies)
|
|
10
|
+
* - 5: HealthCheckEngine (health endpoints, depends on http)
|
|
11
|
+
* - 10: SocketIOEngine, WebsocketEngine (depend on http)
|
|
12
|
+
* - 20: TeapotEngine, TeacupEngine (depend on http, socketio)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import '@expressive-tea/core/engines'; // Registers all core engines
|
|
17
|
+
* import Boot from '@expressive-tea/core';
|
|
18
|
+
*
|
|
19
|
+
* class MyApp extends Boot {}
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @module engines
|
|
23
|
+
* @since 2.0.0
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.TeacupEngine = exports.TeapotEngine = exports.WebsocketEngine = exports.SocketIOEngine = exports.HealthCheckEngine = exports.HTTPEngine = void 0;
|
|
27
|
+
const EngineRegistry_1 = require("../classes/EngineRegistry");
|
|
28
|
+
const http_1 = require("./http");
|
|
29
|
+
exports.HTTPEngine = http_1.default;
|
|
30
|
+
const health_1 = require("./health");
|
|
31
|
+
exports.HealthCheckEngine = health_1.default;
|
|
32
|
+
const socketio_1 = require("./socketio");
|
|
33
|
+
exports.SocketIOEngine = socketio_1.default;
|
|
34
|
+
const websocket_1 = require("./websocket");
|
|
35
|
+
exports.WebsocketEngine = websocket_1.default;
|
|
36
|
+
const teapot_1 = require("./teapot");
|
|
37
|
+
exports.TeapotEngine = teapot_1.default;
|
|
38
|
+
const teacup_1 = require("./teacup");
|
|
39
|
+
exports.TeacupEngine = teacup_1.default;
|
|
40
|
+
/**
|
|
41
|
+
* Register HTTP Engine
|
|
42
|
+
* Priority: 0 (runs first)
|
|
43
|
+
* Dependencies: none
|
|
44
|
+
*/
|
|
45
|
+
EngineRegistry_1.default.register({
|
|
46
|
+
engine: http_1.default,
|
|
47
|
+
name: 'http',
|
|
48
|
+
version: '2.0.0',
|
|
49
|
+
priority: 0,
|
|
50
|
+
dependencies: []
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* Register Health Check Engine
|
|
54
|
+
* Priority: 5
|
|
55
|
+
* Dependencies: http (needs HTTP server for endpoints)
|
|
56
|
+
*/
|
|
57
|
+
EngineRegistry_1.default.register({
|
|
58
|
+
engine: health_1.default,
|
|
59
|
+
name: 'health',
|
|
60
|
+
version: '2.0.0',
|
|
61
|
+
priority: 5,
|
|
62
|
+
dependencies: ['http']
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Register SocketIO Engine
|
|
66
|
+
* Priority: 10
|
|
67
|
+
* Dependencies: http (needs HTTP server to attach to)
|
|
68
|
+
*/
|
|
69
|
+
EngineRegistry_1.default.register({
|
|
70
|
+
engine: socketio_1.default,
|
|
71
|
+
name: 'socketio',
|
|
72
|
+
version: '2.0.0',
|
|
73
|
+
priority: 10,
|
|
74
|
+
dependencies: ['http']
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Register Websocket Engine
|
|
78
|
+
* Priority: 10
|
|
79
|
+
* Dependencies: http (needs HTTP server to attach to)
|
|
80
|
+
*/
|
|
81
|
+
EngineRegistry_1.default.register({
|
|
82
|
+
engine: websocket_1.default,
|
|
83
|
+
name: 'websocket',
|
|
84
|
+
version: '2.0.0',
|
|
85
|
+
priority: 10,
|
|
86
|
+
dependencies: ['http']
|
|
87
|
+
});
|
|
88
|
+
/**
|
|
89
|
+
* Register Teapot Engine (Microservice Gateway Server)
|
|
90
|
+
* Priority: 20
|
|
91
|
+
* Dependencies: http, socketio
|
|
92
|
+
*/
|
|
93
|
+
EngineRegistry_1.default.register({
|
|
94
|
+
engine: teapot_1.default,
|
|
95
|
+
name: 'teapot',
|
|
96
|
+
version: '2.0.0',
|
|
97
|
+
priority: 20,
|
|
98
|
+
dependencies: ['http', 'socketio']
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* Register Teacup Engine (Microservice Gateway Client)
|
|
102
|
+
* Priority: 20
|
|
103
|
+
* Dependencies: http, socketio
|
|
104
|
+
*/
|
|
105
|
+
EngineRegistry_1.default.register({
|
|
106
|
+
engine: teacup_1.default,
|
|
107
|
+
name: 'teacup',
|
|
108
|
+
version: '2.0.0',
|
|
109
|
+
priority: 20,
|
|
110
|
+
dependencies: ['http', 'socketio']
|
|
111
|
+
});
|
|
112
|
+
exports.default = EngineRegistry_1.default;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const socket_io_1 = require("socket.io");
|
|
5
|
+
const inversify_1 = require("inversify");
|
|
6
|
+
const Engine_1 = require("../../classes/Engine");
|
|
7
|
+
const commons_1 = require("@expressive-tea/commons");
|
|
8
|
+
const constants_1 = require("../constants/constants");
|
|
9
|
+
let SocketIOEngine = class SocketIOEngine extends Engine_1.default {
|
|
10
|
+
init() {
|
|
11
|
+
const commonConfig = {
|
|
12
|
+
path: '/exp-tea/',
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
transports: ['websocket', 'polling']
|
|
15
|
+
};
|
|
16
|
+
this.io = this.server && new socket_io_1.Server(this.server, Object.assign({}, commonConfig));
|
|
17
|
+
this.ioSecure = this.serverSecure && new socket_io_1.Server(this.serverSecure, Object.assign({}, commonConfig));
|
|
18
|
+
commons_1.Metadata.set(constants_1.SOCKET_IO_INSTANCE_KEY, this.io, this.context);
|
|
19
|
+
commons_1.Metadata.set(constants_1.SOCKET_IO_SECURE_INSTANCE_KEY, this.ioSecure, this.context);
|
|
20
|
+
}
|
|
21
|
+
static canRegister() {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
SocketIOEngine = tslib_1.__decorate([
|
|
26
|
+
(0, inversify_1.injectable)(),
|
|
27
|
+
(0, inversify_1.injectFromBase)({ extendConstructorArguments: true })
|
|
28
|
+
], SocketIOEngine);
|
|
29
|
+
exports.default = SocketIOEngine;
|
|
30
|
+
;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import ExpressiveTeaEngine from '../../classes/Engine';
|
|
2
|
+
import Boot from '../../classes/Boot';
|
|
3
|
+
export default class TeacupEngine extends ExpressiveTeaEngine {
|
|
4
|
+
private teacupSettings;
|
|
5
|
+
private publicKey;
|
|
6
|
+
private privateKey;
|
|
7
|
+
private publicServerKey;
|
|
8
|
+
private serverSignature;
|
|
9
|
+
private clientSignature;
|
|
10
|
+
private client;
|
|
11
|
+
private isStopping;
|
|
12
|
+
private header;
|
|
13
|
+
private handshaked;
|
|
14
|
+
private accepted;
|
|
15
|
+
start(): Promise<void>;
|
|
16
|
+
static canRegister(ctx?: Boot): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Graceful shutdown for TeacupEngine
|
|
19
|
+
*
|
|
20
|
+
* Disconnects the socket.io-client connection and prevents automatic reconnection.
|
|
21
|
+
* This method is idempotent and safe to call multiple times.
|
|
22
|
+
*
|
|
23
|
+
* @returns {Promise<void>} Promise that resolves when cleanup is complete
|
|
24
|
+
* @since 2.0.0
|
|
25
|
+
*/
|
|
26
|
+
stop(): Promise<void>;
|
|
27
|
+
}
|