@agentick/gateway 0.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/LICENSE +21 -0
- package/README.md +477 -0
- package/dist/agent-registry.d.ts +51 -0
- package/dist/agent-registry.d.ts.map +1 -0
- package/dist/agent-registry.js +78 -0
- package/dist/agent-registry.js.map +1 -0
- package/dist/app-registry.d.ts +51 -0
- package/dist/app-registry.d.ts.map +1 -0
- package/dist/app-registry.js +78 -0
- package/dist/app-registry.js.map +1 -0
- package/dist/bin.d.ts +8 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +37 -0
- package/dist/bin.js.map +1 -0
- package/dist/gateway.d.ts +165 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +1339 -0
- package/dist/gateway.js.map +1 -0
- package/dist/http-transport.d.ts +65 -0
- package/dist/http-transport.d.ts.map +1 -0
- package/dist/http-transport.js +517 -0
- package/dist/http-transport.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +162 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +16 -0
- package/dist/protocol.js.map +1 -0
- package/dist/session-manager.d.ts +101 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +208 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/testing.d.ts +92 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +129 -0
- package/dist/testing.js.map +1 -0
- package/dist/transport-protocol.d.ts +162 -0
- package/dist/transport-protocol.d.ts.map +1 -0
- package/dist/transport-protocol.js +16 -0
- package/dist/transport-protocol.js.map +1 -0
- package/dist/transport.d.ts +115 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +56 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +314 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +37 -0
- package/dist/types.js.map +1 -0
- package/dist/websocket-server.d.ts +87 -0
- package/dist/websocket-server.d.ts.map +1 -0
- package/dist/websocket-server.js +245 -0
- package/dist/websocket-server.js.map +1 -0
- package/dist/ws-transport.d.ts +17 -0
- package/dist/ws-transport.d.ts.map +1 -0
- package/dist/ws-transport.js +174 -0
- package/dist/ws-transport.js.map +1 -0
- package/package.json +51 -0
- package/src/__tests__/custom-methods.spec.ts +220 -0
- package/src/__tests__/gateway-methods.spec.ts +262 -0
- package/src/__tests__/gateway.spec.ts +404 -0
- package/src/__tests__/guards.spec.ts +235 -0
- package/src/__tests__/protocol.spec.ts +58 -0
- package/src/__tests__/session-manager.spec.ts +220 -0
- package/src/__tests__/ws-transport.spec.ts +246 -0
- package/src/app-registry.ts +103 -0
- package/src/bin.ts +38 -0
- package/src/gateway.ts +1712 -0
- package/src/http-transport.ts +623 -0
- package/src/index.ts +94 -0
- package/src/session-manager.ts +272 -0
- package/src/testing.ts +236 -0
- package/src/transport-protocol.ts +249 -0
- package/src/transport.ts +191 -0
- package/src/types.ts +392 -0
- package/src/websocket-server.ts +303 -0
- package/src/ws-transport.ts +205 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-server.js","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Transport
|
|
3
|
+
*
|
|
4
|
+
* Implements the Transport interface using WebSocket connections.
|
|
5
|
+
*/
|
|
6
|
+
import { BaseTransport, type TransportConfig } from "./transport.js";
|
|
7
|
+
export declare class WSTransport extends BaseTransport {
|
|
8
|
+
readonly type: "websocket";
|
|
9
|
+
private wss;
|
|
10
|
+
start(): Promise<void>;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
private handleConnection;
|
|
13
|
+
private handleMessage;
|
|
14
|
+
private handleConnect;
|
|
15
|
+
}
|
|
16
|
+
export declare function createWSTransport(config: TransportConfig): WSTransport;
|
|
17
|
+
//# sourceMappingURL=ws-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-transport.d.ts","sourceRoot":"","sources":["../src/ws-transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,aAAa,EAAwB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAiD3F,qBAAa,WAAY,SAAQ,aAAa;IAC5C,QAAQ,CAAC,IAAI,EAAG,WAAW,CAAU;IACrC,OAAO,CAAC,GAAG,CAAgC;IAElC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB9B,OAAO,CAAC,gBAAgB;YA+BV,aAAa;YA2Bb,aAAa;CA+B5B;AAMD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,WAAW,CAEtE"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Transport
|
|
3
|
+
*
|
|
4
|
+
* Implements the Transport interface using WebSocket connections.
|
|
5
|
+
*/
|
|
6
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
7
|
+
import { BaseTransport } from "./transport.js";
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// WebSocket Client
|
|
10
|
+
// ============================================================================
|
|
11
|
+
class WSClientImpl {
|
|
12
|
+
id;
|
|
13
|
+
socket;
|
|
14
|
+
state;
|
|
15
|
+
transport;
|
|
16
|
+
constructor(id, socket, transport) {
|
|
17
|
+
this.id = id;
|
|
18
|
+
this.socket = socket;
|
|
19
|
+
this.transport = transport;
|
|
20
|
+
this.state = {
|
|
21
|
+
id,
|
|
22
|
+
connectedAt: new Date(),
|
|
23
|
+
authenticated: false,
|
|
24
|
+
subscriptions: new Set(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
send(message) {
|
|
28
|
+
if (this.socket.readyState === WebSocket.OPEN) {
|
|
29
|
+
this.socket.send(JSON.stringify(message));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
close(code, reason) {
|
|
33
|
+
this.socket.close(code, reason);
|
|
34
|
+
}
|
|
35
|
+
get isConnected() {
|
|
36
|
+
return this.socket.readyState === WebSocket.OPEN;
|
|
37
|
+
}
|
|
38
|
+
/** @internal - Update client ID (for custom client IDs) */
|
|
39
|
+
_setId(newId) {
|
|
40
|
+
this.id = newId;
|
|
41
|
+
this.state.id = newId;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// WebSocket Transport
|
|
46
|
+
// ============================================================================
|
|
47
|
+
export class WSTransport extends BaseTransport {
|
|
48
|
+
type = "websocket";
|
|
49
|
+
wss = null;
|
|
50
|
+
start() {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
try {
|
|
53
|
+
this.wss = new WebSocketServer({
|
|
54
|
+
port: this.config.port,
|
|
55
|
+
host: this.config.host,
|
|
56
|
+
});
|
|
57
|
+
this.wss.on("connection", this.handleConnection.bind(this));
|
|
58
|
+
this.wss.on("error", (error) => {
|
|
59
|
+
this.handlers.error?.(error);
|
|
60
|
+
reject(error);
|
|
61
|
+
});
|
|
62
|
+
this.wss.on("listening", () => {
|
|
63
|
+
resolve();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
reject(error);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
stop() {
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
if (!this.wss) {
|
|
74
|
+
resolve();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Close all client connections
|
|
78
|
+
for (const client of this.clients.values()) {
|
|
79
|
+
client.close(1001, "Server shutting down");
|
|
80
|
+
}
|
|
81
|
+
this.clients.clear();
|
|
82
|
+
// Close the server
|
|
83
|
+
this.wss.close(() => {
|
|
84
|
+
this.wss = null;
|
|
85
|
+
resolve();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
handleConnection(socket, _request) {
|
|
90
|
+
const clientId = this.generateClientId();
|
|
91
|
+
const client = new WSClientImpl(clientId, socket, this);
|
|
92
|
+
this.clients.set(clientId, client);
|
|
93
|
+
socket.on("message", (data) => {
|
|
94
|
+
try {
|
|
95
|
+
const message = JSON.parse(data.toString());
|
|
96
|
+
this.handleMessage(client, message);
|
|
97
|
+
}
|
|
98
|
+
catch (_error) {
|
|
99
|
+
client.send({
|
|
100
|
+
type: "error",
|
|
101
|
+
code: "INVALID_MESSAGE",
|
|
102
|
+
message: "Failed to parse message",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
socket.on("close", () => {
|
|
107
|
+
this.clients.delete(client.id);
|
|
108
|
+
this.handlers.disconnect?.(client.id);
|
|
109
|
+
});
|
|
110
|
+
socket.on("error", (error) => {
|
|
111
|
+
this.handlers.error?.(error);
|
|
112
|
+
});
|
|
113
|
+
// Notify handler of new connection (before auth)
|
|
114
|
+
this.handlers.connection?.(client);
|
|
115
|
+
}
|
|
116
|
+
async handleMessage(client, message) {
|
|
117
|
+
// Handle connect message (authentication)
|
|
118
|
+
if (message.type === "connect") {
|
|
119
|
+
await this.handleConnect(client, message);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Handle ping
|
|
123
|
+
if (message.type === "ping") {
|
|
124
|
+
client.send({ type: "pong", timestamp: message.timestamp });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// All other messages require authentication
|
|
128
|
+
if (!client.state.authenticated) {
|
|
129
|
+
client.send({
|
|
130
|
+
type: "error",
|
|
131
|
+
code: "UNAUTHORIZED",
|
|
132
|
+
message: "Authentication required. Send connect message first.",
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Forward to message handler
|
|
137
|
+
this.handlers.message?.(client.id, message);
|
|
138
|
+
}
|
|
139
|
+
async handleConnect(client, message) {
|
|
140
|
+
// Validate authentication
|
|
141
|
+
const authResult = await this.validateAuth(message.token);
|
|
142
|
+
if (!authResult.valid) {
|
|
143
|
+
client.send({
|
|
144
|
+
type: "error",
|
|
145
|
+
code: "AUTH_FAILED",
|
|
146
|
+
message: "Authentication failed",
|
|
147
|
+
});
|
|
148
|
+
client.close(4001, "Authentication failed");
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Update client state
|
|
152
|
+
client.state.authenticated = true;
|
|
153
|
+
client.state.user = authResult.user;
|
|
154
|
+
client.state.metadata = {
|
|
155
|
+
...client.state.metadata,
|
|
156
|
+
...authResult.metadata,
|
|
157
|
+
...message.metadata,
|
|
158
|
+
};
|
|
159
|
+
// Client ID from message takes precedence
|
|
160
|
+
if (message.clientId) {
|
|
161
|
+
// Update internal tracking if client provides their own ID
|
|
162
|
+
this.clients.delete(client.id);
|
|
163
|
+
client._setId(message.clientId);
|
|
164
|
+
this.clients.set(message.clientId, client);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// Factory Function
|
|
170
|
+
// ============================================================================
|
|
171
|
+
export function createWSTransport(config) {
|
|
172
|
+
return new WSTransport(config);
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=ws-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-transport.js","sourceRoot":"","sources":["../src/ws-transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentick/gateway",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Standalone daemon for multi-client, multi-agent access",
|
|
5
|
+
"bin": {
|
|
6
|
+
"agentick-gateway": "./dist/bin.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./testing": {
|
|
21
|
+
"types": "./dist/testing.d.ts",
|
|
22
|
+
"import": "./dist/testing.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"ws": "^8.16.0",
|
|
27
|
+
"@agentick/core": "0.0.1",
|
|
28
|
+
"@agentick/server": "0.0.1",
|
|
29
|
+
"@agentick/kernel": "0.0.1",
|
|
30
|
+
"@agentick/shared": "0.0.1"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.10.5",
|
|
34
|
+
"@types/ws": "^8.5.10",
|
|
35
|
+
"tsx": "^4.19.2",
|
|
36
|
+
"typescript": "^5.7.3",
|
|
37
|
+
"vitest": "^3.0.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@agentick/core": "0.0.1"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc -p tsconfig.build.json",
|
|
44
|
+
"dev": "tsc --watch",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"clean": "rm -rf dist",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"start": "tsx src/bin.ts"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Methods Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for Gateway custom method dispatch, guards, and schema validation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { Context, type KernelContext, type UserContext } from "@agentick/kernel";
|
|
10
|
+
import {
|
|
11
|
+
method,
|
|
12
|
+
isMethodDefinition,
|
|
13
|
+
METHOD_DEFINITION,
|
|
14
|
+
type MethodDefinition,
|
|
15
|
+
type AuthResult,
|
|
16
|
+
} from "../types.js";
|
|
17
|
+
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// method() factory tests
|
|
20
|
+
// ============================================================================
|
|
21
|
+
|
|
22
|
+
describe("method() factory", () => {
|
|
23
|
+
it("should create a method definition with symbol marker", () => {
|
|
24
|
+
const def = method({
|
|
25
|
+
handler: async () => ({ result: true }),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(def[METHOD_DEFINITION]).toBe(true);
|
|
29
|
+
expect(isMethodDefinition(def)).toBe(true);
|
|
30
|
+
expect(typeof def.handler).toBe("function");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should preserve schema in method definition", () => {
|
|
34
|
+
const schema = z.object({
|
|
35
|
+
title: z.string(),
|
|
36
|
+
priority: z.enum(["low", "medium", "high"]).optional(),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const def = method({
|
|
40
|
+
schema,
|
|
41
|
+
handler: async (params) => params,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(def.schema).toBe(schema);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should preserve roles in method definition", () => {
|
|
48
|
+
const def = method({
|
|
49
|
+
roles: ["admin", "moderator"],
|
|
50
|
+
handler: async () => ({}),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
expect(def.roles).toEqual(["admin", "moderator"]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should preserve guard function in method definition", () => {
|
|
57
|
+
const guard = (ctx: KernelContext) => ctx.user?.id === "admin";
|
|
58
|
+
|
|
59
|
+
const def = method({
|
|
60
|
+
guard,
|
|
61
|
+
handler: async () => ({}),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(def.guard).toBe(guard);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should preserve description in method definition", () => {
|
|
68
|
+
const def = method({
|
|
69
|
+
description: "List all tasks for the current user",
|
|
70
|
+
handler: async () => [],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(def.description).toBe("List all tasks for the current user");
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// isMethodDefinition() tests
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
describe("isMethodDefinition()", () => {
|
|
82
|
+
it("should return true for method definitions", () => {
|
|
83
|
+
const def = method({ handler: async () => ({}) });
|
|
84
|
+
expect(isMethodDefinition(def)).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should return false for plain functions", () => {
|
|
88
|
+
const fn = async () => ({});
|
|
89
|
+
expect(isMethodDefinition(fn)).toBe(false);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should return false for plain objects", () => {
|
|
93
|
+
const obj = { handler: async () => ({}) };
|
|
94
|
+
expect(isMethodDefinition(obj)).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should return false for null", () => {
|
|
98
|
+
expect(isMethodDefinition(null)).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("should return false for undefined", () => {
|
|
102
|
+
expect(isMethodDefinition(undefined)).toBe(false);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should return false for primitives", () => {
|
|
106
|
+
expect(isMethodDefinition("string")).toBe(false);
|
|
107
|
+
expect(isMethodDefinition(123)).toBe(false);
|
|
108
|
+
expect(isMethodDefinition(true)).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// Schema validation behavior
|
|
114
|
+
// ============================================================================
|
|
115
|
+
|
|
116
|
+
describe("method schema validation", () => {
|
|
117
|
+
it("should type-infer params from schema", () => {
|
|
118
|
+
const schema = z.object({
|
|
119
|
+
title: z.string(),
|
|
120
|
+
count: z.number(),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// This is a compile-time type check - if it compiles, the types work
|
|
124
|
+
const def = method({
|
|
125
|
+
schema,
|
|
126
|
+
handler: async (params) => {
|
|
127
|
+
// TypeScript should infer params.title as string and params.count as number
|
|
128
|
+
const result: { title: string; count: number } = {
|
|
129
|
+
title: params.title,
|
|
130
|
+
count: params.count,
|
|
131
|
+
};
|
|
132
|
+
return result;
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
expect(def.schema).toBe(schema);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// Context integration (unit tests without full Gateway)
|
|
142
|
+
// ============================================================================
|
|
143
|
+
|
|
144
|
+
describe("Context integration", () => {
|
|
145
|
+
it("should allow Context.get() inside handlers", async () => {
|
|
146
|
+
const handler = async () => {
|
|
147
|
+
const ctx = Context.get();
|
|
148
|
+
return { userId: ctx.user?.id };
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const user: UserContext = { id: "user-123", roles: ["user"] };
|
|
152
|
+
const ctx = Context.create({ user });
|
|
153
|
+
|
|
154
|
+
const result = await Context.run(ctx, handler);
|
|
155
|
+
expect(result).toEqual({ userId: "user-123" });
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("should make user roles available in context", async () => {
|
|
159
|
+
const handler = async () => {
|
|
160
|
+
const ctx = Context.get();
|
|
161
|
+
return { roles: ctx.user?.roles };
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const user: UserContext = { id: "admin-1", roles: ["admin", "user"] };
|
|
165
|
+
const ctx = Context.create({ user });
|
|
166
|
+
|
|
167
|
+
const result = await Context.run(ctx, handler);
|
|
168
|
+
expect(result).toEqual({ roles: ["admin", "user"] });
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("should make metadata available in context", async () => {
|
|
172
|
+
const handler = async () => {
|
|
173
|
+
const ctx = Context.get();
|
|
174
|
+
return {
|
|
175
|
+
sessionId: ctx.metadata?.sessionId,
|
|
176
|
+
gatewayId: ctx.metadata?.gatewayId,
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const ctx = Context.create({
|
|
181
|
+
metadata: { sessionId: "sess-1", gatewayId: "gw-1" },
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const result = await Context.run(ctx, handler);
|
|
185
|
+
expect(result).toEqual({ sessionId: "sess-1", gatewayId: "gw-1" });
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// ============================================================================
|
|
190
|
+
// Streaming method behavior
|
|
191
|
+
// ============================================================================
|
|
192
|
+
|
|
193
|
+
describe("streaming methods", () => {
|
|
194
|
+
it("should support async generator handlers", async () => {
|
|
195
|
+
async function* streamingHandler() {
|
|
196
|
+
yield { chunk: 1 };
|
|
197
|
+
yield { chunk: 2 };
|
|
198
|
+
yield { chunk: 3 };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const chunks: unknown[] = [];
|
|
202
|
+
for await (const chunk of streamingHandler()) {
|
|
203
|
+
chunks.push(chunk);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
expect(chunks).toEqual([{ chunk: 1 }, { chunk: 2 }, { chunk: 3 }]);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("should allow method() with streaming handler", () => {
|
|
210
|
+
const def = method({
|
|
211
|
+
handler: async function* (params: { limit: number }) {
|
|
212
|
+
for (let i = 0; i < params.limit; i++) {
|
|
213
|
+
yield { index: i };
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect(isMethodDefinition(def)).toBe(true);
|
|
219
|
+
});
|
|
220
|
+
});
|