@principal-ai/control-tower-core 0.2.1 → 0.3.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/dist/client/BaseClient.d.ts +23 -0
- package/dist/client/BaseClient.d.ts.map +1 -1
- package/dist/client/BaseClient.js +60 -0
- package/dist/client/PresenceClient.d.ts +43 -8
- package/dist/client/PresenceClient.d.ts.map +1 -1
- package/dist/client/PresenceClient.js +72 -18
- package/dist/generated/client-connection-auth.types.d.ts +312 -0
- package/dist/generated/client-connection-auth.types.d.ts.map +1 -0
- package/dist/generated/client-connection-auth.types.js +11 -0
- package/dist/generated/control-tower-execution.types.d.ts +445 -0
- package/dist/generated/control-tower-execution.types.d.ts.map +1 -0
- package/dist/generated/control-tower-execution.types.js +11 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +6 -6
- package/dist/index.mjs +94 -7
- package/dist/index.mjs.map +6 -6
- package/dist/server/BaseServer.d.ts +18 -1
- package/dist/server/BaseServer.d.ts.map +1 -1
- package/dist/server/BaseServer.js +15 -1
- package/dist/server/ServerBuilder.d.ts +22 -1
- package/dist/server/ServerBuilder.d.ts.map +1 -1
- package/dist/server/ServerBuilder.js +24 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/telemetry/EventValidationIntegration.d.ts +135 -0
- package/dist/telemetry/EventValidationIntegration.d.ts.map +1 -0
- package/dist/telemetry/EventValidationIntegration.js +253 -0
- package/dist/telemetry/EventValidationIntegration.test.d.ts +7 -0
- package/dist/telemetry/EventValidationIntegration.test.d.ts.map +1 -0
- package/dist/telemetry/EventValidationIntegration.test.js +322 -0
- package/dist/telemetry/TelemetryCapture.d.ts +268 -0
- package/dist/telemetry/TelemetryCapture.d.ts.map +1 -0
- package/dist/telemetry/TelemetryCapture.js +263 -0
- package/dist/telemetry/TelemetryCapture.test.d.ts +7 -0
- package/dist/telemetry/TelemetryCapture.test.d.ts.map +1 -0
- package/dist/telemetry/TelemetryCapture.test.js +396 -0
- package/dist/telemetry-example.d.ts +33 -0
- package/dist/telemetry-example.d.ts.map +1 -0
- package/dist/telemetry-example.js +124 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/presence.d.ts +69 -0
- package/dist/types/presence.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -8,8 +8,20 @@ import type { PresenceManager } from "../abstractions/PresenceManager.js";
|
|
|
8
8
|
import type { RoomManager } from "../abstractions/RoomManager.js";
|
|
9
9
|
import type { IStorageAdapter } from "../abstractions/StorageAdapter.js";
|
|
10
10
|
import type { ITransportAdapter } from "../abstractions/TransportAdapter.js";
|
|
11
|
-
import type { Event, ExperimentalFeatureConfig, ExperimentalUsageEvent, Lock, Room, RoomConfig } from "../types/index.js";
|
|
11
|
+
import type { Event, ExperimentalFeatureConfig, ExperimentalUsageEvent, Lock, Message, Room, RoomConfig } from "../types/index.js";
|
|
12
12
|
import { ExperimentalAPI } from "./ExperimentalAPI.js";
|
|
13
|
+
/**
|
|
14
|
+
* Custom message handler for application-specific message types.
|
|
15
|
+
*
|
|
16
|
+
* Called when a message type is not recognized by the built-in handler.
|
|
17
|
+
* Return true if the message was handled, false to fall through to the default error response.
|
|
18
|
+
*
|
|
19
|
+
* @param clientId - The ID of the client that sent the message
|
|
20
|
+
* @param message - The message received
|
|
21
|
+
* @param sendResponse - Function to send a response back to the client (preserves message.id for correlation)
|
|
22
|
+
* @returns Promise<boolean> - true if handled, false otherwise
|
|
23
|
+
*/
|
|
24
|
+
export type CustomMessageHandler = (clientId: string, message: Message, sendResponse: (response: Record<string, unknown>) => Promise<void>) => Promise<boolean>;
|
|
13
25
|
export interface ServerConfig {
|
|
14
26
|
transport: ITransportAdapter;
|
|
15
27
|
auth?: IAuthAdapter;
|
|
@@ -22,6 +34,11 @@ export interface ServerConfig {
|
|
|
22
34
|
webSocketPath?: string;
|
|
23
35
|
webSocketServer?: WebSocketServer;
|
|
24
36
|
experimental?: ExperimentalFeatureConfig;
|
|
37
|
+
/**
|
|
38
|
+
* Custom message handler for application-specific message types.
|
|
39
|
+
* Called when a message type is not recognized by the built-in handler.
|
|
40
|
+
*/
|
|
41
|
+
customMessageHandler?: CustomMessageHandler;
|
|
25
42
|
}
|
|
26
43
|
export interface ConnectedClient {
|
|
27
44
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseServer.d.ts","sourceRoot":"","sources":["../../src/server/BaseServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EACX,KAAK,EACL,yBAAyB,EACzB,sBAAsB,EACtB,IAAI,
|
|
1
|
+
{"version":3,"file":"BaseServer.d.ts","sourceRoot":"","sources":["../../src/server/BaseServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EACX,KAAK,EACL,yBAAyB,EACzB,sBAAsB,EACtB,IAAI,EAEJ,OAAO,EACP,IAAI,EACJ,UAAU,EAEV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,KAC9D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,MAAM,WAAW,YAAY;IAC5B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,yBAAyB,CAAC;IACzC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC5C;AAED,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,OAAO,EAAE,EAAE,CAAC;IACZ,gBAAgB,EAAE;QAAE,MAAM,EAAE,eAAe,CAAA;KAAE,CAAC;IAC9C,mBAAmB,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D,oBAAoB,EAAE;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,CAAC;IACF,YAAY,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAC7B,YAAY,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,kBAAkB,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,gBAAgB,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,eAAe,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,aAAa,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,aAAa,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,KAAK,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,kBAAkB,EAAE,sBAAsB,CAAC;IAE3C,gBAAgB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,yBAAyB,EAAE;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,4BAA4B,EAAE;QAC7B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,iBAAiB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,qBAAa,UAAW,SAAQ,iBAAiB,CAAC,YAAY,CAAC;IAC9D,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,IAAI,CAAC,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAC,CAAkB;IAClC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,MAAM,CAAe;IAE7B,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,qBAAqB,CAGzB;IACJ,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,mBAAmB,CAAC,CAAiB;IAE7C;;;;;;;OAOG;IACH,SAAgB,YAAY,EAAE,eAAe,CAAC;gBAElC,MAAM,EAAE,YAAY;IAqDhC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA0C/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAQxB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BnC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAyD3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAsCb,sBAAsB;YAuDtB,uBAAuB;YAiFvB,gCAAgC;YA6BhC,oBAAoB;YAIpB,oBAAoB;YAUpB,SAAS;YAwBT,gBAAgB;IA2E9B,OAAO,CAAC,0BAA0B;YA8GpB,kBAAkB;YAgDlB,cAAc;YA0Gd,eAAe;YAgCf,oBAAoB;YAyCpB,iBAAiB;YA8CjB,iBAAiB;YAuCjB,YAAY;IAc1B,OAAO,CAAC,UAAU;IAKZ,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/C,mBAAmB,IAAI,eAAe,EAAE;IAIxC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAInD,SAAS,IAAI,OAAO;IAIpB,OAAO,IAAI,YAAY,GAAG,aAAa;IAIvC,aAAa,IAAI,OAAO;IAIxB;;;;;;OAMG;YACW,sBAAsB;IA+BpC;;OAEG;IACH,kBAAkB,IAAI,eAAe,GAAG,SAAS;IAIjD;;;;;OAKG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D;;;;;;;OAOG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAI7C;;;;;;OAMG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAQ5D;;;;;;;OAOG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAGjD"}
|
|
@@ -458,11 +458,25 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
|
|
|
458
458
|
timestamp: Date.now(),
|
|
459
459
|
});
|
|
460
460
|
break;
|
|
461
|
-
default:
|
|
461
|
+
default: {
|
|
462
|
+
// Try custom message handler if configured
|
|
463
|
+
if (this.config.customMessageHandler) {
|
|
464
|
+
const sendResponse = async (response) => {
|
|
465
|
+
await this.sendToClient(clientId, {
|
|
466
|
+
id: message.id,
|
|
467
|
+
...response,
|
|
468
|
+
});
|
|
469
|
+
};
|
|
470
|
+
const handled = await this.config.customMessageHandler(clientId, message, sendResponse);
|
|
471
|
+
if (handled)
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
// Fall through to error if not handled
|
|
462
475
|
await this.sendToClient(clientId, {
|
|
463
476
|
type: "error",
|
|
464
477
|
error: `Unknown message type: ${message.type}`,
|
|
465
478
|
});
|
|
479
|
+
}
|
|
466
480
|
}
|
|
467
481
|
}
|
|
468
482
|
catch (error) {
|
|
@@ -8,7 +8,7 @@ import type { RoomManager } from "../abstractions/RoomManager.js";
|
|
|
8
8
|
import type { IStorageAdapter } from "../abstractions/StorageAdapter.js";
|
|
9
9
|
import type { ITransportAdapter } from "../abstractions/TransportAdapter.js";
|
|
10
10
|
import type { ExperimentalFeatureConfig, RoomConfig } from "../types/index.js";
|
|
11
|
-
import { BaseServer } from "./BaseServer.js";
|
|
11
|
+
import { BaseServer, type CustomMessageHandler } from "./BaseServer.js";
|
|
12
12
|
export declare class ServerBuilder {
|
|
13
13
|
private transport?;
|
|
14
14
|
private auth?;
|
|
@@ -21,6 +21,7 @@ export declare class ServerBuilder {
|
|
|
21
21
|
private webSocketPath?;
|
|
22
22
|
private webSocketServer?;
|
|
23
23
|
private experimentalFeatures?;
|
|
24
|
+
private customMessageHandler?;
|
|
24
25
|
withTransport(transport: ITransportAdapter): this;
|
|
25
26
|
withAuth(auth: IAuthAdapter): this;
|
|
26
27
|
withStorage(storage: IStorageAdapter): this;
|
|
@@ -48,6 +49,26 @@ export declare class ServerBuilder {
|
|
|
48
49
|
* @see docs/EXPERIMENTAL_BROADCAST.md
|
|
49
50
|
*/
|
|
50
51
|
withExperimentalFeatures(features: ExperimentalFeatureConfig): this;
|
|
52
|
+
/**
|
|
53
|
+
* Set a custom message handler for application-specific message types.
|
|
54
|
+
*
|
|
55
|
+
* The handler is called when a message type is not recognized by the built-in handlers.
|
|
56
|
+
* Return true from the handler if the message was handled, false to fall through
|
|
57
|
+
* to the default error response.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* builder.withCustomMessageHandler(async (clientId, message, sendResponse) => {
|
|
62
|
+
* if (message.type === 'presence:get_users') {
|
|
63
|
+
* const users = await getPresenceUsers();
|
|
64
|
+
* await sendResponse({ type: 'presence:users', payload: { users } });
|
|
65
|
+
* return true;
|
|
66
|
+
* }
|
|
67
|
+
* return false;
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
withCustomMessageHandler(handler: CustomMessageHandler): this;
|
|
51
72
|
build(): BaseServer;
|
|
52
73
|
/**
|
|
53
74
|
* Wire presence extension hooks to server events
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerBuilder.d.ts","sourceRoot":"","sources":["../../src/server/ServerBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,
|
|
1
|
+
{"version":3,"file":"ServerBuilder.d.ts","sourceRoot":"","sources":["../../src/server/ServerBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EACN,UAAU,EACV,KAAK,oBAAoB,EAEzB,MAAM,iBAAiB,CAAC;AAEzB,qBAAa,aAAa;IACzB,OAAO,CAAC,SAAS,CAAC,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAC,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAC,CAAkB;IAClC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAChD,OAAO,CAAC,UAAU,CAAC,CAA2B;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,oBAAoB,CAAC,CAA4B;IACzD,OAAO,CAAC,oBAAoB,CAAC,CAAuB;IAEpD,aAAa,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAKjD,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAKlC,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAK3C,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAK/C,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAK/C;;;;;;;OAOG;IACH,mBAAmB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;IAK3D,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI;IAKxD,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI;IAKtD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKrC,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAK/C;;;;;;;OAOG;IACH,wBAAwB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAKnE;;;;;;;;;;;;;;;;;;OAkBG;IACH,wBAAwB,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAK7D,KAAK,IAAI,UAAU;IAqEnB;;;OAGG;IACH,OAAO,CAAC,0BAA0B;CAyClC"}
|
|
@@ -65,6 +65,29 @@ class ServerBuilder {
|
|
|
65
65
|
this.experimentalFeatures = features;
|
|
66
66
|
return this;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Set a custom message handler for application-specific message types.
|
|
70
|
+
*
|
|
71
|
+
* The handler is called when a message type is not recognized by the built-in handlers.
|
|
72
|
+
* Return true from the handler if the message was handled, false to fall through
|
|
73
|
+
* to the default error response.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* builder.withCustomMessageHandler(async (clientId, message, sendResponse) => {
|
|
78
|
+
* if (message.type === 'presence:get_users') {
|
|
79
|
+
* const users = await getPresenceUsers();
|
|
80
|
+
* await sendResponse({ type: 'presence:users', payload: { users } });
|
|
81
|
+
* return true;
|
|
82
|
+
* }
|
|
83
|
+
* return false;
|
|
84
|
+
* });
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
withCustomMessageHandler(handler) {
|
|
88
|
+
this.customMessageHandler = handler;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
68
91
|
build() {
|
|
69
92
|
if (!this.transport) {
|
|
70
93
|
throw new Error("Transport adapter is required");
|
|
@@ -95,6 +118,7 @@ class ServerBuilder {
|
|
|
95
118
|
warnOnExperimentalUse: true,
|
|
96
119
|
trackUsageMetrics: false,
|
|
97
120
|
},
|
|
121
|
+
customMessageHandler: this.customMessageHandler,
|
|
98
122
|
};
|
|
99
123
|
const server = new BaseServer_js_1.BaseServer(config);
|
|
100
124
|
// Auto-enhance DefaultRoomManager with broadcasting capabilities
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { BaseServer, type ConnectedClient, type ServerConfig, type ServerEvents, } from "./BaseServer.js";
|
|
1
|
+
export { BaseServer, type ConnectedClient, type CustomMessageHandler, type ServerConfig, type ServerEvents, } from "./BaseServer.js";
|
|
2
2
|
export { ExperimentalAPI } from "./ExperimentalAPI.js";
|
|
3
3
|
export { ServerBuilder } from "./ServerBuilder.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Validation Integration for Control Tower
|
|
3
|
+
*
|
|
4
|
+
* This demonstrates how to integrate event schema validation
|
|
5
|
+
* into the Control Tower server for type-safe telemetry.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* 1. Install: npm install @principal-ai/principal-view-core
|
|
9
|
+
* 2. Import canvas and types
|
|
10
|
+
* 3. Create validated event emitters
|
|
11
|
+
* 4. Use in server event handlers
|
|
12
|
+
*/
|
|
13
|
+
import type { ExtendedCanvas } from '@principal-ai/principal-view-core';
|
|
14
|
+
import type { WebsocketAdapter, Server, MessageHandler, AuthAdapter, ClientLifecycle, ClientResponse, NodeEmitterByName } from '@generated/client-connection-auth.types';
|
|
15
|
+
/**
|
|
16
|
+
* Control Tower Telemetry Service
|
|
17
|
+
*
|
|
18
|
+
* Provides type-safe, validated event emission for all Control Tower operations.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ControlTowerTelemetry {
|
|
21
|
+
private validator;
|
|
22
|
+
private canvas;
|
|
23
|
+
websocketAdapter: NodeEmitterByName<WebsocketAdapter.Event>;
|
|
24
|
+
server: NodeEmitterByName<Server.Event>;
|
|
25
|
+
messageHandler: NodeEmitterByName<MessageHandler.Event>;
|
|
26
|
+
authAdapter: NodeEmitterByName<AuthAdapter.Event>;
|
|
27
|
+
clientLifecycle: NodeEmitterByName<ClientLifecycle.Event>;
|
|
28
|
+
clientResponse: NodeEmitterByName<ClientResponse.Event>;
|
|
29
|
+
constructor(canvas: ExtendedCanvas, options?: {
|
|
30
|
+
/** Strict mode throws on validation errors (for tests) */
|
|
31
|
+
strict?: boolean;
|
|
32
|
+
/** Custom event handler */
|
|
33
|
+
onEvent?: (nodeId: string, eventName: string, attributes: Record<string, any>) => void;
|
|
34
|
+
});
|
|
35
|
+
/**
|
|
36
|
+
* Get available event names for a component
|
|
37
|
+
*/
|
|
38
|
+
getEventNames(component: 'websocket-adapter' | 'server' | 'message-handler' | 'auth-adapter' | 'client-lifecycle' | 'client-response'): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Validate an event manually (for testing)
|
|
41
|
+
*/
|
|
42
|
+
validate(component: string, eventName: string, attributes: Record<string, any>): any;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Example: Integrating with BaseServer
|
|
46
|
+
*
|
|
47
|
+
* This shows how you would integrate telemetry into the BaseServer class.
|
|
48
|
+
*/
|
|
49
|
+
export declare class TelemetryIntegrationExample {
|
|
50
|
+
private telemetry;
|
|
51
|
+
constructor(canvas: ExtendedCanvas);
|
|
52
|
+
/**
|
|
53
|
+
* Example: Handle WebSocket connection received
|
|
54
|
+
*/
|
|
55
|
+
handleConnectionReceived(connectionId: string, origin?: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* Example: Handle WebSocket connection established
|
|
58
|
+
*/
|
|
59
|
+
handleConnectionEstablished(connectionId: string, transportType: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Example: Handle client connected to server
|
|
62
|
+
*/
|
|
63
|
+
handleClientConnected(clientId: string, transportType: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Example: Handle client awaiting authentication
|
|
66
|
+
*/
|
|
67
|
+
handleClientAwaitingAuth(clientId: string, timeoutMs?: number): void;
|
|
68
|
+
/**
|
|
69
|
+
* Example: Handle message received
|
|
70
|
+
*/
|
|
71
|
+
handleMessageReceived(clientId: string, messageType: string, messageSize?: number): void;
|
|
72
|
+
/**
|
|
73
|
+
* Example: Handle message validated
|
|
74
|
+
*/
|
|
75
|
+
handleMessageValidated(clientId: string, messageType: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Example: Handle message validation failure
|
|
78
|
+
*/
|
|
79
|
+
handleMessageValidationFailed(clientId: string, messageType: string, errorMessage: string, errorField?: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Example: Handle auth validation started
|
|
82
|
+
*/
|
|
83
|
+
handleAuthValidationStarted(clientId: string, authMethod?: string): void;
|
|
84
|
+
/**
|
|
85
|
+
* Example: Handle auth validation success
|
|
86
|
+
*/
|
|
87
|
+
handleAuthValidationSuccess(clientId: string, userId: string, authMethod?: string, duration?: number): void;
|
|
88
|
+
/**
|
|
89
|
+
* Example: Handle auth validation failure
|
|
90
|
+
*/
|
|
91
|
+
handleAuthValidationFailed(clientId: string, errorCode: string, errorMessage: string): void;
|
|
92
|
+
/**
|
|
93
|
+
* Example: Handle client state changed
|
|
94
|
+
*/
|
|
95
|
+
handleClientStateChanged(clientId: string, fromState: string, toState: string, duration?: number): void;
|
|
96
|
+
/**
|
|
97
|
+
* Example: Handle client authenticated
|
|
98
|
+
*/
|
|
99
|
+
handleClientAuthenticated(clientId: string, userId: string, totalDuration?: number): void;
|
|
100
|
+
/**
|
|
101
|
+
* Example: Handle client disconnected
|
|
102
|
+
*/
|
|
103
|
+
handleClientDisconnected(clientId: string, reason: string, sessionDuration: number, wasAuthenticated: boolean): void;
|
|
104
|
+
/**
|
|
105
|
+
* Example: Handle response sent to client
|
|
106
|
+
*/
|
|
107
|
+
handleResponseSent(clientId: string, responseType: string, size?: number): void;
|
|
108
|
+
/**
|
|
109
|
+
* Example: Handle response send failure
|
|
110
|
+
*/
|
|
111
|
+
handleResponseSendFailed(clientId: string, errorMessage: string): void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Load canvas from file
|
|
115
|
+
*/
|
|
116
|
+
export declare function loadControlTowerCanvas(): ExtendedCanvas;
|
|
117
|
+
/**
|
|
118
|
+
* Create telemetry service instance
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const telemetry = createTelemetryService();
|
|
123
|
+
*
|
|
124
|
+
* telemetry.clientLifecycle('client.connected', {
|
|
125
|
+
* 'client.id': 'abc123',
|
|
126
|
+
* 'transport.type': 'websocket',
|
|
127
|
+
* 'connection.time': Date.now(),
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export declare function createTelemetryService(options?: {
|
|
132
|
+
strict?: boolean;
|
|
133
|
+
onEvent?: (nodeId: string, eventName: string, attributes: Record<string, any>) => void;
|
|
134
|
+
}): ControlTowerTelemetry;
|
|
135
|
+
//# sourceMappingURL=EventValidationIntegration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventValidationIntegration.d.ts","sourceRoot":"","sources":["../../src/telemetry/EventValidationIntegration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EACV,gBAAgB,EAChB,MAAM,EACN,cAAc,EACd,WAAW,EACX,eAAe,EACf,cAAc,EACd,iBAAiB,EAClB,MAAM,yCAAyC,CAAC;AAEjD;;;;GAIG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,MAAM,CAAiB;IAGxB,gBAAgB,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,cAAc,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACxD,WAAW,EAAE,iBAAiB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAClD,eAAe,EAAE,iBAAiB,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC1D,cAAc,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;gBAG7D,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE;QACP,0DAA0D;QAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,2BAA2B;QAC3B,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;KACnF;IAwDR;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,mBAAmB,GAAG,QAAQ,GAAG,iBAAiB,GAAG,cAAc,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,MAAM,EAAE;IAIhJ;;OAEG;IACH,QAAQ,CACN,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAIlC;AAED;;;;GAIG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,SAAS,CAAwB;gBAE7B,MAAM,EAAE,cAAc;IAWlC;;OAEG;IACH,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAO9D;;OAEG;IACH,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;IAOvE;;OAEG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;IAQ7D;;OAEG;IACH,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAO7D;;OAEG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;IAQjF;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAO5D;;OAEG;IACH,6BAA6B,CAC3B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM;IAUrB;;OAEG;IACH,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAOjE;;OAEG;IACH,2BAA2B,CACzB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM;IAUnB;;OAEG;IACH,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAQpF;;OAEG;IACH,wBAAwB,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM;IAUnB;;OAEG;IACH,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM;IAelF;;OAEG;IACH,wBAAwB,CACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,OAAO;IAU3B;;OAEG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IAQxE;;OAEG;IACH,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;CAMhE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,cAAc,CAMvD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CACxF,GAAG,qBAAqB,CAGxB"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Event Validation Integration for Control Tower
|
|
4
|
+
*
|
|
5
|
+
* This demonstrates how to integrate event schema validation
|
|
6
|
+
* into the Control Tower server for type-safe telemetry.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* 1. Install: npm install @principal-ai/principal-view-core
|
|
10
|
+
* 2. Import canvas and types
|
|
11
|
+
* 3. Create validated event emitters
|
|
12
|
+
* 4. Use in server event handlers
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.TelemetryIntegrationExample = exports.ControlTowerTelemetry = void 0;
|
|
16
|
+
exports.loadControlTowerCanvas = loadControlTowerCanvas;
|
|
17
|
+
exports.createTelemetryService = createTelemetryService;
|
|
18
|
+
const principal_view_core_1 = require("@principal-ai/principal-view-core");
|
|
19
|
+
/**
|
|
20
|
+
* Control Tower Telemetry Service
|
|
21
|
+
*
|
|
22
|
+
* Provides type-safe, validated event emission for all Control Tower operations.
|
|
23
|
+
*/
|
|
24
|
+
class ControlTowerTelemetry {
|
|
25
|
+
constructor(canvas, options = {}) {
|
|
26
|
+
this.canvas = canvas;
|
|
27
|
+
this.validator = new principal_view_core_1.EventValidator(canvas);
|
|
28
|
+
const defaultHandler = (nodeId, eventName, attributes) => {
|
|
29
|
+
// Default: log to console (replace with your telemetry backend)
|
|
30
|
+
console.log(`[${nodeId}] ${eventName}`, attributes);
|
|
31
|
+
};
|
|
32
|
+
const eventHandler = options.onEvent || defaultHandler;
|
|
33
|
+
// Create type-safe emitters for each component
|
|
34
|
+
this.websocketAdapter = (0, principal_view_core_1.createValidatedEmitter)(this.validator, 'websocket-adapter', (eventName, attributes) => eventHandler('websocket-adapter', eventName, attributes), { strict: options.strict ?? false });
|
|
35
|
+
this.server = (0, principal_view_core_1.createValidatedEmitter)(this.validator, 'server', (eventName, attributes) => eventHandler('server', eventName, attributes), { strict: options.strict ?? false });
|
|
36
|
+
this.messageHandler = (0, principal_view_core_1.createValidatedEmitter)(this.validator, 'message-handler', (eventName, attributes) => eventHandler('message-handler', eventName, attributes), { strict: options.strict ?? false });
|
|
37
|
+
this.authAdapter = (0, principal_view_core_1.createValidatedEmitter)(this.validator, 'auth-adapter', (eventName, attributes) => eventHandler('auth-adapter', eventName, attributes), { strict: options.strict ?? false });
|
|
38
|
+
this.clientLifecycle = (0, principal_view_core_1.createValidatedEmitter)(this.validator, 'client-lifecycle', (eventName, attributes) => eventHandler('client-lifecycle', eventName, attributes), { strict: options.strict ?? false });
|
|
39
|
+
this.clientResponse = (0, principal_view_core_1.createValidatedEmitter)(this.validator, 'client-response', (eventName, attributes) => eventHandler('client-response', eventName, attributes), { strict: options.strict ?? false });
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get available event names for a component
|
|
43
|
+
*/
|
|
44
|
+
getEventNames(component) {
|
|
45
|
+
return this.validator.getNodeEventNames(component);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validate an event manually (for testing)
|
|
49
|
+
*/
|
|
50
|
+
validate(component, eventName, attributes) {
|
|
51
|
+
return this.validator.validate(component, eventName, attributes);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.ControlTowerTelemetry = ControlTowerTelemetry;
|
|
55
|
+
/**
|
|
56
|
+
* Example: Integrating with BaseServer
|
|
57
|
+
*
|
|
58
|
+
* This shows how you would integrate telemetry into the BaseServer class.
|
|
59
|
+
*/
|
|
60
|
+
class TelemetryIntegrationExample {
|
|
61
|
+
constructor(canvas) {
|
|
62
|
+
// Create telemetry service
|
|
63
|
+
this.telemetry = new ControlTowerTelemetry(canvas, {
|
|
64
|
+
strict: false, // Permissive in production
|
|
65
|
+
onEvent: (nodeId, eventName, attributes) => {
|
|
66
|
+
// Send to your telemetry backend (OpenTelemetry, DataDog, etc.)
|
|
67
|
+
console.log(`[TELEMETRY] ${nodeId}.${eventName}`, attributes);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Example: Handle WebSocket connection received
|
|
73
|
+
*/
|
|
74
|
+
handleConnectionReceived(connectionId, origin) {
|
|
75
|
+
this.telemetry.websocketAdapter('connection.received', {
|
|
76
|
+
'connection.id': connectionId,
|
|
77
|
+
'connection.origin': origin,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Example: Handle WebSocket connection established
|
|
82
|
+
*/
|
|
83
|
+
handleConnectionEstablished(connectionId, transportType) {
|
|
84
|
+
this.telemetry.websocketAdapter('connection.established', {
|
|
85
|
+
'connection.id': connectionId,
|
|
86
|
+
'transport.type': transportType,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Example: Handle client connected to server
|
|
91
|
+
*/
|
|
92
|
+
handleClientConnected(clientId, transportType) {
|
|
93
|
+
this.telemetry.server('client.connected', {
|
|
94
|
+
'client.id': clientId,
|
|
95
|
+
'transport.type': transportType,
|
|
96
|
+
'connection.timestamp': Date.now(),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Example: Handle client awaiting authentication
|
|
101
|
+
*/
|
|
102
|
+
handleClientAwaitingAuth(clientId, timeoutMs) {
|
|
103
|
+
this.telemetry.server('client.awaiting_auth', {
|
|
104
|
+
'client.id': clientId,
|
|
105
|
+
'auth.timeout_ms': timeoutMs,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Example: Handle message received
|
|
110
|
+
*/
|
|
111
|
+
handleMessageReceived(clientId, messageType, messageSize) {
|
|
112
|
+
this.telemetry.messageHandler('message.received', {
|
|
113
|
+
'client.id': clientId,
|
|
114
|
+
'message.type': messageType,
|
|
115
|
+
'message.size_bytes': messageSize,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Example: Handle message validated
|
|
120
|
+
*/
|
|
121
|
+
handleMessageValidated(clientId, messageType) {
|
|
122
|
+
this.telemetry.messageHandler('message.validated', {
|
|
123
|
+
'client.id': clientId,
|
|
124
|
+
'message.type': messageType,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Example: Handle message validation failure
|
|
129
|
+
*/
|
|
130
|
+
handleMessageValidationFailed(clientId, messageType, errorMessage, errorField) {
|
|
131
|
+
this.telemetry.messageHandler('message.validation_failed', {
|
|
132
|
+
'client.id': clientId,
|
|
133
|
+
'message.type': messageType,
|
|
134
|
+
'validation.error': errorMessage,
|
|
135
|
+
'validation.field': errorField,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Example: Handle auth validation started
|
|
140
|
+
*/
|
|
141
|
+
handleAuthValidationStarted(clientId, authMethod) {
|
|
142
|
+
this.telemetry.authAdapter('auth.validation_started', {
|
|
143
|
+
'client.id': clientId,
|
|
144
|
+
'auth.method': authMethod,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Example: Handle auth validation success
|
|
149
|
+
*/
|
|
150
|
+
handleAuthValidationSuccess(clientId, userId, authMethod, duration) {
|
|
151
|
+
this.telemetry.authAdapter('auth.validation_success', {
|
|
152
|
+
'client.id': clientId,
|
|
153
|
+
'user.id': userId,
|
|
154
|
+
'auth.method': authMethod,
|
|
155
|
+
'validation.duration_ms': duration,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Example: Handle auth validation failure
|
|
160
|
+
*/
|
|
161
|
+
handleAuthValidationFailed(clientId, errorCode, errorMessage) {
|
|
162
|
+
this.telemetry.authAdapter('auth.validation_failed', {
|
|
163
|
+
'client.id': clientId,
|
|
164
|
+
'auth.error_code': errorCode,
|
|
165
|
+
'auth.error_message': errorMessage,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Example: Handle client state changed
|
|
170
|
+
*/
|
|
171
|
+
handleClientStateChanged(clientId, fromState, toState, duration) {
|
|
172
|
+
this.telemetry.clientLifecycle('client.state_changed', {
|
|
173
|
+
'client.id': clientId,
|
|
174
|
+
'state.from': fromState,
|
|
175
|
+
'state.to': toState,
|
|
176
|
+
'state.duration_ms': duration,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Example: Handle client authenticated
|
|
181
|
+
*/
|
|
182
|
+
handleClientAuthenticated(clientId, userId, totalDuration) {
|
|
183
|
+
// ✅ Type-safe: TypeScript knows exact attributes for this event
|
|
184
|
+
this.telemetry.clientLifecycle('client.authenticated', {
|
|
185
|
+
'client.id': clientId,
|
|
186
|
+
'user.id': userId,
|
|
187
|
+
'connection.total_duration_ms': totalDuration,
|
|
188
|
+
});
|
|
189
|
+
// ❌ TypeScript error: missing required field
|
|
190
|
+
// this.telemetry.clientLifecycle('client.authenticated', {
|
|
191
|
+
// 'client.id': clientId,
|
|
192
|
+
// // Missing 'user.id' - TypeScript error!
|
|
193
|
+
// });
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Example: Handle client disconnected
|
|
197
|
+
*/
|
|
198
|
+
handleClientDisconnected(clientId, reason, sessionDuration, wasAuthenticated) {
|
|
199
|
+
this.telemetry.clientLifecycle('client.disconnected', {
|
|
200
|
+
'client.id': clientId,
|
|
201
|
+
'disconnect.reason': reason,
|
|
202
|
+
'session.total_duration_ms': sessionDuration,
|
|
203
|
+
'client.was_authenticated': wasAuthenticated,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Example: Handle response sent to client
|
|
208
|
+
*/
|
|
209
|
+
handleResponseSent(clientId, responseType, size) {
|
|
210
|
+
this.telemetry.clientResponse('response.sent', {
|
|
211
|
+
'client.id': clientId,
|
|
212
|
+
'response.type': responseType,
|
|
213
|
+
'response.size_bytes': size,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Example: Handle response send failure
|
|
218
|
+
*/
|
|
219
|
+
handleResponseSendFailed(clientId, errorMessage) {
|
|
220
|
+
this.telemetry.clientResponse('response.send_failed', {
|
|
221
|
+
'client.id': clientId,
|
|
222
|
+
'error.message': errorMessage,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
exports.TelemetryIntegrationExample = TelemetryIntegrationExample;
|
|
227
|
+
/**
|
|
228
|
+
* Load canvas from file
|
|
229
|
+
*/
|
|
230
|
+
function loadControlTowerCanvas() {
|
|
231
|
+
const fs = require('fs');
|
|
232
|
+
const path = require('path');
|
|
233
|
+
const canvasPath = path.join(__dirname, '../../.principal-views/client-connection-auth.otel.canvas');
|
|
234
|
+
return JSON.parse(fs.readFileSync(canvasPath, 'utf-8'));
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Create telemetry service instance
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const telemetry = createTelemetryService();
|
|
242
|
+
*
|
|
243
|
+
* telemetry.clientLifecycle('client.connected', {
|
|
244
|
+
* 'client.id': 'abc123',
|
|
245
|
+
* 'transport.type': 'websocket',
|
|
246
|
+
* 'connection.time': Date.now(),
|
|
247
|
+
* });
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
function createTelemetryService(options) {
|
|
251
|
+
const canvas = loadControlTowerCanvas();
|
|
252
|
+
return new ControlTowerTelemetry(canvas, options);
|
|
253
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventValidationIntegration.test.d.ts","sourceRoot":"","sources":["../../src/telemetry/EventValidationIntegration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|