@blokjs/trigger-grpc 0.6.17 → 0.6.19

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,162 +0,0 @@
1
- import fs from "node:fs";
2
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
-
4
- // Use vi.hoisted for mocks referenced inside vi.mock factories
5
- const { mockCall } = vi.hoisted(() => {
6
- const mockCall = vi.fn().mockResolvedValue({
7
- Message: Buffer.from(JSON.stringify({ result: "ok" })).toString("base64"),
8
- Encoding: "BASE64",
9
- Type: "JSON",
10
- });
11
- return { mockCall };
12
- });
13
-
14
- vi.mock("../../src/GrpcClient", () => {
15
- class MockGrpcClient {
16
- call = mockCall;
17
- }
18
- return {
19
- default: MockGrpcClient,
20
- HttpVersionEnum: { HTTP1: "1.1", HTTP2: "2" },
21
- TransportEnum: { GRPC: "grpc", GRPC_WEB: "grpc-web", CONNECT: "connect" },
22
- };
23
- });
24
-
25
- vi.mock("../../src/MessageDecode", () => {
26
- class MockMessageDecode {
27
- responseDecode() {
28
- return { result: "ok" };
29
- }
30
- }
31
- return { default: MockMessageDecode };
32
- });
33
-
34
- import NanoSDK, { NanoSDKClient } from "../../src/NanoSDK";
35
-
36
- describe("NanoSDK", () => {
37
- let sdk: NanoSDK;
38
-
39
- beforeEach(() => {
40
- sdk = new NanoSDK();
41
- vi.clearAllMocks();
42
- });
43
-
44
- afterEach(() => {
45
- vi.restoreAllMocks();
46
- });
47
-
48
- describe("createClient()", () => {
49
- it("should create client with explicit host and token", () => {
50
- const client = sdk.createClient("localhost:8433", "my-token");
51
- expect(client).toBeDefined();
52
- expect(client).toBeInstanceOf(NanoSDKClient);
53
- });
54
-
55
- it("should create client with host only (empty token)", () => {
56
- const client = sdk.createClient("myhost:9090");
57
- expect(client).toBeDefined();
58
- });
59
-
60
- it("should read nanosdk.json when no host provided", () => {
61
- vi.spyOn(fs, "existsSync").mockReturnValue(true);
62
- vi.spyOn(fs, "readFileSync").mockReturnValue(JSON.stringify({ host: "127.0.0.1:5000", token: "file-token" }));
63
-
64
- const client = sdk.createClient();
65
- expect(fs.existsSync).toHaveBeenCalled();
66
- expect(fs.readFileSync).toHaveBeenCalled();
67
- expect(client).toBeDefined();
68
- });
69
-
70
- it("should use default host when no host and no nanosdk.json", () => {
71
- vi.spyOn(fs, "existsSync").mockReturnValue(false);
72
-
73
- const client = sdk.createClient();
74
- expect(client).toBeDefined();
75
- });
76
-
77
- it("should throw for host without port and without protocol", () => {
78
- expect(() => sdk.createClient("invalidhost")).toThrow(
79
- "Invalid host format. The host must have the format domain:port",
80
- );
81
- });
82
-
83
- it("should accept host with http:// prefix", () => {
84
- const client = sdk.createClient("http://localhost");
85
- expect(client).toBeDefined();
86
- });
87
-
88
- it("should accept host with https:// prefix", () => {
89
- const client = sdk.createClient("https://myserver");
90
- expect(client).toBeDefined();
91
- });
92
- });
93
- });
94
-
95
- describe("NanoSDKClient", () => {
96
- let client: NanoSDKClient;
97
-
98
- beforeEach(() => {
99
- vi.clearAllMocks();
100
- const sdk = new NanoSDK();
101
- client = sdk.createClient("localhost:8433", "test-token");
102
- });
103
-
104
- describe("python3()", () => {
105
- it("should build correct request for Python3 node", async () => {
106
- const result = await client.python3("my-node", { url: "http://example.com" });
107
- expect(mockCall).toHaveBeenCalled();
108
- const callArgs = mockCall.mock.calls[0];
109
- const request = callArgs[0];
110
- expect(request.Name).toBe("my-node");
111
- expect(request.Encoding).toBe("BASE64");
112
- expect(request.Type).toBe("JSON");
113
- const decoded = JSON.parse(Buffer.from(request.Message, "base64").toString("utf-8"));
114
- expect(decoded.workflow.steps[0].type).toBe("runtime.python3");
115
- expect(decoded.workflow.steps[0].node).toBe("my-node");
116
- });
117
-
118
- it("should pass inputs to the workflow node config", async () => {
119
- const inputs = { url: "http://api.com", method: "POST" };
120
- await client.python3("api-call", inputs);
121
- const request = mockCall.mock.calls[0][0];
122
- const decoded = JSON.parse(Buffer.from(request.Message, "base64").toString("utf-8"));
123
- expect(decoded.workflow.nodes.node.inputs).toEqual(inputs);
124
- });
125
-
126
- it("should return decoded response", async () => {
127
- const result = await client.python3("my-node", {});
128
- expect(result).toEqual({ result: "ok" });
129
- });
130
- });
131
-
132
- describe("nodejs()", () => {
133
- it("should build correct request for Node.js node", async () => {
134
- await client.nodejs("my-node", { data: "test" });
135
- const request = mockCall.mock.calls[0][0];
136
- const decoded = JSON.parse(Buffer.from(request.Message, "base64").toString("utf-8"));
137
- expect(decoded.workflow.steps[0].type).toBe("module");
138
- expect(decoded.workflow.steps[0].node).toBe("my-node");
139
- });
140
-
141
- it("should use custom type parameter", async () => {
142
- await client.nodejs("my-node", {}, "local");
143
- const request = mockCall.mock.calls[0][0];
144
- const decoded = JSON.parse(Buffer.from(request.Message, "base64").toString("utf-8"));
145
- expect(decoded.workflow.steps[0].type).toBe("local");
146
- });
147
-
148
- it("should include http trigger in workflow", async () => {
149
- await client.nodejs("my-node", {});
150
- const request = mockCall.mock.calls[0][0];
151
- const decoded = JSON.parse(Buffer.from(request.Message, "base64").toString("utf-8"));
152
- expect(decoded.workflow.trigger.http).toBeDefined();
153
- expect(decoded.workflow.trigger.http.method).toBe("GET");
154
- });
155
-
156
- it("should pass authorization header", async () => {
157
- await client.nodejs("my-node", {});
158
- const callOpts = mockCall.mock.calls[0][1];
159
- expect(callOpts.headers.Authorization).toBe("Bearer test-token");
160
- });
161
- });
162
- });
@@ -1,16 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import nodes from "../../src/Nodes";
3
-
4
- describe("Nodes", () => {
5
- it("should export an object with node keys", () => {
6
- expect(typeof nodes).toBe("object");
7
- });
8
-
9
- it("should have @blokjs/api-call key", () => {
10
- expect(nodes["@blokjs/api-call"]).toBeDefined();
11
- });
12
-
13
- it("should have @blokjs/if-else key", () => {
14
- expect(nodes["@blokjs/if-else"]).toBeDefined();
15
- });
16
- });
package/buf.gen.yaml DELETED
@@ -1,11 +0,0 @@
1
- version: v2
2
- clean: true
3
- plugins:
4
- - local: protoc-gen-es
5
- opt: target=ts
6
- out: src/gen
7
- include_imports: true
8
- # - local: protoc-gen-connect-es
9
- # opt: target=ts
10
- # out: src
11
- # include_imports: true
package/buf.yaml DELETED
@@ -1,9 +0,0 @@
1
- version: v2
2
- breaking:
3
- use:
4
- - FILE
5
- lint:
6
- use:
7
- - STANDARD
8
- modules:
9
- - path: proto
@@ -1,28 +0,0 @@
1
- -----BEGIN PRIVATE KEY-----
2
- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNjfXRKBwXU0IH
3
- ftJJGiR5w6Ccf2JfPZJgDdarhVgJjL2cy9d4AwIq4ydiuU+H8MnguzdGrFaCgYOB
4
- GfgEI4dOAGr1AInRVVHRWKvwGdLYm59dBRi5PQuU2EKVonQNsZy/qcOJSBzBSSAx
5
- PFCpTwrxj0j/Dug6LxIa1wB7UenYn5NjkFSF8F5HufE7l4goIVh0/fVgRripCsnk
6
- iMQFVhMr+2glX+19zTVkBl9EtAPbkXsegUUdnkOH2sd1TBN4HUibnktX+P1aIlhd
7
- p741Eni42jU92u33iZasvvnkA94Q2MhBhzx3lgqAAcHcePzBI9yOEQbTqik4Nkpv
8
- moqqDFBbAgMBAAECggEACDu0aeFCZsjF70jsIVNzvJDSYRJVHV14/HHxdENOCGvj
9
- uGENy1fLgW5ByJmFjvtdCqxVBXanrGiFnOkuXvQRWlV380JHQuQ497qmgGJ4aIar
10
- Nm2a1OiWCysyV43/OgEwNxkUpO4HgNJuAKrazD1HQe+sS9MMCDCUeBC+izH3vN5s
11
- 9LWOrhde+ZwCkHJgRxp6V5HBJXU/27T02ZjgvPXupzXQ2ozRgx2gn5lLvJJfqG/h
12
- jEMi9qyuwoRUL4QXDg3TNHHSllnENdRrVJr7VsvYpRpQogVsr4V7zIZiFkAcbuC4
13
- kMuHeahkjqmlSYVuz9DxPHcmFRW/B5MI5MLQwCvI6QKBgQD61emfMrA323QIWF5l
14
- hbNQBS3hje9pwN27EU3QmCq0z/2Ja0TTaSeNSdlQAfMEGHsO5tL0ldqS267uqs5r
15
- clrukrOFmcARZiHne5U1uMcWgYvRmPTTdwng1lQSBuLo7XR9f6sW3u1csOJ8PY4w
16
- oKtsAIKm0r53iVRCPpd7D9Lr3QKBgQDRyWIccS93kI2rmRxkg4nhniCP8uAacYHy
17
- ZEZUFpm0p23rLKF7zlGd1xZmwKV5lnd1278qBt9YMvDGw6Mlt3WTQUh9XQ3b5q1V
18
- xOHfyn2QvWfFbX/tWousq2RP3CJakGiKMefSx8aZB/Vwat3kSdgz825Vcr9oN2j1
19
- lZZemRlllwKBgD+K1QXpN07PHxPGHxOkzQnmZfsPk6i8nO74sTe4dIkdb2LSc7sC
20
- lmxqWsyz0bYl5Xae7q3bEGXHlQcM6gG6FGL/cs7TZh6COvCDFAdp6bU/2AWes9al
21
- /zCf2ug+KllLXgk0wEio7IRgot9KUKzs5sATWQWduXZaqaemZ4VbOtlZAoGAK457
22
- b1pUt6dssq8khP4Gl7CEJD8SJotgppoJPBZBLZABs21dzd3FdlcdEJJ5COijvvW0
23
- GB67Ko3RDgO6kO8pWzyXt2elo/2eCYvKNfPN5EpfDE+y2u4Mx/oB5s7W1yTaf67i
24
- 6hGOe2F6pS+bCHYIjKjDRLyBXzr58NtxEA0Lh9sCgYEA6dI03OhJpruHxyOE3HYE
25
- oSDah3wr8WUw5BsGDsrW2tMVV7Y3YRO02mL/DB17bmM1FzS5s0n8DKU0c2wViFm4
26
- ZI4wZdm1hA1MBQBEFVQlVkmwtfyhmsnr98Huckd58PfMUZf6KJE9L4h7SXtPa/VL
27
- 492ASgwAEWWqFlfK6wSrHiM=
28
- -----END PRIVATE KEY-----
package/localhost+2.pem DELETED
@@ -1,27 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEoTCCAwmgAwIBAgIRAKSu5ey0gTHNC82jEhdfdpYwDQYJKoZIhvcNAQELBQAw
3
- gbExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTFDMEEGA1UECww6bWFy
4
- Y29ATWFyY29zLU1hY0Jvb2stUHJvLmxvY2FsIChNYXJjbyBDYXN0aWxsbyBEZWxs
5
- YSBTZXJhKTFKMEgGA1UEAwxBbWtjZXJ0IG1hcmNvQE1hcmNvcy1NYWNCb29rLVBy
6
- by5sb2NhbCAoTWFyY28gQ2FzdGlsbG8gRGVsbGEgU2VyYSkwHhcNMjUwMjAzMDE1
7
- MjM5WhcNMjcwNTAzMDE1MjM5WjBuMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1l
8
- bnQgY2VydGlmaWNhdGUxQzBBBgNVBAsMOm1hcmNvQE1hcmNvcy1NYWNCb29rLVBy
9
- by5sb2NhbCAoTWFyY28gQ2FzdGlsbG8gRGVsbGEgU2VyYSkwggEiMA0GCSqGSIb3
10
- DQEBAQUAA4IBDwAwggEKAoIBAQDNjfXRKBwXU0IHftJJGiR5w6Ccf2JfPZJgDdar
11
- hVgJjL2cy9d4AwIq4ydiuU+H8MnguzdGrFaCgYOBGfgEI4dOAGr1AInRVVHRWKvw
12
- GdLYm59dBRi5PQuU2EKVonQNsZy/qcOJSBzBSSAxPFCpTwrxj0j/Dug6LxIa1wB7
13
- UenYn5NjkFSF8F5HufE7l4goIVh0/fVgRripCsnkiMQFVhMr+2glX+19zTVkBl9E
14
- tAPbkXsegUUdnkOH2sd1TBN4HUibnktX+P1aIlhdp741Eni42jU92u33iZasvvnk
15
- A94Q2MhBhzx3lgqAAcHcePzBI9yOEQbTqik4NkpvmoqqDFBbAgMBAAGjdjB0MA4G
16
- A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBTN
17
- imcw8dRZ+LdM83iq2xnhRgHVMjAsBgNVHREEJTAjgglsb2NhbGhvc3SHBH8AAAGH
18
- EAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQADggGBAIA2HiGT0dtdkNfB
19
- LFAIUvlatqHkH4Pds3jd0TnT4muoebPoHc3HSoqnSdt4g2vN+75S47G7E5b/qQbH
20
- ZfkL9kgZoCar79DuVpC/kCPI/NACRsqdgIcnd09FqN2Dmg1UP2F/nulLucWfOiSL
21
- T3q3nVEAm3UL4R5VopFW94bp8jJ/cWseDohIGZBza4yUiMnbd6mK+g+DoExfGbwc
22
- A3601xeDWcDxKv+KaBWQeyoUWO66FKYOJcdwaiPCPrvXVz3tdbxBpHB/beNeulaU
23
- 6EzDRCmtIwEZNwq9MNn0wViOjta1TtkeERtbvnmgPmFhhSbHDtGbbxuwWnV91aZg
24
- 0JFymKsmmBIv4Qu50zVPo7Jz0n6CucIPVUW8ZoamVBr6ljHOfZIg9N0hkRoX7DUT
25
- pPV22KliCRZCHYnyVcIzwtW2lxlzydUnldhxZga6vlfoKR5WzCceTtsX2+p8dbJe
26
- p5jVRsLyT/sfECb8n5N7BYRLSh36FekFGErFCr9Svqd9pRVsWg==
27
- -----END CERTIFICATE-----
@@ -1,33 +0,0 @@
1
- syntax = "proto3";
2
-
3
- package blok.workflow.v1;
4
-
5
- message WorkflowRequest {
6
- string Name = 1;
7
- string Message = 2;
8
- string Encoding = 3;
9
- string Type = 4;
10
- }
11
-
12
- message WorkflowResponse {
13
- string Message = 1;
14
- string Encoding = 2;
15
- string Type = 3;
16
- }
17
-
18
- enum MessageEncoding {
19
- BASE64 = 0;
20
- STRING = 1;
21
- }
22
-
23
- enum MessageType {
24
- TEXT = 0;
25
- JSON = 1;
26
- XML = 2;
27
- HTML = 3;
28
- BINARY = 4;
29
- }
30
-
31
- service WorkflowService {
32
- rpc ExecuteWorkflow (WorkflowRequest) returns (WorkflowResponse) {}
33
- }
@@ -1,265 +0,0 @@
1
- import {
2
- DefaultLogger,
3
- type GlobalOptions,
4
- NodeMap,
5
- type ParamsDictionary,
6
- TriggerBase,
7
- type TriggerResponse,
8
- } from "@blokjs/runner";
9
- import { type Context, GlobalError } from "@blokjs/shared";
10
- import type { ConnectRouter } from "@connectrpc/connect";
11
- import { type Span, SpanStatusCode, metrics, trace } from "@opentelemetry/api";
12
- import fastify from "fastify";
13
- import { v4 as uuid } from "uuid";
14
- import MessageDecode from "./MessageDecode";
15
- import nodes from "./Nodes";
16
- import workflows from "./Workflows";
17
- import type RuntimeWorkflow from "./types/RuntimeWorkflow";
18
-
19
- import { type Step, Workflow } from "@blokjs/helper";
20
- import type { TriggerOpts } from "@blokjs/helper/dist/types/TriggerOpts";
21
- import {
22
- MessageEncoding,
23
- MessageType,
24
- type WorkflowRequest,
25
- type WorkflowResponse,
26
- WorkflowService,
27
- } from "./gen/workflow_pb";
28
-
29
- enum NodeTypes {
30
- MODULE = "module",
31
- LOCAL = "local",
32
- PYTHON3 = "runtime.python3",
33
- }
34
-
35
- export default class GRpcTrigger extends TriggerBase {
36
- private server = fastify({
37
- http2: true,
38
- // https: {
39
- // key: readFileSync("localhost+2-key.pem", "utf8"),
40
- // cert: readFileSync("localhost+2.pem", "utf8"),
41
- // }
42
- });
43
- private nodeMap: GlobalOptions = <GlobalOptions>{};
44
- protected tracer = trace.getTracer(
45
- process.env.PROJECT_NAME || "trigger-grpc-workflow",
46
- process.env.PROJECT_VERSION || "0.0.1",
47
- );
48
- private logger = new DefaultLogger();
49
-
50
- constructor() {
51
- super();
52
- this.loadNodes();
53
- this.loadWorkflows();
54
- }
55
-
56
- getApp() {
57
- return this.server;
58
- }
59
-
60
- async listen(): Promise<number> {
61
- return 0;
62
- }
63
-
64
- loadNodes() {
65
- this.nodeMap.nodes = new NodeMap();
66
- const nodeKeys = Object.keys(nodes);
67
- for (const key of nodeKeys) {
68
- this.nodeMap.nodes.addNode(key, nodes[key]);
69
- }
70
- }
71
-
72
- loadWorkflows() {
73
- this.nodeMap.workflows = workflows;
74
- }
75
-
76
- processRequest(router: ConnectRouter, trigger: GRpcTrigger) {
77
- router.service(WorkflowService, {
78
- executeWorkflow: (request: WorkflowRequest) => trigger.executeWorkflow(request),
79
- });
80
- }
81
-
82
- async executeWorkflow(request: WorkflowRequest) {
83
- const start = performance.now();
84
- const coder = new MessageDecode();
85
- let name = request.Name;
86
- const messageContext: Context = coder.requestDecode(request);
87
- const runtimeWorkflow = messageContext as unknown as RuntimeWorkflow;
88
- const id: string = (messageContext.request.query?.requestId as string) || (uuid() as string);
89
- let remoteNodeExecution = false;
90
-
91
- const defaultMeter = metrics.getMeter("default");
92
- const workflow_runner_errors = defaultMeter.createCounter("workflow_errors", {
93
- description: "Workflow runner errors",
94
- });
95
-
96
- return await this.tracer.startActiveSpan(`${name}`, async (span: Span) => {
97
- try {
98
- if (runtimeWorkflow !== undefined) {
99
- const workflowModel = runtimeWorkflow.workflow;
100
- const node_type = (workflowModel.steps[0] as unknown as ParamsDictionary).type;
101
- let set_node_type: NodeTypes = NodeTypes.MODULE;
102
- switch (node_type) {
103
- case "runtime.python3":
104
- set_node_type = NodeTypes.PYTHON3;
105
- break;
106
- case "local":
107
- set_node_type = NodeTypes.LOCAL;
108
- break;
109
- default:
110
- set_node_type = NodeTypes.MODULE;
111
- break;
112
- }
113
-
114
- const trigger = Object.keys(workflowModel.trigger)[0];
115
- const trigger_config =
116
- ((workflowModel.trigger as unknown as ParamsDictionary)[trigger] as unknown as TriggerOpts) || {};
117
-
118
- const step: Step = Workflow({
119
- name: `Remote Node: ${name}`,
120
- version: "1.0.0",
121
- description: "Remote Node",
122
- })
123
- .addTrigger((trigger as unknown as "http") || "grpc", trigger_config)
124
- .addStep({
125
- name: "node",
126
- node: name,
127
- type: set_node_type,
128
- inputs: ((workflowModel.nodes as unknown as ParamsDictionary).node as unknown as ParamsDictionary).inputs,
129
- });
130
-
131
- this.nodeMap.workflows[id] = step;
132
- name = id;
133
- remoteNodeExecution = true;
134
- }
135
-
136
- await this.configuration.init(name, this.nodeMap);
137
- let ctx: Context = this.createContext(undefined, name, id);
138
- ctx.request = messageContext.request;
139
- ctx.logger.log(`Workflow: ${name}, Version: ${this.configuration.version}`);
140
-
141
- const response: TriggerResponse = await this.run(ctx);
142
- ctx = response.ctx;
143
- const average = response.metrics;
144
-
145
- // Support both module nodes (wrapped BlokResponse with .data/.contentType)
146
- // and runtime adapter nodes (raw data without wrapper)
147
- const hasWrapper =
148
- ctx.response && typeof ctx.response === "object" && "data" in ctx.response && "contentType" in ctx.response;
149
- if (!hasWrapper) {
150
- // Runtime adapter node: ctx.response is raw data, wrap it
151
- ctx.response = {
152
- data: ctx.response,
153
- contentType: "application/json",
154
- success: true,
155
- error: null,
156
- } as typeof ctx.response;
157
- }
158
- if (ctx.response.contentType === undefined || ctx.response.contentType === "")
159
- ctx.response.contentType = "application/json";
160
-
161
- const end = performance.now();
162
- ctx.logger.log(`Completed in ${(end - start).toFixed(2)}ms`);
163
-
164
- span.setAttribute("success", true);
165
- span.setAttribute("Content-Type", ctx.response.contentType as string);
166
- span.setAttribute("workflow_request_id", `${ctx.id}`);
167
- span.setAttribute("workflow_elapsed_time", `${end - start}`);
168
- span.setAttribute("workflow_version", `${this.configuration.version}`);
169
- span.setAttribute("workflow_name", `${this.configuration.name}`);
170
- span.setAttribute("workflow_memory_avg_mb", `${average.memory.total}`);
171
- span.setAttribute("workflow_memory_min_mb", `${average.memory.min}`);
172
- span.setAttribute("workflow_memory_max_mb", `${average.memory.max}`);
173
- span.setAttribute("workflow_cpu_percentage", `${average.cpu.average}`);
174
- span.setAttribute("workflow_cpu_total", `${average.cpu.total}`);
175
- span.setAttribute("workflow_cpu_usage", `${average.cpu.usage}`);
176
- span.setAttribute("workflow_cpu_model", `${average.cpu.model}`);
177
- span.setStatus({ code: SpanStatusCode.OK });
178
-
179
- return coder.responseEncode(ctx, request.Encoding, request.Type);
180
- } catch (e: unknown) {
181
- span.setAttribute("success", false);
182
- span.setAttribute("workflow_request_id", `${id}`);
183
- span.recordException(e as Error);
184
- let message: WorkflowResponse = <WorkflowResponse>{};
185
- const base64Key = MessageEncoding[MessageEncoding.BASE64];
186
- const textKey = MessageType[MessageType.TEXT];
187
- const jsonKey = MessageType[MessageType.JSON];
188
-
189
- if (e instanceof GlobalError) {
190
- const error_context = e as GlobalError;
191
-
192
- if (error_context.context.message === "{}" && error_context.context.json instanceof DOMException) {
193
- workflow_runner_errors.add(1, {
194
- env: process.env.NODE_ENV,
195
- workflow_version: `${this.configuration.version || "unknown"}`,
196
- workflow_name: `${name || this.configuration.name}`,
197
- });
198
- span.setStatus({
199
- code: SpanStatusCode.ERROR,
200
- message: (error_context.context.json as Error).toString(),
201
- });
202
-
203
- this.logger.error(`${(error_context.context.json as Error).toString()}`);
204
- message = {
205
- Message: coder.responseErrorEncode((error_context.context.json as Error).toString(), base64Key, textKey),
206
- Encoding: base64Key,
207
- Type: textKey,
208
- } as WorkflowResponse;
209
- } else {
210
- if (error_context.context.code === undefined) error_context.setCode(500);
211
-
212
- if (error_context.hasJson()) {
213
- workflow_runner_errors.add(1, {
214
- env: process.env.NODE_ENV,
215
- workflow_version: `${this.configuration.version || "unknown"}`,
216
- workflow_name: `${name || this.configuration.name}`,
217
- });
218
- span.setStatus({ code: SpanStatusCode.ERROR, message: JSON.stringify(error_context.context.json) });
219
- this.logger.error(`${JSON.stringify(error_context.context.json)}`);
220
- message = {
221
- Message: coder.responseErrorEncode(JSON.stringify(error_context.context.json), base64Key, textKey),
222
- Encoding: base64Key,
223
- Type: jsonKey,
224
- } as WorkflowResponse;
225
- } else {
226
- workflow_runner_errors.add(1, {
227
- env: process.env.NODE_ENV,
228
- workflow_version: `${this.configuration.version || "unknown"}`,
229
- workflow_name: `${name || this.configuration.name}`,
230
- });
231
- span.setStatus({ code: SpanStatusCode.ERROR, message: error_context.message });
232
- this.logger.error(`${error_context.message}`, error_context.stack?.replace(/\n/g, " "));
233
- message = {
234
- Message: coder.responseErrorEncode(error_context.message, base64Key, textKey),
235
- Encoding: MessageEncoding[MessageEncoding.BASE64],
236
- Type: textKey,
237
- } as WorkflowResponse;
238
- }
239
- }
240
- } else {
241
- workflow_runner_errors.add(1, {
242
- env: process.env.NODE_ENV,
243
- workflow_version: `${this.configuration.version || "unknown"}`,
244
- workflow_name: `${name || this.configuration.name}`,
245
- });
246
- span.setStatus({ code: SpanStatusCode.ERROR, message: (e as Error).message });
247
- this.logger.error(`${(e as Error).message}`, `${(e as Error).stack?.replace(/\n/g, " ")}`);
248
-
249
- message = {
250
- Message: coder.responseErrorEncode((e as Error).message, base64Key, textKey),
251
- Encoding: base64Key,
252
- Type: textKey,
253
- } as WorkflowResponse;
254
- }
255
-
256
- return message;
257
- } finally {
258
- if (remoteNodeExecution) {
259
- delete this.nodeMap.workflows[id];
260
- }
261
- span.end();
262
- }
263
- });
264
- }
265
- }
package/src/GrpcClient.ts DELETED
@@ -1,87 +0,0 @@
1
- import { type Transport, createClient } from "@connectrpc/connect";
2
- import { createGrpcTransport } from "@connectrpc/connect-node";
3
- import { createConnectTransport } from "@connectrpc/connect-node";
4
- import { createGrpcWebTransport } from "@connectrpc/connect-node";
5
- import { type WorkflowRequest, type WorkflowResponse, WorkflowService } from "./gen/workflow_pb";
6
-
7
- export type RpcOptions = {
8
- host: string;
9
- port: number;
10
- protocol: string;
11
- httpVersion: HttpVersionEnum;
12
- transport: TransportEnum;
13
- };
14
-
15
- export type CallOptions = {
16
- headers: Record<string, string>;
17
- };
18
-
19
- export enum TransportEnum {
20
- GRPC = "grpc",
21
- GRPC_WEB = "grpc-web",
22
- CONNECT = "connect",
23
- }
24
-
25
- export enum HttpVersionEnum {
26
- HTTP1 = "1.1",
27
- HTTP2 = "2",
28
- }
29
-
30
- export type { WorkflowRequest, WorkflowResponse };
31
-
32
- export default class GrpcClient {
33
- protected opts: RpcOptions;
34
-
35
- constructor(options: RpcOptions) {
36
- this.opts = options;
37
- }
38
-
39
- async call(message: WorkflowRequest, opts?: CallOptions): Promise<WorkflowResponse> {
40
- const transport = this.transport();
41
- const client = createClient(WorkflowService, transport);
42
- return await client.executeWorkflow(message, opts);
43
- }
44
-
45
- transport(): Transport {
46
- switch (this.opts.transport) {
47
- case TransportEnum.GRPC:
48
- return createGrpcTransport({
49
- baseUrl: `${this.opts.protocol}://${this.opts.host}:${this.opts.port}/`,
50
- interceptors: [],
51
- });
52
- case TransportEnum.GRPC_WEB:
53
- return createGrpcWebTransport({
54
- baseUrl: `${this.opts.protocol}://${this.opts.host}:${this.opts.port}/`,
55
- httpVersion: this.opts.httpVersion,
56
- interceptors: [],
57
- });
58
- case TransportEnum.CONNECT:
59
- return createConnectTransport({
60
- baseUrl: `${this.opts.protocol}://${this.opts.host}:${this.opts.port}/`,
61
- httpVersion: this.opts.httpVersion,
62
- interceptors: [],
63
- });
64
- default:
65
- throw new Error("Invalid transport type");
66
- }
67
- }
68
- }
69
-
70
- // let client = new GrpcClient({
71
- // host: "localhost",
72
- // port: 8433,
73
- // protocol: "http",
74
- // httpVersion: HttpVersionEnum.HTTP2,
75
- // transport: TransportEnum.GRPC,
76
- // });
77
-
78
- // client.call({
79
- // "Name": "countries",
80
- // "Message": "ewogICAgInJlcXVlc3QiOiB7CiAgICAgICAgImJvZHkiOiB7CiAgICAgICAgICAgICJjb3VudHJ5X25hbWUiOiAiQ2FuYWRhIgogICAgICAgIH0KICAgIH0KfQ==",
81
- // "Encoding": "BASE64",
82
- // "Type": "JSON"
83
- // } as WorkflowRequest).then((response) => {
84
- // console.log(response);
85
- // }).catch((error) => {
86
- // console.error(error);
87
- // });