keypointjs 1.1.1 → 1.2.2
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 +108 -677
- package/package.json +21 -13
- package/src/core/BPE.js +47 -0
- package/src/core/GrpcEngine.js +209 -0
- package/src/core/HttpEngine.js +107 -0
- package/src/core/PA.js +169 -0
- package/src/core/ProtocolEngine.js +566 -182
- package/src/core/WsEngine.js +333 -0
- package/src/keypointJS.js +360 -95
package/src/keypointJS.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
|
-
KeypointJS Main Module © 2026
|
|
2
|
+
KeypointJS Main Module © 2026 - By AnasBex
|
|
3
3
|
__________________________________________
|
|
4
|
+
Do not make changes to the core of this file, unless you understand all of its code structure and paths.
|
|
4
5
|
|
|
5
6
|
*/
|
|
6
7
|
|
|
@@ -22,22 +23,28 @@ import { AccessDecision } from './policy/AccessDecision.js';
|
|
|
22
23
|
|
|
23
24
|
export class KeypointJS {
|
|
24
25
|
constructor(options = {}) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
this.options = {
|
|
27
|
+
requireKeypoint: true,
|
|
28
|
+
strictMode: true,
|
|
29
|
+
validateOrigin: true,
|
|
30
|
+
validateProtocol: true,
|
|
31
|
+
enableCORS: false,
|
|
32
|
+
corsOrigins: ['*'],
|
|
33
|
+
maxRequestSize: '10mb',
|
|
34
|
+
defaultResponseHeaders: {
|
|
35
|
+
'X-Powered-By': 'KeypointJS',
|
|
36
|
+
'X-Content-Type-Options': 'nosniff'
|
|
37
|
+
},
|
|
38
|
+
errorHandler: this.defaultErrorHandler.bind(this),
|
|
39
|
+
trustedProxies: [],
|
|
40
|
+
// NEW OPTIONS FOR MULTI-PROTOCOL:
|
|
41
|
+
enableWebSocket: true, // Enable WebSocket support
|
|
42
|
+
enableGrpc: false, // Enable gRPC support
|
|
43
|
+
enableHttp2: true, // Enable HTTP/2
|
|
44
|
+
enableHttp3: false, // Enable HTTP/3
|
|
45
|
+
protocolEngines: {}, // Custom protocol engines
|
|
46
|
+
...options
|
|
47
|
+
};
|
|
41
48
|
|
|
42
49
|
// Initialize core components
|
|
43
50
|
this.initializeCore();
|
|
@@ -98,12 +105,17 @@ export class KeypointJS {
|
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
initializeCore() {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
// Core protocol engine with multi-protocol support
|
|
109
|
+
this.protocolEngine = new ProtocolEngine({
|
|
110
|
+
maxBodySize: this.options.maxRequestSize,
|
|
111
|
+
parseJSON: true,
|
|
112
|
+
parseForm: true,
|
|
113
|
+
validateProtocol: this.options.validateProtocol,
|
|
114
|
+
trustedProxies: this.options.trustedProxies,
|
|
115
|
+
enableWebSocket: this.options.enableWebSocket,
|
|
116
|
+
enableGrpc: this.options.enableGrpc,
|
|
117
|
+
protocolEngines: this.options.protocolEngines
|
|
118
|
+
});
|
|
107
119
|
|
|
108
120
|
// Keypoint system
|
|
109
121
|
this.keypointStorage = this.options.keypointStorage || new MemoryKeypointStorage();
|
|
@@ -126,6 +138,107 @@ export class KeypointJS {
|
|
|
126
138
|
this.wsGuard = null;
|
|
127
139
|
}
|
|
128
140
|
|
|
141
|
+
// NEW METHOD: Create multi-protocol server
|
|
142
|
+
createMultiProtocolServer() {
|
|
143
|
+
return new Promise(async (resolve, reject) => {
|
|
144
|
+
try {
|
|
145
|
+
const servers = {};
|
|
146
|
+
const http = await import('http');
|
|
147
|
+
const https = await import('https');
|
|
148
|
+
|
|
149
|
+
// Create HTTP server
|
|
150
|
+
servers.http = http.createServer(async (req, res) => {
|
|
151
|
+
await this.handleHttpRequest(req, res);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Create HTTPS server if certs provided
|
|
155
|
+
if (this.options.https) {
|
|
156
|
+
servers.https = https.createServer(
|
|
157
|
+
this.options.https,
|
|
158
|
+
async (req, res) => {
|
|
159
|
+
await this.handleHttpRequest(req, res);
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Setup WebSocket support
|
|
165
|
+
if (this.wsGuard && this.options.enableWebSocket) {
|
|
166
|
+
this.wsGuard.attachToServer(servers.http, this);
|
|
167
|
+
if (servers.https) {
|
|
168
|
+
this.wsGuard.attachToServer(servers.https, this);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Setup gRPC server if enabled
|
|
173
|
+
if (this.options.enableGrpc) {
|
|
174
|
+
servers.grpc = await this.createGrpcServer();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
resolve(servers);
|
|
178
|
+
|
|
179
|
+
} catch (error) {
|
|
180
|
+
reject(new Error(`Failed to create servers: ${error.message}`));
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// NEW METHOD: Handle HTTP requests (supports HTTP/HTTPS)
|
|
186
|
+
async handleHttpRequest(req, res) {
|
|
187
|
+
try {
|
|
188
|
+
const response = await this.handleRequest(req, res);
|
|
189
|
+
|
|
190
|
+
res.statusCode = response.status || 200;
|
|
191
|
+
|
|
192
|
+
// Set headers
|
|
193
|
+
if (response.headers) {
|
|
194
|
+
Object.entries(response.headers).forEach(([key, value]) => {
|
|
195
|
+
if (value !== undefined && value !== null) {
|
|
196
|
+
res.setHeader(key, value);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Send body
|
|
202
|
+
if (response.body !== undefined && response.body !== null) {
|
|
203
|
+
const body = typeof response.body === 'string'
|
|
204
|
+
? response.body
|
|
205
|
+
: JSON.stringify(response.body);
|
|
206
|
+
res.end(body);
|
|
207
|
+
} else {
|
|
208
|
+
res.end();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error('HTTP request error:', error);
|
|
213
|
+
res.statusCode = 500;
|
|
214
|
+
res.setHeader('Content-Type', 'application/json');
|
|
215
|
+
res.end(JSON.stringify({
|
|
216
|
+
error: 'Internal Server Error',
|
|
217
|
+
timestamp: new Date().toISOString()
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// NEW METHOD: Create gRPC server
|
|
223
|
+
async createGrpcServer() {
|
|
224
|
+
try {
|
|
225
|
+
// Note: In production, use @grpc/grpc-js
|
|
226
|
+
console.log('gRPC server support requires additional setup');
|
|
227
|
+
console.log('Install: npm install @grpc/grpc-js @grpc/proto-loader');
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
start: (port) => {
|
|
231
|
+
console.log(`gRPC server would start on port ${port}`);
|
|
232
|
+
console.log('See docs for gRPC implementation');
|
|
233
|
+
},
|
|
234
|
+
stop: () => console.log('gRPC server stopped')
|
|
235
|
+
};
|
|
236
|
+
} catch (error) {
|
|
237
|
+
console.warn('gRPC support not available:', error.message);
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
129
242
|
initializeLayers() {
|
|
130
243
|
// Layer 0: Pre-processing (hooks)
|
|
131
244
|
this.use(async (ctx, next) => {
|
|
@@ -134,43 +247,58 @@ export class KeypointJS {
|
|
|
134
247
|
});
|
|
135
248
|
|
|
136
249
|
// Layer 1: Protocol Engine
|
|
250
|
+
// Protocol Engine (UPDATED for multi-protocol)
|
|
137
251
|
this.use(async (ctx, next) => {
|
|
138
252
|
try {
|
|
139
|
-
// Make sure ctx.request is a native Node.js Request object.
|
|
140
253
|
if (!ctx.request || typeof ctx.request !== 'object') {
|
|
141
254
|
throw new ProtocolError('Invalid request object', 400);
|
|
142
255
|
}
|
|
143
256
|
|
|
144
257
|
const processed = await this.protocolEngine.process(ctx.request);
|
|
145
258
|
|
|
146
|
-
//
|
|
259
|
+
// Store original protocol before context updates
|
|
260
|
+
const originalProtocol = processed.protocol;
|
|
261
|
+
|
|
262
|
+
// Update context
|
|
147
263
|
Object.assign(ctx, {
|
|
148
264
|
id: processed.id,
|
|
149
265
|
timestamp: processed.timestamp,
|
|
150
266
|
metadata: {
|
|
151
267
|
...ctx.metadata,
|
|
152
|
-
...processed.metadata
|
|
268
|
+
...processed.metadata,
|
|
269
|
+
protocolEngine: processed.metadata.engine,
|
|
270
|
+
protocolVersion: processed.metadata.protocolVersion
|
|
153
271
|
}
|
|
154
272
|
});
|
|
155
273
|
|
|
156
|
-
//
|
|
274
|
+
// Preserve original request and add processed data
|
|
157
275
|
ctx.request = {
|
|
158
276
|
...ctx.request,
|
|
159
277
|
...processed.request,
|
|
160
|
-
originalRequest: ctx.request
|
|
278
|
+
originalRequest: ctx.request
|
|
161
279
|
};
|
|
162
280
|
|
|
163
|
-
// Set protocol
|
|
164
|
-
ctx.setState('_protocol',
|
|
281
|
+
// Set protocol-specific properties
|
|
282
|
+
ctx.setState('_protocol', originalProtocol);
|
|
165
283
|
ctx.setState('_ip', processed.request?.ip || '0.0.0.0');
|
|
284
|
+
ctx._protocol = originalProtocol;
|
|
166
285
|
|
|
167
|
-
//
|
|
168
|
-
if (
|
|
169
|
-
ctx.
|
|
286
|
+
// Add protocol-specific helpers based on detected protocol
|
|
287
|
+
if (originalProtocol.startsWith('ws')) {
|
|
288
|
+
ctx.isWebSocket = true;
|
|
289
|
+
ctx.webSocket = {
|
|
290
|
+
key: processed.request?.key,
|
|
291
|
+
version: processed.request?.version
|
|
292
|
+
};
|
|
293
|
+
} else if (originalProtocol.startsWith('grpc')) {
|
|
294
|
+
ctx.isGrpc = true;
|
|
295
|
+
ctx.grpc = {
|
|
296
|
+
service: processed.request?.service,
|
|
297
|
+
method: processed.request?.method
|
|
298
|
+
};
|
|
170
299
|
}
|
|
171
300
|
|
|
172
301
|
} catch (error) {
|
|
173
|
-
// Use ProtocolError if available, otherwise KeypointError
|
|
174
302
|
if (error.name === 'ProtocolError') {
|
|
175
303
|
throw error;
|
|
176
304
|
}
|
|
@@ -469,18 +597,20 @@ this.use(async (ctx, next) => {
|
|
|
469
597
|
this.stats.requests++;
|
|
470
598
|
|
|
471
599
|
try {
|
|
472
|
-
// Run the middleware chain
|
|
473
600
|
await this.runMiddlewareChain(ctx);
|
|
474
601
|
this.stats.successful++;
|
|
475
602
|
|
|
476
|
-
//
|
|
603
|
+
// Track protocol usage
|
|
604
|
+
const protocol = ctx.protocol || 'unknown';
|
|
605
|
+
if (!this.stats.protocols) this.stats.protocols = {};
|
|
606
|
+
this.stats.protocols[protocol] = (this.stats.protocols[protocol] || 0) + 1;
|
|
607
|
+
|
|
477
608
|
this.emit('request:success', {
|
|
478
609
|
ctx,
|
|
479
610
|
timestamp: new Date(),
|
|
480
611
|
duration: ctx.response?.duration || 0
|
|
481
612
|
});
|
|
482
613
|
|
|
483
|
-
// Return response
|
|
484
614
|
return ctx.response || {
|
|
485
615
|
status: 404,
|
|
486
616
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -490,14 +620,12 @@ this.use(async (ctx, next) => {
|
|
|
490
620
|
} catch (error) {
|
|
491
621
|
this.stats.failed++;
|
|
492
622
|
|
|
493
|
-
// Emit error event
|
|
494
623
|
this.emit('request:error', {
|
|
495
624
|
ctx,
|
|
496
625
|
error,
|
|
497
626
|
timestamp: new Date()
|
|
498
627
|
});
|
|
499
628
|
|
|
500
|
-
// Handle error via error handler
|
|
501
629
|
return this.options.errorHandler(error, ctx, response);
|
|
502
630
|
}
|
|
503
631
|
}
|
|
@@ -568,53 +696,136 @@ createServer() {
|
|
|
568
696
|
});
|
|
569
697
|
}
|
|
570
698
|
|
|
571
|
-
//
|
|
699
|
+
// listen method with multi-protocol support
|
|
572
700
|
listen(port, hostname = '0.0.0.0', callback) {
|
|
573
701
|
return new Promise(async (resolve, reject) => {
|
|
574
702
|
try {
|
|
575
|
-
const
|
|
703
|
+
const servers = await this.createMultiProtocolServer();
|
|
576
704
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
const
|
|
580
|
-
|
|
705
|
+
// Start HTTP server
|
|
706
|
+
servers.http.listen(port, hostname, () => {
|
|
707
|
+
const address = servers.http.address();
|
|
708
|
+
this.logServerStart(address, servers);
|
|
581
709
|
|
|
582
|
-
|
|
710
|
+
if (callback) callback(servers);
|
|
711
|
+
resolve(servers);
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
// Start HTTPS server if available
|
|
715
|
+
if (servers.https) {
|
|
716
|
+
const httpsPort = this.options.httpsPort || port + 1;
|
|
717
|
+
servers.https.listen(httpsPort, hostname, () => {
|
|
718
|
+
console.log(`HTTPS server started on port ${httpsPort}`);
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Start gRPC server if available
|
|
723
|
+
if (servers.grpc && this.options.enableGrpc) {
|
|
724
|
+
const grpcPort = this.options.grpcPort || port + 2;
|
|
725
|
+
servers.grpc.start(grpcPort);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Error handling
|
|
729
|
+
servers.http.on('error', (error) => {
|
|
730
|
+
this.emit('server:error', { protocol: 'http', error, timestamp: new Date() });
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
// Graceful shutdown
|
|
734
|
+
process.on('SIGTERM', () => this.shutdown(servers));
|
|
735
|
+
process.on('SIGINT', () => this.shutdown(servers));
|
|
736
|
+
|
|
737
|
+
} catch (error) {
|
|
738
|
+
reject(error);
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// NEW METHOD: Improved server startup logging
|
|
744
|
+
logServerStart(address, servers) {
|
|
745
|
+
const actualHost = address.address;
|
|
746
|
+
const actualPort = address.port;
|
|
747
|
+
|
|
748
|
+
const protocols = ['HTTP'];
|
|
749
|
+
if (servers.https) protocols.push('HTTPS');
|
|
750
|
+
if (this.options.enableWebSocket) protocols.push('WebSocket');
|
|
751
|
+
if (this.options.enableGrpc) protocols.push('gRPC');
|
|
752
|
+
|
|
753
|
+
const protocolStr = protocols.join(' / ');
|
|
754
|
+
|
|
755
|
+
console.log(`
|
|
583
756
|
╔═══════════════════════════════════════════════╗
|
|
584
757
|
║ KeypointJS Server Started ║
|
|
585
758
|
╠═══════════════════════════════════════════════╣
|
|
586
759
|
║ Address: ${actualHost}:${actualPort}${' '.repeat(20 - (actualHost.length + actualPort.toString().length))}║
|
|
587
760
|
║ Mode: ${this.options.requireKeypoint ? 'Strict' : 'Permissive'}${' '.repeat(25 - (this.options.requireKeypoint ? 6 : 9))}║
|
|
588
|
-
║ Protocols:
|
|
761
|
+
║ Protocols: ${protocolStr}${' '.repeat(25 - protocolStr.length)}║
|
|
589
762
|
║ Plugins: ${this.pluginManager.getPluginNames().length} loaded${' '.repeat(20 - this.pluginManager.getPluginNames().length.toString().length)}║
|
|
590
763
|
║ Keypoints: ${this.keypointStorage.store.size} registered${' '.repeat(20 - this.keypointStorage.store.size.toString().length)}║
|
|
764
|
+
║ Engines: ${this.protocolEngine.engines.size} available${' '.repeat(20 - this.protocolEngine.engines.size.toString().length)}║
|
|
591
765
|
╚═══════════════════════════════════════════════╝
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
766
|
+
`);
|
|
767
|
+
|
|
768
|
+
this.emit('server:started', {
|
|
769
|
+
host: actualHost,
|
|
770
|
+
port: actualPort,
|
|
771
|
+
protocols,
|
|
772
|
+
timestamp: new Date()
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// Protocol-specific configuration methods
|
|
777
|
+
enableProtocol(protocol, options = {}) {
|
|
778
|
+
switch (protocol.toLowerCase()) {
|
|
779
|
+
case 'websocket':
|
|
780
|
+
case 'ws':
|
|
781
|
+
this.options.enableWebSocket = true;
|
|
782
|
+
if (!this.wsGuard) {
|
|
783
|
+
this.enableWebSocket(options);
|
|
784
|
+
}
|
|
785
|
+
break;
|
|
604
786
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
787
|
+
case 'grpc':
|
|
788
|
+
this.options.enableGrpc = true;
|
|
789
|
+
this.configureProtocolEngine({ enableGrpc: true });
|
|
790
|
+
break;
|
|
609
791
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
792
|
+
case 'http2':
|
|
793
|
+
this.options.enableHttp2 = true;
|
|
794
|
+
this.configureProtocolEngine({ http2: true });
|
|
795
|
+
break;
|
|
613
796
|
|
|
614
|
-
|
|
615
|
-
|
|
797
|
+
default:
|
|
798
|
+
console.warn(`Unknown protocol: ${protocol}`);
|
|
799
|
+
}
|
|
800
|
+
return this;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Get available protocols
|
|
804
|
+
getAvailableProtocols() {
|
|
805
|
+
const protocols = Array.from(this.protocolEngine.engines.keys());
|
|
806
|
+
const available = [];
|
|
807
|
+
|
|
808
|
+
for (const protocol of protocols) {
|
|
809
|
+
if (protocol === 'http' || protocol === 'https') {
|
|
810
|
+
available.push(protocol.toUpperCase());
|
|
811
|
+
} else if (protocol === 'ws' || protocol === 'wss') {
|
|
812
|
+
if (this.options.enableWebSocket) {
|
|
813
|
+
available.push('WebSocket');
|
|
814
|
+
}
|
|
815
|
+
} else if (protocol.startsWith('grpc')) {
|
|
816
|
+
if (this.options.enableGrpc) {
|
|
817
|
+
available.push('gRPC');
|
|
818
|
+
}
|
|
616
819
|
}
|
|
617
|
-
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
return [...new Set(available)]; // Remove duplicates
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// Register custom protocol engine
|
|
826
|
+
registerProtocolEngine(protocol, engine) {
|
|
827
|
+
this.protocolEngine.registerEngine(protocol, engine);
|
|
828
|
+
return this;
|
|
618
829
|
}
|
|
619
830
|
|
|
620
831
|
|
|
@@ -709,32 +920,45 @@ listen(port, hostname = '0.0.0.0', callback) {
|
|
|
709
920
|
// Statistics
|
|
710
921
|
|
|
711
922
|
getStats() {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
: '0%',
|
|
721
|
-
plugins: this.pluginManager.getStats(),
|
|
722
|
-
keypoints: {
|
|
723
|
-
total: this.keypointStorage.store.size,
|
|
724
|
-
expired: (async () => {
|
|
725
|
-
const all = await this.keypointStorage.list();
|
|
726
|
-
return all.filter(k => k.isExpired()).length;
|
|
727
|
-
})(),
|
|
728
|
-
active: (async () => {
|
|
729
|
-
const all = await this.keypointStorage.list();
|
|
730
|
-
return all.filter(k => !k.isExpired()).length;
|
|
731
|
-
})()
|
|
732
|
-
},
|
|
733
|
-
routes: this.router.routes.size,
|
|
734
|
-
policies: this.policyEngine.rules.length
|
|
735
|
-
};
|
|
923
|
+
const uptime = Date.now() - this.stats.startTime;
|
|
924
|
+
|
|
925
|
+
// Get protocol distribution from recent requests
|
|
926
|
+
const protocolStats = {};
|
|
927
|
+
if (this.stats.protocols) {
|
|
928
|
+
for (const [protocol, count] of Object.entries(this.stats.protocols)) {
|
|
929
|
+
protocolStats[protocol] = count;
|
|
930
|
+
}
|
|
736
931
|
}
|
|
737
932
|
|
|
933
|
+
return {
|
|
934
|
+
...this.stats,
|
|
935
|
+
uptime,
|
|
936
|
+
uptimeFormatted: this.formatUptime(uptime),
|
|
937
|
+
successRate: this.stats.requests > 0 ?
|
|
938
|
+
(this.stats.successful / this.stats.requests * 100).toFixed(2) + '%' :
|
|
939
|
+
'0%',
|
|
940
|
+
protocols: {
|
|
941
|
+
available: this.getAvailableProtocols(),
|
|
942
|
+
distribution: protocolStats,
|
|
943
|
+
engines: this.protocolEngine.engines.size
|
|
944
|
+
},
|
|
945
|
+
plugins: this.pluginManager.getStats(),
|
|
946
|
+
keypoints: {
|
|
947
|
+
total: this.keypointStorage.store.size,
|
|
948
|
+
expired: (async () => {
|
|
949
|
+
const all = await this.keypointStorage.list();
|
|
950
|
+
return all.filter(k => k.isExpired()).length;
|
|
951
|
+
})(),
|
|
952
|
+
active: (async () => {
|
|
953
|
+
const all = await this.keypointStorage.list();
|
|
954
|
+
return all.filter(k => !k.isExpired()).length;
|
|
955
|
+
})()
|
|
956
|
+
},
|
|
957
|
+
routes: this.router.routes.size,
|
|
958
|
+
policies: this.policyEngine.rules.length
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
|
|
738
962
|
formatUptime(ms) {
|
|
739
963
|
const seconds = Math.floor(ms / 1000);
|
|
740
964
|
const days = Math.floor(seconds / 86400);
|
|
@@ -846,9 +1070,41 @@ export class ValidationError extends Error {
|
|
|
846
1070
|
|
|
847
1071
|
// Export utilities
|
|
848
1072
|
|
|
1073
|
+
// At the bottom of the file, add example exports
|
|
1074
|
+
export const ProtocolExamples = {
|
|
1075
|
+
// Example WebSocket configuration
|
|
1076
|
+
webSocketConfig: {
|
|
1077
|
+
path: '/ws',
|
|
1078
|
+
requireKeypoint: true,
|
|
1079
|
+
pingInterval: 30000,
|
|
1080
|
+
maxConnections: 1000
|
|
1081
|
+
},
|
|
1082
|
+
|
|
1083
|
+
// Example gRPC configuration
|
|
1084
|
+
grpcConfig: {
|
|
1085
|
+
enableReflection: true,
|
|
1086
|
+
maxMessageSize: '4mb',
|
|
1087
|
+
keepaliveTime: 7200000
|
|
1088
|
+
},
|
|
1089
|
+
|
|
1090
|
+
// Example multi-protocol configuration
|
|
1091
|
+
multiProtocolConfig: {
|
|
1092
|
+
enableWebSocket: true,
|
|
1093
|
+
enableGrpc: true,
|
|
1094
|
+
enableHttp2: true,
|
|
1095
|
+
trustedProxies: ['192.168.1.0/24', '10.0.0.0/8'],
|
|
1096
|
+
protocolEngines: {
|
|
1097
|
+
// Custom protocol engines can be added here
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
|
|
849
1102
|
export {
|
|
850
1103
|
Context,
|
|
851
1104
|
ProtocolEngine,
|
|
1105
|
+
ProtocolError,
|
|
1106
|
+
// Protocol engines (optional exports)
|
|
1107
|
+
// Note: These are re-exported from ProtocolEngine.js
|
|
852
1108
|
Keypoint,
|
|
853
1109
|
KeypointContext,
|
|
854
1110
|
KeypointValidator,
|
|
@@ -861,5 +1117,14 @@ export {
|
|
|
861
1117
|
BuiltInHooks,
|
|
862
1118
|
RateLimiter,
|
|
863
1119
|
AuditLogger,
|
|
864
|
-
WebSocketGuard
|
|
865
|
-
|
|
1120
|
+
WebSocketGuard,
|
|
1121
|
+
AccessDecision,
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1124
|
+
// TypeScript/IntelliSense,
|
|
1125
|
+
/*
|
|
1126
|
+
* @typedef {import('./core/ProtocolEngine.js').HttpEngine} HttpEngine
|
|
1127
|
+
* @typedef {import('./core/ProtocolEngine.js').GrpcEngine} GrpcEngine
|
|
1128
|
+
* @typedef {import('./core/ProtocolEngine.js').WsEngine} WsEngine
|
|
1129
|
+
* @typedef {import('./core/ProtocolEngine.js').ProtocolAdapter} ProtocolAdapter
|
|
1130
|
+
*/
|