@blokjs/trigger-grpc 0.6.18 → 0.6.20

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.
@@ -1,138 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
-
3
- // vi.mock factories are hoisted — cannot reference top-level variables.
4
- // Use vi.hoisted() to define shared mocks.
5
- const { mockExecuteWorkflow, mockCreateClient } = vi.hoisted(() => {
6
- const mockExecuteWorkflow = vi.fn().mockResolvedValue({ Message: "response", Encoding: "BASE64", Type: "JSON" });
7
- const mockCreateClient = vi.fn().mockReturnValue({ executeWorkflow: mockExecuteWorkflow });
8
- return { mockExecuteWorkflow, mockCreateClient };
9
- });
10
-
11
- vi.mock("@connectrpc/connect", () => ({
12
- createClient: mockCreateClient,
13
- }));
14
-
15
- vi.mock("@connectrpc/connect-node", () => ({
16
- createGrpcTransport: vi.fn().mockReturnValue({ type: "grpc" }),
17
- createGrpcWebTransport: vi.fn().mockReturnValue({ type: "grpc-web" }),
18
- createConnectTransport: vi.fn().mockReturnValue({ type: "connect" }),
19
- }));
20
-
21
- import { createConnectTransport, createGrpcTransport, createGrpcWebTransport } from "@connectrpc/connect-node";
22
- import GrpcClient, { TransportEnum, HttpVersionEnum, type RpcOptions } from "../../src/GrpcClient";
23
-
24
- describe("GrpcClient", () => {
25
- const defaultOpts: RpcOptions = {
26
- host: "localhost",
27
- port: 8433,
28
- protocol: "http",
29
- httpVersion: HttpVersionEnum.HTTP2,
30
- transport: TransportEnum.GRPC,
31
- };
32
-
33
- beforeEach(() => {
34
- vi.clearAllMocks();
35
- });
36
-
37
- describe("constructor()", () => {
38
- it("should store options", () => {
39
- const client = new GrpcClient(defaultOpts);
40
- expect(client).toBeDefined();
41
- });
42
- });
43
-
44
- describe("transport()", () => {
45
- it("should create gRPC transport for GRPC type", () => {
46
- const client = new GrpcClient({ ...defaultOpts, transport: TransportEnum.GRPC });
47
- const transport = client.transport();
48
- expect(createGrpcTransport).toHaveBeenCalledWith({
49
- baseUrl: "http://localhost:8433/",
50
- interceptors: [],
51
- });
52
- expect(transport).toEqual({ type: "grpc" });
53
- });
54
-
55
- it("should create gRPC-Web transport for GRPC_WEB type", () => {
56
- const client = new GrpcClient({ ...defaultOpts, transport: TransportEnum.GRPC_WEB });
57
- const transport = client.transport();
58
- expect(createGrpcWebTransport).toHaveBeenCalledWith({
59
- baseUrl: "http://localhost:8433/",
60
- httpVersion: HttpVersionEnum.HTTP2,
61
- interceptors: [],
62
- });
63
- expect(transport).toEqual({ type: "grpc-web" });
64
- });
65
-
66
- it("should create Connect transport for CONNECT type", () => {
67
- const client = new GrpcClient({ ...defaultOpts, transport: TransportEnum.CONNECT });
68
- const transport = client.transport();
69
- expect(createConnectTransport).toHaveBeenCalledWith({
70
- baseUrl: "http://localhost:8433/",
71
- httpVersion: HttpVersionEnum.HTTP2,
72
- interceptors: [],
73
- });
74
- expect(transport).toEqual({ type: "connect" });
75
- });
76
-
77
- it("should throw for invalid transport type", () => {
78
- const client = new GrpcClient({ ...defaultOpts, transport: "invalid" as TransportEnum });
79
- expect(() => client.transport()).toThrow("Invalid transport type");
80
- });
81
-
82
- it("should use correct baseUrl with custom protocol and port", () => {
83
- const client = new GrpcClient({
84
- ...defaultOpts,
85
- protocol: "https",
86
- host: "api.example.com",
87
- port: 9090,
88
- transport: TransportEnum.GRPC,
89
- });
90
- client.transport();
91
- expect(createGrpcTransport).toHaveBeenCalledWith({
92
- baseUrl: "https://api.example.com:9090/",
93
- interceptors: [],
94
- });
95
- });
96
- });
97
-
98
- describe("call()", () => {
99
- it("should create client and execute workflow", async () => {
100
- const client = new GrpcClient(defaultOpts);
101
- const message = {
102
- Name: "test",
103
- Message: "data",
104
- Encoding: "BASE64",
105
- Type: "JSON",
106
- };
107
-
108
- const result = await client.call(message as any);
109
- expect(mockCreateClient).toHaveBeenCalled();
110
- expect(mockExecuteWorkflow).toHaveBeenCalledWith(message, undefined);
111
- expect(result).toEqual({ Message: "response", Encoding: "BASE64", Type: "JSON" });
112
- });
113
-
114
- it("should pass call options with headers", async () => {
115
- const client = new GrpcClient(defaultOpts);
116
- const message = { Name: "test", Message: "data", Encoding: "BASE64", Type: "JSON" };
117
- const opts = { headers: { Authorization: "Bearer token123" } };
118
-
119
- await client.call(message as any, opts);
120
- expect(mockExecuteWorkflow).toHaveBeenCalledWith(message, opts);
121
- });
122
- });
123
-
124
- describe("TransportEnum", () => {
125
- it("should have correct values", () => {
126
- expect(TransportEnum.GRPC).toBe("grpc");
127
- expect(TransportEnum.GRPC_WEB).toBe("grpc-web");
128
- expect(TransportEnum.CONNECT).toBe("connect");
129
- });
130
- });
131
-
132
- describe("HttpVersionEnum", () => {
133
- it("should have correct values", () => {
134
- expect(HttpVersionEnum.HTTP1).toBe("1.1");
135
- expect(HttpVersionEnum.HTTP2).toBe("2");
136
- });
137
- });
138
- });
@@ -1,127 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
-
3
- // Use vi.hoisted for mocks referenced in vi.mock factories
4
- const { mockRegister, mockListen, mockAddresses } = vi.hoisted(() => {
5
- const mockRegister = vi.fn().mockResolvedValue(undefined);
6
- const mockListen = vi.fn().mockResolvedValue(undefined);
7
- const mockAddresses = vi.fn().mockReturnValue([{ address: "0.0.0.0", port: 8443 }]);
8
- return { mockRegister, mockListen, mockAddresses };
9
- });
10
-
11
- // Mock OpenTelemetry
12
- vi.mock("@opentelemetry/api", () => ({
13
- trace: {
14
- getTracer: () => ({
15
- startActiveSpan: (_name: string, fn: (span: any) => any) =>
16
- fn({
17
- setAttribute: vi.fn(),
18
- setStatus: vi.fn(),
19
- end: vi.fn(),
20
- }),
21
- }),
22
- },
23
- metrics: {
24
- getMeter: () => ({
25
- createCounter: () => ({ add: vi.fn() }),
26
- createGauge: () => ({ record: vi.fn() }),
27
- }),
28
- },
29
- SpanStatusCode: { OK: 0, ERROR: 1 },
30
- }));
31
-
32
- // Mock fastify — must return a class-like constructor
33
- vi.mock("fastify", () => ({
34
- default: () => ({
35
- register: mockRegister,
36
- listen: mockListen,
37
- addresses: mockAddresses,
38
- }),
39
- }));
40
-
41
- // Mock connect-fastify
42
- vi.mock("@connectrpc/connect-fastify", () => ({
43
- fastifyConnectPlugin: "mocked-plugin",
44
- }));
45
-
46
- // Mock GRpcTrigger
47
- vi.mock("../../src/GRpcTrigger", () => {
48
- return {
49
- default: class MockGRpcTrigger {
50
- getApp() {
51
- return {
52
- register: mockRegister,
53
- listen: mockListen,
54
- addresses: mockAddresses,
55
- };
56
- }
57
- processRequest() {}
58
- },
59
- };
60
- });
61
-
62
- // Mock runner — DefaultLogger must be a class (used with new)
63
- vi.mock("@blokjs/runner", () => ({
64
- DefaultLogger: class MockDefaultLogger {
65
- log() {}
66
- error() {}
67
- },
68
- }));
69
-
70
- import GrpcServer from "../../src/GrpcServer";
71
-
72
- describe("GrpcServer", () => {
73
- beforeEach(() => {
74
- vi.clearAllMocks();
75
- });
76
-
77
- describe("constructor()", () => {
78
- it("should create instance with provided options", () => {
79
- const server = new GrpcServer({ host: "127.0.0.1", port: 9090 });
80
- expect(server).toBeDefined();
81
- });
82
-
83
- it("should default host to 0.0.0.0 when undefined", () => {
84
- const server = new GrpcServer({ host: undefined as any, port: 8443 });
85
- expect(server).toBeDefined();
86
- });
87
-
88
- it("should default port to 8443 when undefined", () => {
89
- const server = new GrpcServer({ host: "0.0.0.0", port: undefined as any });
90
- expect(server).toBeDefined();
91
- });
92
-
93
- it("should default both host and port when undefined", () => {
94
- const server = new GrpcServer({ host: undefined as any, port: undefined as any });
95
- expect(server).toBeDefined();
96
- });
97
- });
98
-
99
- describe("start()", () => {
100
- it("should register connect plugin and listen", async () => {
101
- const server = new GrpcServer({ host: "0.0.0.0", port: 8443 });
102
- await server.start();
103
- expect(mockRegister).toHaveBeenCalled();
104
- expect(mockListen).toHaveBeenCalled();
105
- });
106
-
107
- it("should use GRPC_HOST env var when set", async () => {
108
- const originalHost = process.env.GRPC_HOST;
109
- process.env.GRPC_HOST = "10.0.0.1";
110
- const server = new GrpcServer({ host: "0.0.0.0", port: 8443 });
111
- await server.start();
112
- const listenArgs = mockListen.mock.calls[0][0];
113
- expect(listenArgs.host).toBe("10.0.0.1");
114
- process.env.GRPC_HOST = originalHost;
115
- });
116
-
117
- it("should use GRPC_PORT env var when set", async () => {
118
- const originalPort = process.env.GRPC_PORT;
119
- process.env.GRPC_PORT = "9999";
120
- const server = new GrpcServer({ host: "0.0.0.0", port: 8443 });
121
- await server.start();
122
- const listenArgs = mockListen.mock.calls[0][0];
123
- expect(listenArgs.port).toBe(9999);
124
- process.env.GRPC_PORT = originalPort;
125
- });
126
- });
127
- });
@@ -1,314 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
- import MessageDecode from "../../src/MessageDecode";
3
- import { MessageEncoding, MessageType } from "../../src/gen/workflow_pb";
4
-
5
- describe("MessageDecode", () => {
6
- let decoder: MessageDecode;
7
-
8
- beforeEach(() => {
9
- decoder = new MessageDecode();
10
- });
11
-
12
- describe("requestDecode()", () => {
13
- it("should decode BASE64 + JSON request", () => {
14
- const payload = { request: { body: { key: "value" } } };
15
- const base64 = Buffer.from(JSON.stringify(payload)).toString("base64");
16
- const request = {
17
- Name: "test",
18
- Message: base64,
19
- Encoding: MessageEncoding[MessageEncoding.BASE64],
20
- Type: MessageType[MessageType.JSON],
21
- };
22
-
23
- const result = decoder.requestDecode(request as any);
24
- expect(result).toEqual(payload);
25
- });
26
-
27
- it("should decode STRING + JSON request", () => {
28
- const payload = { request: { body: { key: "value" } } };
29
- const request = {
30
- Name: "test",
31
- Message: JSON.stringify(payload),
32
- Encoding: MessageEncoding[MessageEncoding.STRING],
33
- Type: MessageType[MessageType.JSON],
34
- };
35
-
36
- const result = decoder.requestDecode(request as any);
37
- expect(result).toEqual(payload);
38
- });
39
-
40
- it("should decode BASE64 + XML request", () => {
41
- const xml = "<root><key>value</key></root>";
42
- const base64 = Buffer.from(xml).toString("base64");
43
- const request = {
44
- Name: "test",
45
- Message: base64,
46
- Encoding: MessageEncoding[MessageEncoding.BASE64],
47
- Type: MessageType[MessageType.XML],
48
- };
49
-
50
- const result = decoder.requestDecode(request as any);
51
- expect(result).toBeDefined();
52
- expect((result as any).root).toBeDefined();
53
- });
54
-
55
- it("should decode STRING + XML request", () => {
56
- const xml = "<root><key>value</key></root>";
57
- const request = {
58
- Name: "test",
59
- Message: xml,
60
- Encoding: MessageEncoding[MessageEncoding.STRING],
61
- Type: MessageType[MessageType.XML],
62
- };
63
-
64
- const result = decoder.requestDecode(request as any);
65
- expect(result).toBeDefined();
66
- expect((result as any).root).toBeDefined();
67
- });
68
-
69
- it("should throw for unsupported encoding", () => {
70
- const request = {
71
- Name: "test",
72
- Message: "data",
73
- Encoding: "UNKNOWN",
74
- Type: MessageType[MessageType.JSON],
75
- };
76
-
77
- expect(() => decoder.requestDecode(request as any)).toThrow("Unsupported encoding: UNKNOWN");
78
- });
79
- });
80
-
81
- describe("decodeType()", () => {
82
- it("should decode JSON string to object", () => {
83
- const json = '{"key":"value"}';
84
- const result = decoder.decodeType(json, MessageType[MessageType.JSON]);
85
- expect(result).toEqual({ key: "value" });
86
- });
87
-
88
- it("should decode XML string to object", () => {
89
- const xml = "<root><item>test</item></root>";
90
- const result = decoder.decodeType(xml, MessageType[MessageType.XML]);
91
- expect(result).toBeDefined();
92
- expect((result as any).root).toBeDefined();
93
- });
94
-
95
- it("should throw for unsupported type", () => {
96
- expect(() => decoder.decodeType("data", "BINARY")).toThrow("Unsupported type: BINARY");
97
- });
98
-
99
- it("should throw for TEXT type (not supported in decode)", () => {
100
- expect(() => decoder.decodeType("data", MessageType[MessageType.TEXT])).toThrow("Unsupported type: TEXT");
101
- });
102
- });
103
-
104
- describe("responseEncode()", () => {
105
- it("should encode response with BASE64 + JSON", () => {
106
- const ctx = {
107
- response: {
108
- data: { result: "ok" },
109
- contentType: "application/json",
110
- },
111
- };
112
-
113
- const result = decoder.responseEncode(
114
- ctx as any,
115
- MessageEncoding[MessageEncoding.BASE64],
116
- MessageType[MessageType.JSON],
117
- );
118
-
119
- expect(result.Encoding).toBe(MessageEncoding[MessageEncoding.BASE64]);
120
- expect(result.Type).toBe(MessageType[MessageType.JSON]);
121
- // The message should be base64 encoded
122
- const decoded = Buffer.from(result.Message, "base64").toString("utf-8");
123
- expect(JSON.parse(decoded)).toEqual({ result: "ok" });
124
- });
125
-
126
- it("should encode response with STRING + JSON", () => {
127
- const ctx = {
128
- response: {
129
- data: { result: "ok" },
130
- contentType: "application/json",
131
- },
132
- };
133
-
134
- const result = decoder.responseEncode(
135
- ctx as any,
136
- MessageEncoding[MessageEncoding.STRING],
137
- MessageType[MessageType.JSON],
138
- );
139
-
140
- expect(result.Encoding).toBe(MessageEncoding[MessageEncoding.STRING]);
141
- });
142
-
143
- it("should encode response with TEXT content type", () => {
144
- const ctx = {
145
- response: {
146
- data: "hello world",
147
- contentType: "text/plain",
148
- },
149
- };
150
-
151
- const result = decoder.responseEncode(
152
- ctx as any,
153
- MessageEncoding[MessageEncoding.STRING],
154
- MessageType[MessageType.TEXT],
155
- );
156
-
157
- expect(result.Encoding).toBe(MessageEncoding[MessageEncoding.STRING]);
158
- expect(result.Type).toBe(MessageType[MessageType.TEXT]);
159
- });
160
-
161
- it("should throw for unsupported encoding", () => {
162
- const ctx = {
163
- response: {
164
- data: "test",
165
- contentType: "text/plain",
166
- },
167
- };
168
-
169
- expect(() => decoder.responseEncode(ctx as any, "UNKNOWN", MessageType[MessageType.JSON])).toThrow(
170
- "Unsupported encoding: UNKNOWN",
171
- );
172
- });
173
- });
174
-
175
- describe("responseErrorEncode()", () => {
176
- it("should encode error with BASE64", () => {
177
- const result = decoder.responseErrorEncode(
178
- "Error occurred",
179
- MessageEncoding[MessageEncoding.BASE64],
180
- MessageType[MessageType.TEXT],
181
- );
182
-
183
- const decoded = Buffer.from(result, "base64").toString("utf-8");
184
- expect(decoded).toBe("Error occurred");
185
- });
186
-
187
- it("should encode error with STRING", () => {
188
- const result = decoder.responseErrorEncode(
189
- "Error occurred",
190
- MessageEncoding[MessageEncoding.STRING],
191
- MessageType[MessageType.TEXT],
192
- );
193
-
194
- expect(result).toBe("Error occurred");
195
- });
196
-
197
- it("should encode JSON error with BASE64", () => {
198
- const error = JSON.stringify({ code: 500, message: "Server error" });
199
- const result = decoder.responseErrorEncode(
200
- error,
201
- MessageEncoding[MessageEncoding.BASE64],
202
- MessageType[MessageType.JSON],
203
- );
204
-
205
- const decoded = Buffer.from(result, "base64").toString("utf-8");
206
- expect(JSON.parse(decoded)).toBe(error);
207
- });
208
-
209
- it("should throw for unsupported encoding", () => {
210
- expect(() => decoder.responseErrorEncode("Error", "UNKNOWN", MessageType[MessageType.TEXT])).toThrow(
211
- "Unsupported encoding: UNKNOWN",
212
- );
213
- });
214
- });
215
-
216
- describe("responseDecode()", () => {
217
- it("should decode BASE64 + JSON response", () => {
218
- const data = { result: "ok" };
219
- const base64 = Buffer.from(JSON.stringify(data)).toString("base64");
220
- const response = {
221
- Message: base64,
222
- Encoding: MessageEncoding[MessageEncoding.BASE64],
223
- Type: MessageType[MessageType.JSON],
224
- };
225
-
226
- const result = decoder.responseDecode(response as any);
227
- expect(result).toEqual(data);
228
- });
229
-
230
- it("should decode STRING + JSON response", () => {
231
- const data = { result: "ok" };
232
- const response = {
233
- Message: JSON.stringify(data),
234
- Encoding: MessageEncoding[MessageEncoding.STRING],
235
- Type: MessageType[MessageType.JSON],
236
- };
237
-
238
- const result = decoder.responseDecode(response as any);
239
- expect(result).toEqual(data);
240
- });
241
-
242
- it("should decode BASE64 + XML response", () => {
243
- const xml = "<root><key>value</key></root>";
244
- const base64 = Buffer.from(xml).toString("base64");
245
- const response = {
246
- Message: base64,
247
- Encoding: MessageEncoding[MessageEncoding.BASE64],
248
- Type: MessageType[MessageType.XML],
249
- };
250
-
251
- const result = decoder.responseDecode(response as any);
252
- expect(result).toBeDefined();
253
- });
254
-
255
- it("should throw for unsupported encoding in response", () => {
256
- const response = {
257
- Message: "data",
258
- Encoding: "UNKNOWN",
259
- Type: MessageType[MessageType.JSON],
260
- };
261
-
262
- expect(() => decoder.responseDecode(response as any)).toThrow("Unsupported encoding: UNKNOWN");
263
- });
264
- });
265
-
266
- describe("encodeType()", () => {
267
- it("should encode object to JSON string", () => {
268
- const result = decoder.encodeType({ key: "value" }, MessageType[MessageType.JSON]);
269
- expect(result).toBe('{"key":"value"}');
270
- });
271
-
272
- it("should encode TEXT to string", () => {
273
- const result = decoder.encodeType("hello", MessageType[MessageType.TEXT]);
274
- expect(result).toBe("hello");
275
- });
276
-
277
- it("should encode HTML to string", () => {
278
- const result = decoder.encodeType("<h1>Hello</h1>", MessageType[MessageType.HTML]);
279
- expect(result).toBe("<h1>Hello</h1>");
280
- });
281
-
282
- it("should encode object to XML string", () => {
283
- const result = decoder.encodeType({ root: { key: "value" } }, MessageType[MessageType.XML]);
284
- expect(typeof result).toBe("string");
285
- expect(result).toContain("key");
286
- });
287
-
288
- it("should throw for unsupported type", () => {
289
- expect(() => decoder.encodeType("data", "BINARY")).toThrow("Unsupported type: BINARY");
290
- });
291
- });
292
-
293
- describe("mapContentType()", () => {
294
- it("should map application/json to JSON", () => {
295
- expect(decoder.mapContentType("application/json")).toBe(MessageType.JSON);
296
- });
297
-
298
- it("should map text/html to HTML", () => {
299
- expect(decoder.mapContentType("text/html")).toBe(MessageType.HTML);
300
- });
301
-
302
- it("should map text/xml to XML", () => {
303
- expect(decoder.mapContentType("text/xml")).toBe(MessageType.XML);
304
- });
305
-
306
- it("should default to TEXT for unknown content type", () => {
307
- expect(decoder.mapContentType("text/plain")).toBe(MessageType.TEXT);
308
- });
309
-
310
- it("should default to TEXT for empty string", () => {
311
- expect(decoder.mapContentType("")).toBe(MessageType.TEXT);
312
- });
313
- });
314
- });