@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.
- package/.eslintrc.json +36 -0
- package/.prettierrc.json +6 -0
- package/README.md +4 -0
- package/dist/hatchet/clients/admin/admin-client.d.ts +14 -0
- package/dist/hatchet/clients/admin/admin-client.js +50 -0
- package/dist/hatchet/clients/admin/admin-client.test.d.ts +1 -0
- package/dist/hatchet/clients/admin/admin-client.test.js +101 -0
- package/dist/hatchet/clients/dispatcher/action-listener.d.ts +24 -0
- package/dist/hatchet/clients/dispatcher/action-listener.js +113 -0
- package/dist/hatchet/clients/dispatcher/action-listener.test.d.ts +4 -0
- package/dist/hatchet/clients/dispatcher/action-listener.test.js +277 -0
- package/dist/hatchet/clients/dispatcher/dispatcher-client.d.ts +17 -0
- package/dist/hatchet/clients/dispatcher/dispatcher-client.js +46 -0
- package/dist/hatchet/clients/dispatcher/dispatcher-client.test.d.ts +1 -0
- package/dist/hatchet/clients/dispatcher/dispatcher-client.test.js +99 -0
- package/dist/hatchet/clients/event/event-client.d.ts +9 -0
- package/dist/hatchet/clients/event/event-client.js +28 -0
- package/dist/hatchet/clients/event/event-client.test.d.ts +1 -0
- package/dist/hatchet/clients/event/event-client.test.js +60 -0
- package/dist/hatchet/clients/hatchet-client/client-config.d.ts +72 -0
- package/dist/hatchet/clients/hatchet-client/client-config.js +17 -0
- package/dist/hatchet/clients/hatchet-client/hatchet-client.d.ts +26 -0
- package/dist/hatchet/clients/hatchet-client/hatchet-client.js +133 -0
- package/dist/hatchet/clients/hatchet-client/hatchet-client.test.d.ts +2 -0
- package/dist/hatchet/clients/hatchet-client/hatchet-client.test.js +135 -0
- package/dist/hatchet/clients/hatchet-client/index.d.ts +2 -0
- package/dist/hatchet/clients/hatchet-client/index.js +18 -0
- package/dist/hatchet/clients/worker/index.d.ts +1 -0
- package/dist/hatchet/clients/worker/index.js +17 -0
- package/dist/hatchet/clients/worker/worker.d.ts +31 -0
- package/dist/hatchet/clients/worker/worker.js +228 -0
- package/dist/hatchet/clients/worker/worker.test.d.ts +1 -0
- package/dist/hatchet/clients/worker/worker.test.js +256 -0
- package/dist/hatchet/index.d.ts +2 -0
- package/dist/hatchet/index.js +4 -0
- package/dist/hatchet/sdk.d.ts +2 -0
- package/dist/hatchet/sdk.js +4 -0
- package/dist/hatchet/step.d.ts +30 -0
- package/dist/hatchet/step.js +63 -0
- package/dist/hatchet/util/config-loader/config-loader.d.ts +13 -0
- package/dist/hatchet/util/config-loader/config-loader.js +85 -0
- package/dist/hatchet/util/config-loader/config-loader.test.d.ts +1 -0
- package/dist/hatchet/util/config-loader/config-loader.test.js +72 -0
- package/dist/hatchet/util/config-loader/index.d.ts +1 -0
- package/dist/hatchet/util/config-loader/index.js +17 -0
- package/dist/hatchet/util/errors/hatchet-error.d.ts +4 -0
- package/dist/hatchet/util/errors/hatchet-error.js +9 -0
- package/dist/hatchet/util/hatchet-promise/hatchet-promise.d.ts +6 -0
- package/dist/hatchet/util/hatchet-promise/hatchet-promise.js +12 -0
- package/dist/hatchet/util/hatchet-promise/hatchet-promise.test.d.ts +1 -0
- package/dist/hatchet/util/hatchet-promise/hatchet-promise.test.js +40 -0
- package/dist/hatchet/util/logger/index.d.ts +1 -0
- package/dist/hatchet/util/logger/index.js +17 -0
- package/dist/hatchet/util/logger/logger.d.ts +12 -0
- package/dist/hatchet/util/logger/logger.js +37 -0
- package/dist/hatchet/util/sleep.d.ts +2 -0
- package/dist/hatchet/util/sleep.js +6 -0
- package/dist/hatchet/workflow.d.ts +78 -0
- package/dist/hatchet/workflow.js +44 -0
- package/dist/protoc/dispatcher/dispatcher.d.ts +273 -0
- package/dist/protoc/dispatcher/dispatcher.js +918 -0
- package/dist/protoc/dispatcher/index.d.ts +1 -0
- package/dist/protoc/dispatcher/index.js +17 -0
- package/dist/protoc/events/events.d.ts +165 -0
- package/dist/protoc/events/events.js +443 -0
- package/dist/protoc/google/protobuf/timestamp.d.ts +121 -0
- package/dist/protoc/google/protobuf/timestamp.js +110 -0
- package/dist/protoc/google/protobuf/wrappers.d.ts +160 -0
- package/dist/protoc/google/protobuf/wrappers.js +527 -0
- package/dist/protoc/workflows/index.d.ts +1 -0
- package/dist/protoc/workflows/index.js +17 -0
- package/dist/protoc/workflows/workflows.d.ts +438 -0
- package/dist/protoc/workflows/workflows.js +1814 -0
- package/examples/dag-worker.ts +55 -0
- package/examples/example-event.ts +7 -0
- package/examples/simple-worker.ts +39 -0
- package/generate-protoc.sh +10 -0
- package/hatchet/clients/admin/admin-client.test.ts +116 -0
- package/hatchet/clients/admin/admin-client.ts +43 -0
- package/hatchet/clients/dispatcher/action-listener.test.ts +270 -0
- package/hatchet/clients/dispatcher/action-listener.ts +91 -0
- package/hatchet/clients/dispatcher/dispatcher-client.test.ts +111 -0
- package/hatchet/clients/dispatcher/dispatcher-client.ts +47 -0
- package/hatchet/clients/event/event-client.test.ts +72 -0
- package/hatchet/clients/event/event-client.ts +32 -0
- package/hatchet/clients/hatchet-client/client-config.ts +22 -0
- package/hatchet/clients/hatchet-client/fixtures/.hatchet-invalid.yaml +6 -0
- package/hatchet/clients/hatchet-client/fixtures/.hatchet.yaml +8 -0
- package/hatchet/clients/hatchet-client/hatchet-client.test.ts +162 -0
- package/hatchet/clients/hatchet-client/hatchet-client.ts +136 -0
- package/hatchet/clients/hatchet-client/index.ts +2 -0
- package/hatchet/clients/worker/index.ts +1 -0
- package/hatchet/clients/worker/worker.test.ts +347 -0
- package/hatchet/clients/worker/worker.ts +229 -0
- package/hatchet/index.ts +3 -0
- package/hatchet/sdk.ts +3 -0
- package/hatchet/step.ts +48 -0
- package/hatchet/util/config-loader/config-loader.test.ts +79 -0
- package/hatchet/util/config-loader/config-loader.ts +91 -0
- package/hatchet/util/config-loader/fixtures/.hatchet-invalid.yaml +6 -0
- package/hatchet/util/config-loader/fixtures/.hatchet.yaml +8 -0
- package/hatchet/util/config-loader/index.ts +1 -0
- package/hatchet/util/errors/hatchet-error.ts +8 -0
- package/hatchet/util/hatchet-promise/hatchet-promise.test.ts +32 -0
- package/hatchet/util/hatchet-promise/hatchet-promise.ts +13 -0
- package/hatchet/util/logger/index.ts +1 -0
- package/hatchet/util/logger/logger.ts +44 -0
- package/hatchet/util/sleep.ts +6 -0
- package/hatchet/workflow.ts +30 -0
- package/jest.config.ts +205 -0
- package/package.json +65 -0
- package/protoc/dispatcher/dispatcher.ts +1101 -0
- package/protoc/dispatcher/index.ts +1 -0
- package/protoc/events/events.ts +519 -0
- package/protoc/events/index.ts +1 -0
- package/protoc/google/protobuf/timestamp.ts +210 -0
- package/protoc/google/protobuf/wrappers.ts +657 -0
- package/protoc/workflows/index.ts +1 -0
- package/protoc/workflows/workflows.ts +2158 -0
- 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,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 @@
|
|
|
1
|
+
export * from './worker';
|