@hatchet-dev/typescript-sdk 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.
Files changed (120) hide show
  1. package/.eslintrc.json +36 -0
  2. package/.prettierrc.json +6 -0
  3. package/README.md +4 -0
  4. package/dist/hatchet/clients/admin/admin-client.d.ts +14 -0
  5. package/dist/hatchet/clients/admin/admin-client.js +50 -0
  6. package/dist/hatchet/clients/admin/admin-client.test.d.ts +1 -0
  7. package/dist/hatchet/clients/admin/admin-client.test.js +101 -0
  8. package/dist/hatchet/clients/dispatcher/action-listener.d.ts +24 -0
  9. package/dist/hatchet/clients/dispatcher/action-listener.js +113 -0
  10. package/dist/hatchet/clients/dispatcher/action-listener.test.d.ts +4 -0
  11. package/dist/hatchet/clients/dispatcher/action-listener.test.js +277 -0
  12. package/dist/hatchet/clients/dispatcher/dispatcher-client.d.ts +17 -0
  13. package/dist/hatchet/clients/dispatcher/dispatcher-client.js +46 -0
  14. package/dist/hatchet/clients/dispatcher/dispatcher-client.test.d.ts +1 -0
  15. package/dist/hatchet/clients/dispatcher/dispatcher-client.test.js +99 -0
  16. package/dist/hatchet/clients/event/event-client.d.ts +9 -0
  17. package/dist/hatchet/clients/event/event-client.js +28 -0
  18. package/dist/hatchet/clients/event/event-client.test.d.ts +1 -0
  19. package/dist/hatchet/clients/event/event-client.test.js +60 -0
  20. package/dist/hatchet/clients/hatchet-client/client-config.d.ts +72 -0
  21. package/dist/hatchet/clients/hatchet-client/client-config.js +17 -0
  22. package/dist/hatchet/clients/hatchet-client/hatchet-client.d.ts +26 -0
  23. package/dist/hatchet/clients/hatchet-client/hatchet-client.js +133 -0
  24. package/dist/hatchet/clients/hatchet-client/hatchet-client.test.d.ts +2 -0
  25. package/dist/hatchet/clients/hatchet-client/hatchet-client.test.js +135 -0
  26. package/dist/hatchet/clients/hatchet-client/index.d.ts +2 -0
  27. package/dist/hatchet/clients/hatchet-client/index.js +18 -0
  28. package/dist/hatchet/clients/worker/index.d.ts +1 -0
  29. package/dist/hatchet/clients/worker/index.js +17 -0
  30. package/dist/hatchet/clients/worker/worker.d.ts +31 -0
  31. package/dist/hatchet/clients/worker/worker.js +228 -0
  32. package/dist/hatchet/clients/worker/worker.test.d.ts +1 -0
  33. package/dist/hatchet/clients/worker/worker.test.js +256 -0
  34. package/dist/hatchet/index.d.ts +2 -0
  35. package/dist/hatchet/index.js +4 -0
  36. package/dist/hatchet/sdk.d.ts +2 -0
  37. package/dist/hatchet/sdk.js +4 -0
  38. package/dist/hatchet/step.d.ts +30 -0
  39. package/dist/hatchet/step.js +63 -0
  40. package/dist/hatchet/util/config-loader/config-loader.d.ts +13 -0
  41. package/dist/hatchet/util/config-loader/config-loader.js +85 -0
  42. package/dist/hatchet/util/config-loader/config-loader.test.d.ts +1 -0
  43. package/dist/hatchet/util/config-loader/config-loader.test.js +72 -0
  44. package/dist/hatchet/util/config-loader/index.d.ts +1 -0
  45. package/dist/hatchet/util/config-loader/index.js +17 -0
  46. package/dist/hatchet/util/errors/hatchet-error.d.ts +4 -0
  47. package/dist/hatchet/util/errors/hatchet-error.js +9 -0
  48. package/dist/hatchet/util/hatchet-promise/hatchet-promise.d.ts +6 -0
  49. package/dist/hatchet/util/hatchet-promise/hatchet-promise.js +12 -0
  50. package/dist/hatchet/util/hatchet-promise/hatchet-promise.test.d.ts +1 -0
  51. package/dist/hatchet/util/hatchet-promise/hatchet-promise.test.js +40 -0
  52. package/dist/hatchet/util/logger/index.d.ts +1 -0
  53. package/dist/hatchet/util/logger/index.js +17 -0
  54. package/dist/hatchet/util/logger/logger.d.ts +12 -0
  55. package/dist/hatchet/util/logger/logger.js +37 -0
  56. package/dist/hatchet/util/sleep.d.ts +2 -0
  57. package/dist/hatchet/util/sleep.js +6 -0
  58. package/dist/hatchet/workflow.d.ts +78 -0
  59. package/dist/hatchet/workflow.js +44 -0
  60. package/dist/protoc/dispatcher/dispatcher.d.ts +273 -0
  61. package/dist/protoc/dispatcher/dispatcher.js +918 -0
  62. package/dist/protoc/dispatcher/index.d.ts +1 -0
  63. package/dist/protoc/dispatcher/index.js +17 -0
  64. package/dist/protoc/events/events.d.ts +165 -0
  65. package/dist/protoc/events/events.js +443 -0
  66. package/dist/protoc/google/protobuf/timestamp.d.ts +121 -0
  67. package/dist/protoc/google/protobuf/timestamp.js +110 -0
  68. package/dist/protoc/google/protobuf/wrappers.d.ts +160 -0
  69. package/dist/protoc/google/protobuf/wrappers.js +527 -0
  70. package/dist/protoc/workflows/index.d.ts +1 -0
  71. package/dist/protoc/workflows/index.js +17 -0
  72. package/dist/protoc/workflows/workflows.d.ts +438 -0
  73. package/dist/protoc/workflows/workflows.js +1814 -0
  74. package/examples/dag-worker.ts +55 -0
  75. package/examples/example-event.ts +7 -0
  76. package/examples/simple-worker.ts +39 -0
  77. package/generate-protoc.sh +10 -0
  78. package/hatchet/clients/admin/admin-client.test.ts +116 -0
  79. package/hatchet/clients/admin/admin-client.ts +43 -0
  80. package/hatchet/clients/dispatcher/action-listener.test.ts +270 -0
  81. package/hatchet/clients/dispatcher/action-listener.ts +91 -0
  82. package/hatchet/clients/dispatcher/dispatcher-client.test.ts +111 -0
  83. package/hatchet/clients/dispatcher/dispatcher-client.ts +47 -0
  84. package/hatchet/clients/event/event-client.test.ts +72 -0
  85. package/hatchet/clients/event/event-client.ts +32 -0
  86. package/hatchet/clients/hatchet-client/client-config.ts +22 -0
  87. package/hatchet/clients/hatchet-client/fixtures/.hatchet-invalid.yaml +6 -0
  88. package/hatchet/clients/hatchet-client/fixtures/.hatchet.yaml +8 -0
  89. package/hatchet/clients/hatchet-client/hatchet-client.test.ts +162 -0
  90. package/hatchet/clients/hatchet-client/hatchet-client.ts +136 -0
  91. package/hatchet/clients/hatchet-client/index.ts +2 -0
  92. package/hatchet/clients/worker/index.ts +1 -0
  93. package/hatchet/clients/worker/worker.test.ts +347 -0
  94. package/hatchet/clients/worker/worker.ts +229 -0
  95. package/hatchet/index.ts +3 -0
  96. package/hatchet/sdk.ts +3 -0
  97. package/hatchet/step.ts +48 -0
  98. package/hatchet/util/config-loader/config-loader.test.ts +79 -0
  99. package/hatchet/util/config-loader/config-loader.ts +91 -0
  100. package/hatchet/util/config-loader/fixtures/.hatchet-invalid.yaml +6 -0
  101. package/hatchet/util/config-loader/fixtures/.hatchet.yaml +8 -0
  102. package/hatchet/util/config-loader/index.ts +1 -0
  103. package/hatchet/util/errors/hatchet-error.ts +8 -0
  104. package/hatchet/util/hatchet-promise/hatchet-promise.test.ts +32 -0
  105. package/hatchet/util/hatchet-promise/hatchet-promise.ts +13 -0
  106. package/hatchet/util/logger/index.ts +1 -0
  107. package/hatchet/util/logger/logger.ts +44 -0
  108. package/hatchet/util/sleep.ts +6 -0
  109. package/hatchet/workflow.ts +30 -0
  110. package/jest.config.ts +205 -0
  111. package/package.json +65 -0
  112. package/protoc/dispatcher/dispatcher.ts +1101 -0
  113. package/protoc/dispatcher/index.ts +1 -0
  114. package/protoc/events/events.ts +519 -0
  115. package/protoc/events/index.ts +1 -0
  116. package/protoc/google/protobuf/timestamp.ts +210 -0
  117. package/protoc/google/protobuf/wrappers.ts +657 -0
  118. package/protoc/workflows/index.ts +1 -0
  119. package/protoc/workflows/workflows.ts +2158 -0
  120. package/tsconfig.json +120 -0
@@ -0,0 +1,111 @@
1
+ import { ActionEventType } from '@protoc/dispatcher';
2
+ import { DispatcherClient } from './dispatcher-client';
3
+ import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test';
4
+
5
+ let client: DispatcherClient;
6
+
7
+ describe('DispatcherClient', () => {
8
+ it('should create a client', () => {
9
+ const x = new DispatcherClient(
10
+ {
11
+ token: 'TOKEN',
12
+
13
+ host_port: 'HOST_PORT',
14
+ log_level: 'OFF',
15
+ tls_config: {
16
+ cert_file: 'TLS_CERT_FILE',
17
+ key_file: 'TLS_KEY_FILE',
18
+ ca_file: 'TLS_ROOT_CA_FILE',
19
+ server_name: 'TLS_SERVER_NAME',
20
+ },
21
+ },
22
+ mockChannel,
23
+ mockFactory
24
+ );
25
+
26
+ expect(x).toBeDefined();
27
+ });
28
+
29
+ beforeEach(() => {
30
+ client = new DispatcherClient(
31
+ {
32
+ token: 'TOKEN',
33
+
34
+ host_port: 'HOST_PORT',
35
+ log_level: 'OFF',
36
+ tls_config: {
37
+ cert_file: 'TLS_CERT_FILE',
38
+ key_file: 'TLS_KEY_FILE',
39
+ ca_file: 'TLS_ROOT_CA_FILE',
40
+ server_name: 'TLS_SERVER_NAME',
41
+ },
42
+ },
43
+ mockChannel,
44
+ mockFactory
45
+ );
46
+ });
47
+
48
+ describe('get_action_listener', () => {
49
+ it('should register the worker', async () => {
50
+ const clientSpy = jest.spyOn(client.client, 'register').mockResolvedValue({
51
+ workerId: 'WORKER_ID',
52
+ tenantId: 'TENANT_ID',
53
+ workerName: 'WORKER_NAME',
54
+ });
55
+
56
+ const listenerSpy = jest.spyOn(client.client, 'listen');
57
+
58
+ const listener = await client.get_action_listener({
59
+ workerName: 'WORKER_NAME',
60
+ services: ['SERVICE'],
61
+ actions: ['ACTION'],
62
+ });
63
+
64
+ expect(clientSpy).toHaveBeenCalledWith({
65
+ workerName: 'WORKER_NAME',
66
+ services: ['SERVICE'],
67
+ actions: ['ACTION'],
68
+ });
69
+
70
+ expect(listenerSpy).toHaveBeenCalledWith({
71
+ workerId: 'WORKER_ID',
72
+ });
73
+
74
+ expect(listener).toBeDefined();
75
+ expect(listener.workerId).toEqual('WORKER_ID');
76
+ });
77
+ });
78
+
79
+ describe('send_action_event', () => {
80
+ it('should send action events', () => {
81
+ const clientSpy = jest.spyOn(client.client, 'sendActionEvent').mockResolvedValue({
82
+ tenantId: 'TENANT_ID',
83
+ workerId: 'WORKER_ID',
84
+ });
85
+
86
+ client.send_action_event({
87
+ workerId: 'WORKER_ID',
88
+ actionId: 'ACTION_ID',
89
+ eventType: ActionEventType.STEP_EVENT_TYPE_COMPLETED,
90
+ eventPayload: '{"foo":"bar"}',
91
+ eventTimestamp: new Date(),
92
+ jobId: 'a',
93
+ jobRunId: 'b',
94
+ stepId: 'c',
95
+ stepRunId: 'd',
96
+ });
97
+
98
+ expect(clientSpy).toHaveBeenCalledWith({
99
+ workerId: 'WORKER_ID',
100
+ actionId: 'ACTION_ID',
101
+ eventType: ActionEventType.STEP_EVENT_TYPE_COMPLETED,
102
+ eventPayload: '{"foo":"bar"}',
103
+ jobId: 'a',
104
+ jobRunId: 'b',
105
+ stepId: 'c',
106
+ stepRunId: 'd',
107
+ eventTimestamp: expect.any(Object),
108
+ });
109
+ });
110
+ });
111
+ });
@@ -0,0 +1,47 @@
1
+ import { Channel, ClientFactory } from 'nice-grpc';
2
+ import {
3
+ DispatcherClient as PbDispatcherClient,
4
+ DispatcherDefinition,
5
+ ActionEvent,
6
+ } from '@protoc/dispatcher';
7
+ import { ClientConfig } from '@clients/hatchet-client/client-config';
8
+ import HatchetError from '@util/errors/hatchet-error';
9
+ import { ActionListener } from './action-listener';
10
+
11
+ interface GetActionListenerOptions {
12
+ workerName: string;
13
+ services: string[];
14
+ actions: string[];
15
+ }
16
+
17
+ export class DispatcherClient {
18
+ config: ClientConfig;
19
+ client: PbDispatcherClient;
20
+
21
+ constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) {
22
+ this.config = config;
23
+ this.client = factory.create(DispatcherDefinition, channel);
24
+ }
25
+
26
+ async get_action_listener(options: GetActionListenerOptions) {
27
+ // Register the worker
28
+ const registration = await this.client.register({
29
+ ...options,
30
+ });
31
+
32
+ // Subscribe to the worker
33
+ const listener = this.client.listen({
34
+ workerId: registration.workerId,
35
+ });
36
+
37
+ return new ActionListener(this, listener, registration.workerId);
38
+ }
39
+
40
+ async send_action_event(in_: ActionEvent) {
41
+ try {
42
+ return this.client.sendActionEvent(in_);
43
+ } catch (e: any) {
44
+ throw new HatchetError(e.message);
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,72 @@
1
+ import HatchetError from '@util/errors/hatchet-error';
2
+ import { EventClient } from './event-client';
3
+ import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test';
4
+
5
+ let client: EventClient;
6
+
7
+ describe('EventClient', () => {
8
+ it('should create a client', () => {
9
+ const x = new EventClient(
10
+ {
11
+ token: 'TOKEN',
12
+ host_port: 'HOST_PORT',
13
+ tls_config: {
14
+ cert_file: 'TLS_CERT_FILE',
15
+ key_file: 'TLS_KEY_FILE',
16
+ ca_file: 'TLS_ROOT_CA_FILE',
17
+ server_name: 'TLS_SERVER_NAME',
18
+ },
19
+ },
20
+ mockChannel,
21
+ mockFactory
22
+ );
23
+
24
+ expect(x).toBeDefined();
25
+ });
26
+
27
+ beforeEach(() => {
28
+ client = new EventClient(
29
+ {
30
+ token: 'TOKEN',
31
+ host_port: 'HOST_PORT',
32
+ tls_config: {
33
+ cert_file: 'TLS_CERT_FILE',
34
+ key_file: 'TLS_KEY_FILE',
35
+ ca_file: 'TLS_ROOT_CA_FILE',
36
+ server_name: 'TLS_SERVER_NAME',
37
+ },
38
+ },
39
+ mockChannel,
40
+ mockFactory
41
+ );
42
+ });
43
+
44
+ it('should push events', () => {
45
+ const clientSpy = jest.spyOn(client.client, 'push').mockResolvedValue({
46
+ tenantId: 'x',
47
+ eventId: 'y',
48
+ key: 'z',
49
+ eventTimestamp: new Date(),
50
+ payload: 'string',
51
+ });
52
+
53
+ client.push('type', { foo: 'bar' });
54
+
55
+ expect(clientSpy).toHaveBeenCalledWith({
56
+ key: 'type',
57
+ payload: '{"foo":"bar"}',
58
+ eventTimestamp: expect.any(Date),
59
+ });
60
+ });
61
+
62
+ it('should throw an error when push fails', () => {
63
+ const clientSpy = jest.spyOn(client.client, 'push');
64
+ clientSpy.mockImplementation(() => {
65
+ throw new Error('foo');
66
+ });
67
+
68
+ expect(() => {
69
+ client.push('type', { foo: 'bar' });
70
+ }).toThrow(new HatchetError('foo'));
71
+ });
72
+ });
@@ -0,0 +1,32 @@
1
+ import { Channel, ClientFactory } from 'nice-grpc';
2
+ import {
3
+ EventsServiceClient,
4
+ EventsServiceDefinition,
5
+ PushEventRequest,
6
+ } from '@protoc/events/events';
7
+ import HatchetError from '@util/errors/hatchet-error';
8
+ import { ClientConfig } from '@clients/hatchet-client/client-config';
9
+
10
+ export class EventClient {
11
+ config: ClientConfig;
12
+ client: EventsServiceClient;
13
+
14
+ constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) {
15
+ this.config = config;
16
+ this.client = factory.create(EventsServiceDefinition, channel);
17
+ }
18
+
19
+ push<T>(type: string, input: T) {
20
+ const req: PushEventRequest = {
21
+ key: type,
22
+ payload: JSON.stringify(input),
23
+ eventTimestamp: new Date(),
24
+ };
25
+
26
+ try {
27
+ return this.client.push(req);
28
+ } catch (e: any) {
29
+ throw new HatchetError(e.message);
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,22 @@
1
+ import { ChannelCredentials } from 'nice-grpc';
2
+ import { z } from 'zod';
3
+
4
+ const ClientTLSConfigSchema = z.object({
5
+ tls_strategy: z.enum(['tls', 'mtls']).optional(),
6
+ cert_file: z.string().optional(),
7
+ ca_file: z.string().optional(),
8
+ key_file: z.string().optional(),
9
+ server_name: z.string().optional(),
10
+ });
11
+
12
+ export const ClientConfigSchema = z.object({
13
+ token: z.string(),
14
+ tls_config: ClientTLSConfigSchema,
15
+ host_port: z.string(),
16
+ log_level: z.enum(['OFF', 'DEBUG', 'INFO', 'WARN', 'ERROR']).optional(),
17
+ });
18
+
19
+ export type ClientConfig = z.infer<typeof ClientConfigSchema> & {
20
+ credentials?: ChannelCredentials;
21
+ };
22
+ export type ClientTLSConfig = z.infer<typeof ClientTLSConfigSchema>;
@@ -0,0 +1,6 @@
1
+ tenant_id: 'TENANT_ID_YAML'
2
+ host_port: 'HOST_PORT_YAML'
3
+ tls_config:
4
+ cert_file: 'TLS_CERT_FILE_YAML'
5
+ key_file: 'TLS_KEY_FILE_YAML'
6
+ ca_file: 'TLS_ROOT_CA_FILE_YAML'
@@ -0,0 +1,8 @@
1
+ token: 'TOKEN_YAML'
2
+ tenant_id: 'TENANT_ID_YAML'
3
+ host_port: 'HOST_PORT_YAML'
4
+ tls_config:
5
+ cert_file: 'TLS_CERT_FILE_YAML'
6
+ key_file: 'TLS_KEY_FILE_YAML'
7
+ ca_file: 'TLS_ROOT_CA_FILE_YAML'
8
+ server_name: 'TLS_SERVER_NAME_YAML'
@@ -0,0 +1,162 @@
1
+ import { ChannelCredentials, createChannel, createClientFactory } from 'nice-grpc';
2
+ import { HatchetClient } from './hatchet-client';
3
+
4
+ export const mockChannel = createChannel('localhost:50051');
5
+ export const mockFactory = createClientFactory();
6
+
7
+ describe('Client', () => {
8
+ beforeEach(() => {
9
+ process.env.HATCHET_CLIENT_TOKEN = 'TOKEN_ENV';
10
+ });
11
+
12
+ it('should load from environment variables', () => {
13
+ const hatchet = new HatchetClient(
14
+ {
15
+ token: 'TOKEN_ENV',
16
+ host_port: 'HOST_PORT',
17
+ log_level: 'OFF',
18
+ tls_config: {
19
+ cert_file: 'TLS_CERT_FILE',
20
+ key_file: 'TLS_KEY_FILE',
21
+ ca_file: 'TLS_ROOT_CA_FILE',
22
+ server_name: 'TLS_SERVER_NAME',
23
+ },
24
+ },
25
+ {
26
+ credentials: ChannelCredentials.createInsecure(),
27
+ }
28
+ );
29
+
30
+ expect(hatchet.config).toEqual({
31
+ token: 'TOKEN_ENV',
32
+ host_port: 'HOST_PORT',
33
+ log_level: 'OFF',
34
+ tls_config: {
35
+ tls_strategy: 'tls',
36
+ cert_file: 'TLS_CERT_FILE',
37
+ key_file: 'TLS_KEY_FILE',
38
+ ca_file: 'TLS_ROOT_CA_FILE',
39
+ server_name: 'TLS_SERVER_NAME',
40
+ },
41
+ });
42
+ });
43
+
44
+ it('should throw an error if the config param is invalid', () => {
45
+ expect(
46
+ () =>
47
+ new HatchetClient({
48
+ host_port: 'HOST_PORT',
49
+ tls_config: {
50
+ tls_strategy: 'tls',
51
+ cert_file: 'TLS_CERT_FILE',
52
+ key_file: 'TLS_KEY_FILE',
53
+ ca_file: 'TLS_ROOT_CA_FILE',
54
+ // @ts-ignore
55
+ server_name: undefined,
56
+ },
57
+ })
58
+ ).toThrow();
59
+ });
60
+
61
+ it('should favor config param over yaml over env vars ', () => {
62
+ const hatchet = new HatchetClient(
63
+ {
64
+ tls_config: {
65
+ cert_file: 'TLS_CERT_FILE',
66
+ key_file: 'TLS_KEY_FILE',
67
+ ca_file: 'TLS_ROOT_CA_FILE',
68
+ server_name: 'TLS_SERVER_NAME',
69
+ },
70
+ },
71
+ {
72
+ config_path: './fixtures/.hatchet.yaml',
73
+ credentials: ChannelCredentials.createInsecure(),
74
+ }
75
+ );
76
+
77
+ expect(hatchet.config).toEqual({
78
+ token: 'TOKEN_YAML',
79
+ host_port: 'HOST_PORT_YAML',
80
+ log_level: 'INFO',
81
+ tls_config: {
82
+ tls_strategy: 'tls',
83
+ cert_file: 'TLS_CERT_FILE',
84
+ key_file: 'TLS_KEY_FILE',
85
+ ca_file: 'TLS_ROOT_CA_FILE',
86
+ server_name: 'TLS_SERVER_NAME',
87
+ },
88
+ });
89
+ });
90
+
91
+ describe('with_host_port', () => {
92
+ it('should set the host_port', () => {
93
+ const hatchet = HatchetClient.with_host_port(
94
+ 'HOST',
95
+ 1234,
96
+ {
97
+ token: 'TOKEN',
98
+ tls_config: {
99
+ tls_strategy: 'tls',
100
+ cert_file: 'TLS_CERT_FILE',
101
+ key_file: 'TLS_KEY_FILE',
102
+ ca_file: 'TLS_ROOT_CA_FILE',
103
+ server_name: 'TLS_SERVER_NAME',
104
+ },
105
+ },
106
+ {
107
+ credentials: ChannelCredentials.createInsecure(),
108
+ }
109
+ );
110
+ expect(hatchet.config).toEqual({
111
+ token: 'TOKEN',
112
+ host_port: 'HOST:1234',
113
+ log_level: 'INFO',
114
+ tls_config: {
115
+ tls_strategy: 'tls',
116
+ cert_file: 'TLS_CERT_FILE',
117
+ key_file: 'TLS_KEY_FILE',
118
+ ca_file: 'TLS_ROOT_CA_FILE',
119
+ server_name: 'TLS_SERVER_NAME',
120
+ },
121
+ });
122
+ });
123
+ });
124
+
125
+ describe('Worker', () => {
126
+ let hatchet: HatchetClient;
127
+
128
+ beforeEach(() => {
129
+ hatchet = new HatchetClient(
130
+ {
131
+ token: 'TOKEN',
132
+ host_port: 'HOST_PORT',
133
+ log_level: 'OFF',
134
+ tls_config: {
135
+ cert_file: 'TLS_CERT_FILE',
136
+ key_file: 'TLS_KEY_FILE',
137
+ ca_file: 'TLS_ROOT_CA_FILE',
138
+ server_name: 'TLS_SERVER_NAME',
139
+ },
140
+ },
141
+ {
142
+ credentials: ChannelCredentials.createInsecure(),
143
+ }
144
+ );
145
+ });
146
+
147
+ describe('run', () => {
148
+ xit('should start a worker', () => {
149
+ const worker = hatchet.run('workflow1');
150
+ expect(worker).toBeDefined();
151
+ });
152
+ });
153
+
154
+ describe('worker', () => {
155
+ it('should start a worker', () => {
156
+ const worker = hatchet.worker('workflow1');
157
+
158
+ expect(worker).toBeDefined();
159
+ });
160
+ });
161
+ });
162
+ });
@@ -0,0 +1,136 @@
1
+ import { z } from 'zod';
2
+ import { ConfigLoader } from '@util/config-loader';
3
+ import { EventClient } from '@clients/event/event-client';
4
+ import { DispatcherClient } from '@clients/dispatcher/dispatcher-client';
5
+ import { AdminClient } from '@clients/admin/admin-client';
6
+ import {
7
+ CallOptions,
8
+ Channel,
9
+ ChannelCredentials,
10
+ ClientMiddlewareCall,
11
+ Metadata,
12
+ createChannel,
13
+ createClientFactory,
14
+ } from 'nice-grpc';
15
+ import { Workflow } from '@hatchet/workflow';
16
+ import { Worker } from '@clients/worker';
17
+ import Logger from '@hatchet/util/logger/logger';
18
+ import { ClientConfig, ClientConfigSchema } from './client-config';
19
+
20
+ export interface HatchetClientOptions {
21
+ config_path?: string;
22
+ credentials?: ChannelCredentials;
23
+ }
24
+
25
+ const addTokenMiddleware = (token: string) =>
26
+ async function* _<Request, Response>(
27
+ call: ClientMiddlewareCall<Request, Response>,
28
+ options: CallOptions
29
+ ) {
30
+ const optionsWithAuth: CallOptions = {
31
+ ...options,
32
+ metadata: new Metadata({ authorization: `bearer ${token}` }),
33
+ };
34
+
35
+ if (!call.responseStream) {
36
+ const response = yield* call.next(call.request, optionsWithAuth);
37
+
38
+ return response;
39
+ }
40
+
41
+ for await (const response of call.next(call.request, optionsWithAuth)) {
42
+ yield response;
43
+ }
44
+
45
+ return undefined;
46
+ };
47
+
48
+ export class HatchetClient {
49
+ config: ClientConfig;
50
+ credentials: ChannelCredentials;
51
+ channel: Channel;
52
+
53
+ event: EventClient;
54
+ dispatcher: DispatcherClient;
55
+ admin: AdminClient;
56
+
57
+ logger: Logger;
58
+
59
+ constructor(config?: Partial<ClientConfig>, options?: HatchetClientOptions) {
60
+ // Initializes a new Client instance.
61
+ // Loads config in the following order: config param > yaml file > env vars
62
+
63
+ const loaded = ConfigLoader.load_client_config({
64
+ path: options?.config_path,
65
+ });
66
+
67
+ try {
68
+ const valid = ClientConfigSchema.parse({
69
+ ...loaded,
70
+ ...{ ...config, tls_config: { ...loaded.tls_config, ...config?.tls_config } },
71
+ });
72
+ this.config = valid;
73
+ } catch (e) {
74
+ if (e instanceof z.ZodError) {
75
+ throw new Error(`Invalid client config: ${e.message}`);
76
+ }
77
+ throw e;
78
+ }
79
+
80
+ this.credentials =
81
+ options?.credentials ?? ConfigLoader.createCredentials(this.config.tls_config);
82
+
83
+ this.channel = createChannel(this.config.host_port, this.credentials, {
84
+ 'grpc.ssl_target_name_override': this.config.tls_config.server_name,
85
+ });
86
+
87
+ const clientFactory = createClientFactory().use(addTokenMiddleware(this.config.token));
88
+
89
+ this.event = new EventClient(this.config, this.channel, clientFactory);
90
+ this.dispatcher = new DispatcherClient(this.config, this.channel, clientFactory);
91
+ this.admin = new AdminClient(this.config, this.channel, clientFactory);
92
+
93
+ this.logger = new Logger('HatchetClient', this.config.log_level);
94
+
95
+ this.logger.info(`Initialized HatchetClient`);
96
+ }
97
+
98
+ static with_host_port(
99
+ host: string,
100
+ port: number,
101
+ config?: Partial<ClientConfig>,
102
+ options?: HatchetClientOptions
103
+ ): HatchetClient {
104
+ return new HatchetClient(
105
+ {
106
+ ...config,
107
+ host_port: `${host}:${port}`,
108
+ },
109
+ options
110
+ );
111
+ }
112
+
113
+ static init(config?: Partial<ClientConfig>, options?: HatchetClientOptions): HatchetClient {
114
+ return new HatchetClient(config, options);
115
+ }
116
+
117
+ async run(workflow: string | Workflow): Promise<Worker> {
118
+ const worker = await this.worker(workflow);
119
+ worker.start();
120
+ return worker;
121
+ }
122
+
123
+ async worker(workflow: string | Workflow): Promise<Worker> {
124
+ const name = typeof workflow === 'string' ? workflow : workflow.id;
125
+ const worker = new Worker(this, {
126
+ name,
127
+ });
128
+
129
+ if (typeof workflow !== 'string') {
130
+ await worker.register_workflow(workflow);
131
+ return worker;
132
+ }
133
+
134
+ return worker;
135
+ }
136
+ }
@@ -0,0 +1,2 @@
1
+ export * from './hatchet-client';
2
+ export * from './client-config';
@@ -0,0 +1 @@
1
+ export * from './worker';