diff --git a/frontend/docs/pages/typescript-sdk/setup.mdx b/frontend/docs/pages/typescript-sdk/setup.mdx index 5f3a1139b..d772bfaf4 100644 --- a/frontend/docs/pages/typescript-sdk/setup.mdx +++ b/frontend/docs/pages/typescript-sdk/setup.mdx @@ -22,13 +22,10 @@ yarn add @hatchet/node-sdk ## Usage -You should have generated a set of client certificates (or received them through Hatchet cloud). These certificates are `ca.cert`, `client-worker.pem`, and `client-worker.key`. You should also make note of the Hatchet server address and the tenant ID you'd like to connect to. +Navigate to `https://app.dev.hatchet-tools.com/tenant-settings` to generate an API Token and set the following environment variables. ```sh HATCHET_CLIENT_TENANT_ID= -HATCHET_CLIENT_TLS_ROOT_CA_FILE=./certs/ca.cert -HATCHET_CLIENT_TLS_CERT_FILE=./certs/client-worker.pem -HATCHET_CLIENT_TLS_KEY_FILE=./certs/client-worker.key -HATCHET_CLIENT_TLS_SERVER_NAME= -HATCHET_CLIENT_HOST_PORT=:443 +HATCHET_CLIENT_TOKEN= +HATCHET_CLIENT_HOST_PORT=: ``` diff --git a/typescript-sdk/hatchet/clients/admin/admin-client.test.ts b/typescript-sdk/hatchet/clients/admin/admin-client.test.ts index 77644b6ff..169813c47 100644 --- a/typescript-sdk/hatchet/clients/admin/admin-client.test.ts +++ b/typescript-sdk/hatchet/clients/admin/admin-client.test.ts @@ -1,6 +1,6 @@ import { CreateWorkflowVersionOpts, WorkflowVersion } from '@protoc/workflows'; import { AdminClient } from './admin-client'; -import { mockChannel } from '../hatchet-client/hatchet-client.test'; +import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test'; describe('AdminClient', () => { let client: AdminClient; @@ -18,7 +18,8 @@ describe('AdminClient', () => { server_name: 'TLS_SERVER_NAME', }, }, - mockChannel + mockChannel, + mockFactory ); expect(x).toBeDefined(); @@ -37,7 +38,8 @@ describe('AdminClient', () => { server_name: 'TLS_SERVER_NAME', }, }, - mockChannel + mockChannel, + mockFactory ); }); diff --git a/typescript-sdk/hatchet/clients/admin/admin-client.ts b/typescript-sdk/hatchet/clients/admin/admin-client.ts index 8f701aa9c..faa923c9a 100644 --- a/typescript-sdk/hatchet/clients/admin/admin-client.ts +++ b/typescript-sdk/hatchet/clients/admin/admin-client.ts @@ -1,4 +1,4 @@ -import { Channel, createClient } from 'nice-grpc'; +import { Channel, ClientFactory } from 'nice-grpc'; import { CreateWorkflowVersionOpts, WorkflowServiceClient, @@ -11,9 +11,9 @@ export class AdminClient { config: ClientConfig; client: WorkflowServiceClient; - constructor(config: ClientConfig, channel: Channel) { + constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) { this.config = config; - this.client = createClient(WorkflowServiceDefinition, channel); + this.client = factory.create(WorkflowServiceDefinition, channel); } async put_workflow(workflow: CreateWorkflowVersionOpts, options?: { autoVersion?: boolean }) { diff --git a/typescript-sdk/hatchet/clients/dispatcher/action-listener.test.ts b/typescript-sdk/hatchet/clients/dispatcher/action-listener.test.ts index 1ccdbddc1..dbe9c71a2 100644 --- a/typescript-sdk/hatchet/clients/dispatcher/action-listener.test.ts +++ b/typescript-sdk/hatchet/clients/dispatcher/action-listener.test.ts @@ -3,7 +3,7 @@ import sleep from '@util/sleep'; import { ServerError, Status } from 'nice-grpc-common'; import { DispatcherClient } from './dispatcher-client'; import { ActionListener } from './action-listener'; -import { mockChannel } from '../hatchet-client/hatchet-client.test'; +import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test'; let dispatcher: DispatcherClient; @@ -55,7 +55,8 @@ describe('ActionListener', () => { server_name: 'TLS_SERVER_NAME', }, }, - mockChannel + mockChannel, + mockFactory ); }); diff --git a/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.test.ts b/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.test.ts index 8bc2557e5..6a5a6474e 100644 --- a/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.test.ts +++ b/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.test.ts @@ -1,6 +1,6 @@ import { ActionEventType } from '@protoc/dispatcher'; import { DispatcherClient } from './dispatcher-client'; -import { mockChannel } from '../hatchet-client/hatchet-client.test'; +import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test'; let client: DispatcherClient; @@ -19,7 +19,8 @@ describe('DispatcherClient', () => { server_name: 'TLS_SERVER_NAME', }, }, - mockChannel + mockChannel, + mockFactory ); expect(x).toBeDefined(); @@ -39,7 +40,8 @@ describe('DispatcherClient', () => { server_name: 'TLS_SERVER_NAME', }, }, - mockChannel + mockChannel, + mockFactory ); }); diff --git a/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.ts b/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.ts index d0458f7e4..2f16fbb00 100644 --- a/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.ts +++ b/typescript-sdk/hatchet/clients/dispatcher/dispatcher-client.ts @@ -1,4 +1,4 @@ -import { Channel, createClient } from 'nice-grpc'; +import { Channel, ClientFactory } from 'nice-grpc'; import { DispatcherClient as PbDispatcherClient, DispatcherDefinition, @@ -18,9 +18,9 @@ export class DispatcherClient { config: ClientConfig; client: PbDispatcherClient; - constructor(config: ClientConfig, channel: Channel) { + constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) { this.config = config; - this.client = createClient(DispatcherDefinition, channel); + this.client = factory.create(DispatcherDefinition, channel); } async get_action_listener(options: GetActionListenerOptions) { diff --git a/typescript-sdk/hatchet/clients/event/event-client.test.ts b/typescript-sdk/hatchet/clients/event/event-client.test.ts index 951c3a439..ae3c2bb57 100644 --- a/typescript-sdk/hatchet/clients/event/event-client.test.ts +++ b/typescript-sdk/hatchet/clients/event/event-client.test.ts @@ -1,11 +1,9 @@ import HatchetError from '@util/errors/hatchet-error'; -import { createChannel } from 'nice-grpc'; import { EventClient } from './event-client'; +import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test'; let client: EventClient; -const mockChannel = createChannel('localhost:50051'); - describe('EventClient', () => { it('should create a client', () => { const x = new EventClient( @@ -20,7 +18,8 @@ describe('EventClient', () => { server_name: 'TLS_SERVER_NAME', }, }, - mockChannel + mockChannel, + mockFactory ); expect(x).toBeDefined(); @@ -39,7 +38,8 @@ describe('EventClient', () => { server_name: 'TLS_SERVER_NAME', }, }, - mockChannel + mockChannel, + mockFactory ); }); diff --git a/typescript-sdk/hatchet/clients/event/event-client.ts b/typescript-sdk/hatchet/clients/event/event-client.ts index 537d1ec0c..6add1bd85 100644 --- a/typescript-sdk/hatchet/clients/event/event-client.ts +++ b/typescript-sdk/hatchet/clients/event/event-client.ts @@ -1,4 +1,4 @@ -import { Channel, createClient } from 'nice-grpc'; +import { Channel, ClientFactory } from 'nice-grpc'; import { EventsServiceClient, EventsServiceDefinition, @@ -11,10 +11,9 @@ export class EventClient { config: ClientConfig; client: EventsServiceClient; - constructor(config: ClientConfig, channel: Channel) { + constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) { this.config = config; - - this.client = createClient(EventsServiceDefinition, channel); + this.client = factory.create(EventsServiceDefinition, channel); } push(type: string, input: T) { diff --git a/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.test.ts b/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.test.ts index 1f9d6997d..41dbb73a6 100644 --- a/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.test.ts +++ b/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.test.ts @@ -1,7 +1,8 @@ -import { ChannelCredentials, createChannel } from 'nice-grpc'; +import { ChannelCredentials, createChannel, createClientFactory } from 'nice-grpc'; import { HatchetClient } from './hatchet-client'; export const mockChannel = createChannel('localhost:50051'); +export const mockFactory = createClientFactory(); describe('Client', () => { beforeEach(() => { diff --git a/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.ts b/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.ts index 171ae5941..26064798a 100644 --- a/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.ts +++ b/typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.ts @@ -3,7 +3,15 @@ import { ConfigLoader } from '@util/config-loader'; import { EventClient } from '@clients/event/event-client'; import { DispatcherClient } from '@clients/dispatcher/dispatcher-client'; import { AdminClient } from '@clients/admin/admin-client'; -import { Channel, ChannelCredentials, createChannel } from 'nice-grpc'; +import { + CallOptions, + Channel, + ChannelCredentials, + ClientMiddlewareCall, + Metadata, + createChannel, + createClientFactory, +} from 'nice-grpc'; import { Workflow } from '@hatchet/workflow'; import { Worker } from '@clients/worker'; import Logger from '@hatchet/util/logger/logger'; @@ -14,6 +22,29 @@ export interface HatchetClientOptions { credentials?: ChannelCredentials; } +const addTokenMiddleware = (token: string) => + async function* _( + call: ClientMiddlewareCall, + options: CallOptions + ) { + const optionsWithAuth: CallOptions = { + ...options, + metadata: new Metadata({ authorization: `'Bearer ${token}` }), + }; + + if (!call.responseStream) { + const response = yield* call.next(call.request, optionsWithAuth); + + return response; + } + + for await (const response of call.next(call.request, optionsWithAuth)) { + yield response; + } + + return undefined; + }; + export class HatchetClient { config: ClientConfig; credentials: ChannelCredentials; @@ -48,13 +79,16 @@ export class HatchetClient { this.credentials = options?.credentials ?? ConfigLoader.createCredentials(this.config.tls_config); + this.channel = createChannel(this.config.host_port, this.credentials, { 'grpc.ssl_target_name_override': this.config.tls_config.server_name, }); - this.event = new EventClient(this.config, this.channel); - this.dispatcher = new DispatcherClient(this.config, this.channel); - this.admin = new AdminClient(this.config, this.channel); + const clientFactory = createClientFactory().use(addTokenMiddleware(this.config.token)); + + this.event = new EventClient(this.config, this.channel, clientFactory); + this.dispatcher = new DispatcherClient(this.config, this.channel, clientFactory); + this.admin = new AdminClient(this.config, this.channel, clientFactory); this.logger = new Logger('HatchetClient', this.config.log_level);