@blokjs/trigger-grpc 0.2.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.
Files changed (75) hide show
  1. package/.env.example +8 -0
  2. package/CHANGELOG.md +143 -0
  3. package/README.md +25 -0
  4. package/__tests__/unit/GRpcTrigger.test.ts +313 -0
  5. package/__tests__/unit/GrpcClient.test.ts +138 -0
  6. package/__tests__/unit/GrpcServer.test.ts +127 -0
  7. package/__tests__/unit/MessageDecode.test.ts +314 -0
  8. package/__tests__/unit/NanoSDK.test.ts +162 -0
  9. package/__tests__/unit/Nodes.test.ts +16 -0
  10. package/buf.gen.yaml +11 -0
  11. package/buf.yaml +9 -0
  12. package/dist/GRpcTrigger.d.ts +18 -0
  13. package/dist/GRpcTrigger.js +219 -0
  14. package/dist/GRpcTrigger.js.map +1 -0
  15. package/dist/GrpcClient.d.ts +28 -0
  16. package/dist/GrpcClient.js +72 -0
  17. package/dist/GrpcClient.js.map +1 -0
  18. package/dist/GrpcServer.d.ts +14 -0
  19. package/dist/GrpcServer.js +54 -0
  20. package/dist/GrpcServer.js.map +1 -0
  21. package/dist/MessageDecode.d.ts +12 -0
  22. package/dist/MessageDecode.js +133 -0
  23. package/dist/MessageDecode.js.map +1 -0
  24. package/dist/NanoSDK.d.ts +13 -0
  25. package/dist/NanoSDK.js +169 -0
  26. package/dist/NanoSDK.js.map +1 -0
  27. package/dist/Nodes.d.ts +5 -0
  28. package/dist/Nodes.js +13 -0
  29. package/dist/Nodes.js.map +1 -0
  30. package/dist/Workflows.d.ts +3 -0
  31. package/dist/Workflows.js +5 -0
  32. package/dist/Workflows.js.map +1 -0
  33. package/dist/gen/workflow_pb.d.ts +113 -0
  34. package/dist/gen/workflow_pb.js +76 -0
  35. package/dist/gen/workflow_pb.js.map +1 -0
  36. package/dist/index.d.ts +10 -0
  37. package/dist/index.js +17 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/opentelemetry_metrics.d.ts +1 -0
  40. package/dist/opentelemetry_metrics.js +21 -0
  41. package/dist/opentelemetry_metrics.js.map +1 -0
  42. package/dist/proto/workflow.proto +33 -0
  43. package/dist/server.d.ts +1 -0
  44. package/dist/server.js +12 -0
  45. package/dist/server.js.map +1 -0
  46. package/dist/types/Message.d.ts +0 -0
  47. package/dist/types/Message.js +2 -0
  48. package/dist/types/Message.js.map +1 -0
  49. package/dist/types/RuntimeWorkflow.d.ts +5 -0
  50. package/dist/types/RuntimeWorkflow.js +3 -0
  51. package/dist/types/RuntimeWorkflow.js.map +1 -0
  52. package/dist/types/Workflows.d.ts +5 -0
  53. package/dist/types/Workflows.js +3 -0
  54. package/dist/types/Workflows.js.map +1 -0
  55. package/localhost+2-key.pem +28 -0
  56. package/localhost+2.pem +27 -0
  57. package/package.json +60 -0
  58. package/proto/workflow.proto +33 -0
  59. package/src/GRpcTrigger.ts +252 -0
  60. package/src/GrpcClient.ts +87 -0
  61. package/src/GrpcServer.ts +63 -0
  62. package/src/MessageDecode.ts +142 -0
  63. package/src/NanoSDK.ts +146 -0
  64. package/src/Nodes.ts +12 -0
  65. package/src/Workflows.ts +5 -0
  66. package/src/gen/workflow_pb.ts +142 -0
  67. package/src/index.ts +22 -0
  68. package/src/opentelemetry_metrics.ts +26 -0
  69. package/src/server.ts +8 -0
  70. package/src/types/Message.ts +0 -0
  71. package/src/types/RuntimeWorkflow.ts +7 -0
  72. package/src/types/Workflows.ts +7 -0
  73. package/tsconfig.json +34 -0
  74. package/vitest.config.ts +29 -0
  75. package/workflows/countries.json +31 -0
package/src/NanoSDK.ts ADDED
@@ -0,0 +1,146 @@
1
+ import fs from "node:fs";
2
+ import type { JsonLikeObject } from "@blokjs/runner";
3
+ import GrpcClient, { type RpcOptions, type WorkflowRequest, HttpVersionEnum, TransportEnum } from "./GrpcClient";
4
+ import MessageDecode from "./MessageDecode";
5
+
6
+ export default class NanoSDK {
7
+ public createClient(host?: string, token?: string) {
8
+ let _host = host || "localhost:8433";
9
+ let _token = token || "";
10
+
11
+ if (!host) {
12
+ const app_path = process.cwd();
13
+ // Validate if the file nanosdk.json exists
14
+ if (fs.existsSync(`${app_path}/nanosdk.json`)) {
15
+ const data = fs.readFileSync(`${app_path}/nanosdk.json`, "utf8");
16
+ const json = JSON.parse(data);
17
+ _host = json.host;
18
+ _token = json.token;
19
+ }
20
+ }
21
+
22
+ // Validate if the host does not have the format domain:port without http:// or https://
23
+ if (!_host.includes("http://") && !_host.includes("https://")) {
24
+ if (!_host.includes(":")) {
25
+ throw new Error("Invalid host format. The host must have the format domain:port");
26
+ }
27
+ }
28
+
29
+ // get host and port
30
+ const host_port = _host.split(":");
31
+
32
+ return new NanoSDKClient(
33
+ {
34
+ host: host_port[0] || "localhost",
35
+ port: Number.parseInt(host_port[1]),
36
+ protocol: "http",
37
+ httpVersion: HttpVersionEnum.HTTP2,
38
+ transport: TransportEnum.GRPC,
39
+ },
40
+ _token,
41
+ );
42
+ }
43
+ }
44
+
45
+ export class NanoSDKClient {
46
+ private client: GrpcClient;
47
+ private token: string;
48
+
49
+ constructor(options: RpcOptions, token: string) {
50
+ this.client = new GrpcClient(options);
51
+ this.token = token;
52
+ }
53
+
54
+ public async python3(nodeName: string, inputs: JsonLikeObject): Promise<JsonLikeObject> {
55
+ const workflow = {
56
+ name: "Remote Node",
57
+ description: "Execution of remote node",
58
+ version: "1.0.0",
59
+ trigger: {
60
+ grpc: {},
61
+ },
62
+ steps: [
63
+ {
64
+ name: "node",
65
+ node: nodeName,
66
+ type: "runtime.python3",
67
+ },
68
+ ],
69
+ nodes: {
70
+ node: {
71
+ inputs: inputs,
72
+ },
73
+ },
74
+ };
75
+
76
+ const base64Workflow = Buffer.from(JSON.stringify({ request: {}, workflow: workflow })).toString("base64");
77
+ const request: WorkflowRequest = {
78
+ $typeName: "blok.workflow.v1.WorkflowRequest",
79
+ Name: nodeName,
80
+ Message: base64Workflow,
81
+ Encoding: "BASE64",
82
+ Type: "JSON",
83
+ };
84
+
85
+ return await this.call(request);
86
+ }
87
+
88
+ public async nodejs(nodeName: string, inputs: JsonLikeObject, type = "module"): Promise<JsonLikeObject> {
89
+ const workflow = {
90
+ name: "Remote Node",
91
+ description: "Execution of remote node",
92
+ version: "1.0.0",
93
+ trigger: {
94
+ http: {
95
+ method: "GET",
96
+ path: "/",
97
+ accept: "application/json",
98
+ },
99
+ },
100
+ steps: [
101
+ {
102
+ name: "node",
103
+ node: nodeName,
104
+ type: type,
105
+ },
106
+ ],
107
+ nodes: {
108
+ node: {
109
+ inputs: inputs,
110
+ },
111
+ },
112
+ };
113
+
114
+ const base64Workflow = Buffer.from(JSON.stringify({ request: {}, workflow: workflow })).toString("base64");
115
+ const request: WorkflowRequest = {
116
+ $typeName: "blok.workflow.v1.WorkflowRequest",
117
+ Name: nodeName,
118
+ Message: base64Workflow,
119
+ Encoding: "BASE64",
120
+ Type: "JSON",
121
+ };
122
+
123
+ return await this.call(request);
124
+ }
125
+
126
+ protected async call(message: WorkflowRequest): Promise<JsonLikeObject> {
127
+ const response = await this.client.call(message, { headers: { Authorization: `Bearer ${this.token}` } });
128
+ const decode = new MessageDecode();
129
+ const responseDecoded = decode.responseDecode(response);
130
+ return responseDecoded;
131
+ }
132
+ }
133
+
134
+ // const client = new NanoSDK().createClient("127.0.0.1:8433", "");
135
+ // client.python3("api_call", {
136
+ // "url": "https://countriesnow.space/api/v0.1/countries/capital",
137
+ // "method": "GET",
138
+ // "headers": {
139
+ // "Content-Type": "application/json"
140
+ // },
141
+ // "responseType": "application/json"
142
+ // }).then((response) => {
143
+ // console.log(response);
144
+ // }).catch((error) => {
145
+ // console.error("ERROR", error);
146
+ // });
package/src/Nodes.ts ADDED
@@ -0,0 +1,12 @@
1
+ import ApiCall from "@blokjs/api-call";
2
+ import IfElse from "@blokjs/if-else";
3
+ import type { NodeBase } from "@blokjs/shared";
4
+
5
+ const nodes: {
6
+ [key: string]: NodeBase;
7
+ } = {
8
+ "@blokjs/api-call": ApiCall,
9
+ "@blokjs/if-else": IfElse,
10
+ };
11
+
12
+ export default nodes;
@@ -0,0 +1,5 @@
1
+ import type Workflows from "./types/Workflows";
2
+
3
+ const workflows: Workflows = {};
4
+
5
+ export default workflows;
@@ -0,0 +1,142 @@
1
+ // @generated by protoc-gen-es v2.2.3 with parameter "target=ts"
2
+ // @generated from file workflow.proto (package blok.workflow.v1, syntax proto3)
3
+ /* eslint-disable */
4
+
5
+ import type { Message } from "@bufbuild/protobuf";
6
+ import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1";
7
+ import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1";
8
+
9
+ /**
10
+ * Describes the file workflow.proto.
11
+ */
12
+ export const file_workflow: GenFile =
13
+ /*@__PURE__*/
14
+ fileDesc(
15
+ "Cg53b3JrZmxvdy5wcm90bxIXbmFub3NlcnZpY2Uud29ya2Zsb3cudjEiUAoPV29ya2Zsb3dSZXF1ZXN0EgwKBE5hbWUYASABKAkSDwoHTWVzc2FnZRgCIAEoCRIQCghFbmNvZGluZxgDIAEoCRIMCgRUeXBlGAQgASgJIkMKEFdvcmtmbG93UmVzcG9uc2USDwoHTWVzc2FnZRgBIAEoCRIQCghFbmNvZGluZxgCIAEoCRIMCgRUeXBlGAMgASgJKikKD01lc3NhZ2VFbmNvZGluZxIKCgZCQVNFNjQQABIKCgZTVFJJTkcQASpACgtNZXNzYWdlVHlwZRIICgRURVhUEAASCAoESlNPThABEgcKA1hNTBACEggKBEhUTUwQAxIKCgZCSU5BUlkQBDJ7Cg9Xb3JrZmxvd1NlcnZpY2USaAoPRXhlY3V0ZVdvcmtmbG93EigubmFub3NlcnZpY2Uud29ya2Zsb3cudjEuV29ya2Zsb3dSZXF1ZXN0GikubmFub3NlcnZpY2Uud29ya2Zsb3cudjEuV29ya2Zsb3dSZXNwb25zZSIAYgZwcm90bzM",
16
+ );
17
+
18
+ /**
19
+ * @generated from message blok.workflow.v1.WorkflowRequest
20
+ */
21
+ export type WorkflowRequest = Message<"blok.workflow.v1.WorkflowRequest"> & {
22
+ /**
23
+ * @generated from field: string Name = 1;
24
+ */
25
+ Name: string;
26
+
27
+ /**
28
+ * @generated from field: string Message = 2;
29
+ */
30
+ Message: string;
31
+
32
+ /**
33
+ * @generated from field: string Encoding = 3;
34
+ */
35
+ Encoding: string;
36
+
37
+ /**
38
+ * @generated from field: string Type = 4;
39
+ */
40
+ Type: string;
41
+ };
42
+
43
+ /**
44
+ * Describes the message blok.workflow.v1.WorkflowRequest.
45
+ * Use `create(WorkflowRequestSchema)` to create a new message.
46
+ */
47
+ export const WorkflowRequestSchema: GenMessage<WorkflowRequest> = /*@__PURE__*/ messageDesc(file_workflow, 0);
48
+
49
+ /**
50
+ * @generated from message blok.workflow.v1.WorkflowResponse
51
+ */
52
+ export type WorkflowResponse = Message<"blok.workflow.v1.WorkflowResponse"> & {
53
+ /**
54
+ * @generated from field: string Message = 1;
55
+ */
56
+ Message: string;
57
+
58
+ /**
59
+ * @generated from field: string Encoding = 2;
60
+ */
61
+ Encoding: string;
62
+
63
+ /**
64
+ * @generated from field: string Type = 3;
65
+ */
66
+ Type: string;
67
+ };
68
+
69
+ /**
70
+ * Describes the message blok.workflow.v1.WorkflowResponse.
71
+ * Use `create(WorkflowResponseSchema)` to create a new message.
72
+ */
73
+ export const WorkflowResponseSchema: GenMessage<WorkflowResponse> = /*@__PURE__*/ messageDesc(file_workflow, 1);
74
+
75
+ /**
76
+ * @generated from enum blok.workflow.v1.MessageEncoding
77
+ */
78
+ export enum MessageEncoding {
79
+ /**
80
+ * @generated from enum value: BASE64 = 0;
81
+ */
82
+ BASE64 = 0,
83
+
84
+ /**
85
+ * @generated from enum value: STRING = 1;
86
+ */
87
+ STRING = 1,
88
+ }
89
+
90
+ /**
91
+ * Describes the enum blok.workflow.v1.MessageEncoding.
92
+ */
93
+ export const MessageEncodingSchema: GenEnum<MessageEncoding> = /*@__PURE__*/ enumDesc(file_workflow, 0);
94
+
95
+ /**
96
+ * @generated from enum blok.workflow.v1.MessageType
97
+ */
98
+ export enum MessageType {
99
+ /**
100
+ * @generated from enum value: TEXT = 0;
101
+ */
102
+ TEXT = 0,
103
+
104
+ /**
105
+ * @generated from enum value: JSON = 1;
106
+ */
107
+ JSON = 1,
108
+
109
+ /**
110
+ * @generated from enum value: XML = 2;
111
+ */
112
+ XML = 2,
113
+
114
+ /**
115
+ * @generated from enum value: HTML = 3;
116
+ */
117
+ HTML = 3,
118
+
119
+ /**
120
+ * @generated from enum value: BINARY = 4;
121
+ */
122
+ BINARY = 4,
123
+ }
124
+
125
+ /**
126
+ * Describes the enum blok.workflow.v1.MessageType.
127
+ */
128
+ export const MessageTypeSchema: GenEnum<MessageType> = /*@__PURE__*/ enumDesc(file_workflow, 1);
129
+
130
+ /**
131
+ * @generated from service blok.workflow.v1.WorkflowService
132
+ */
133
+ export const WorkflowService: GenService<{
134
+ /**
135
+ * @generated from rpc blok.workflow.v1.WorkflowService.ExecuteWorkflow
136
+ */
137
+ executeWorkflow: {
138
+ methodKind: "unary";
139
+ input: typeof WorkflowRequestSchema;
140
+ output: typeof WorkflowResponseSchema;
141
+ };
142
+ }> = /*@__PURE__*/ serviceDesc(file_workflow, 0);
package/src/index.ts ADDED
@@ -0,0 +1,22 @@
1
+ import GrpcClient from "./GrpcClient";
2
+ import { RpcOptions } from "./GrpcClient";
3
+ import { CallOptions } from "./GrpcClient";
4
+ import { TransportEnum } from "./GrpcClient";
5
+ import { HttpVersionEnum } from "./GrpcClient";
6
+ import GrpcServer from "./GrpcServer";
7
+ import { GrpcServerOptions } from "./GrpcServer";
8
+ import NanoSDK from "./NanoSDK";
9
+ import { WorkflowRequest, WorkflowResponse } from "./gen/workflow_pb";
10
+
11
+ export {
12
+ GrpcClient,
13
+ RpcOptions,
14
+ CallOptions,
15
+ TransportEnum,
16
+ HttpVersionEnum,
17
+ WorkflowRequest,
18
+ WorkflowResponse,
19
+ GrpcServer,
20
+ GrpcServerOptions,
21
+ NanoSDK,
22
+ };
@@ -0,0 +1,26 @@
1
+ import { DefaultLogger } from "@blokjs/runner";
2
+ import { metrics } from "@opentelemetry/api";
3
+ import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
4
+ import { Resource } from "@opentelemetry/resources";
5
+ import { MeterProvider } from "@opentelemetry/sdk-metrics";
6
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
7
+
8
+ // Set up the Prometheus exporter to expose metrics at /metrics on port 9091
9
+ const prometheusExporter = new PrometheusExporter({ port: 9091, endpoint: "/metrics" }, () =>
10
+ new DefaultLogger().log("Prometheus scrape endpoint: http://localhost:9091/metrics"),
11
+ );
12
+
13
+ const resource = Resource.default().merge(
14
+ new Resource({
15
+ [ATTR_SERVICE_NAME]: "trigger-http",
16
+ [ATTR_SERVICE_VERSION]: "0.0.8",
17
+ }),
18
+ );
19
+
20
+ // Creates MeterProvider and installs the exporter as a MetricReader
21
+ const meterProvider = new MeterProvider({
22
+ resource: resource,
23
+ });
24
+ meterProvider.addMetricReader(prometheusExporter);
25
+
26
+ metrics.setGlobalMeterProvider(meterProvider);
package/src/server.ts ADDED
@@ -0,0 +1,8 @@
1
+ import GrpcServer from "./GrpcServer";
2
+
3
+ const server = new GrpcServer({
4
+ host: "0.0.0.0",
5
+ port: 8443,
6
+ });
7
+
8
+ server.start();
File without changes
@@ -0,0 +1,7 @@
1
+ import type { ParamsDictionary } from "@blokjs/runner";
2
+
3
+ type RuntimeWorkflow = {
4
+ workflow: ParamsDictionary;
5
+ };
6
+
7
+ export default RuntimeWorkflow;
@@ -0,0 +1,7 @@
1
+ import type { HelperResponse } from "@blokjs/helper";
2
+
3
+ type Workflows = {
4
+ [key: string]: HelperResponse;
5
+ };
6
+
7
+ export default Workflows;
package/tsconfig.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "ts-node": {
3
+ "transpileOnly": true
4
+ },
5
+ "compilerOptions": {
6
+ "target": "ES2022",
7
+ "module": "es2022",
8
+ "moduleResolution": "bundler",
9
+ "rootDir": "./src",
10
+ "baseUrl": ".",
11
+ "paths": {
12
+ "@nodes/*": ["./src/nodes/*"],
13
+ "@src/*": ["src/*"]
14
+ },
15
+ "allowJs": true,
16
+ "declaration": true,
17
+ "sourceMap": true,
18
+ "outDir": "./dist",
19
+ "esModuleInterop": true,
20
+ "forceConsistentCasingInFileNames": true,
21
+ "strict": true,
22
+ "noUnusedLocals": true,
23
+ "noImplicitReturns": true,
24
+ "skipLibCheck": true
25
+ },
26
+ "compileOnSave": true,
27
+ "include": [
28
+ "./src",
29
+ "./src/nodes/**/*.json",
30
+ "./src/nodes/**/*.md",
31
+ "./src/*.json"
32
+ ],
33
+ "exclude": ["src/nodes/**/test/*.ts", "node_modules"]
34
+ }
@@ -0,0 +1,29 @@
1
+ import path from "node:path";
2
+ import { defineConfig } from "vitest/config";
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ globals: true,
7
+ environment: "node",
8
+ coverage: {
9
+ provider: "istanbul",
10
+ reporter: ["text", "json", "html", "lcov"],
11
+ exclude: ["node_modules/", "dist/", "**/*.d.ts", "**/*.config.ts", "__tests__/", "src/gen/", "src/types/"],
12
+ thresholds: {
13
+ lines: 90,
14
+ functions: 90,
15
+ branches: 85,
16
+ statements: 90,
17
+ },
18
+ },
19
+ include: ["__tests__/**/*.test.ts"],
20
+ exclude: ["node_modules", "dist"],
21
+ testTimeout: 10000,
22
+ hookTimeout: 10000,
23
+ },
24
+ resolve: {
25
+ alias: {
26
+ "@": path.resolve(__dirname, "./src"),
27
+ },
28
+ },
29
+ });
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "World Countries",
3
+ "description": "Workflow description",
4
+ "version": "1.0.0",
5
+ "trigger": {
6
+ "http": {
7
+ "method": "GET",
8
+ "path": "/",
9
+ "accept": "application/json"
10
+ }
11
+ },
12
+ "steps": [
13
+ {
14
+ "name": "get-countries-api",
15
+ "node": "@blokjs/api-call",
16
+ "type": "module"
17
+ }
18
+ ],
19
+ "nodes": {
20
+ "get-countries-api": {
21
+ "inputs": {
22
+ "url": "https://countriesnow.space/api/v0.1/countries/capital",
23
+ "method": "GET",
24
+ "headers": {
25
+ "Content-Type": "application/json"
26
+ },
27
+ "responseType": "application/json"
28
+ }
29
+ }
30
+ }
31
+ }