@hatchet-dev/typescript-sdk 0.9.0 → 0.10.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.
@@ -6,6 +6,26 @@ export interface APIMeta {
6
6
  */
7
7
  pylonAppId?: string;
8
8
  posthog?: APIMetaPosthog;
9
+ /**
10
+ * whether or not users can sign up for this instance
11
+ * @example true
12
+ */
13
+ allowSignup?: boolean;
14
+ /**
15
+ * whether or not users can invite other users to this instance
16
+ * @example true
17
+ */
18
+ allowInvites?: boolean;
19
+ /**
20
+ * whether or not users can create new tenants
21
+ * @example true
22
+ */
23
+ allowCreateTenant?: boolean;
24
+ /**
25
+ * whether or not users can change their password
26
+ * @example true
27
+ */
28
+ allowChangePassword?: boolean;
9
29
  }
10
30
  export interface APIMetaAuth {
11
31
  /**
@@ -283,6 +303,19 @@ export interface TenantInviteList {
283
303
  pagination?: PaginationResponse;
284
304
  rows?: TenantInvite[];
285
305
  }
306
+ export interface QueueMetrics {
307
+ /** The number of items in the queue. */
308
+ numQueued: number;
309
+ /** The number of items running. */
310
+ numRunning: number;
311
+ /** The number of items pending. */
312
+ numPending: number;
313
+ }
314
+ export interface TenantQueueMetrics {
315
+ /** The total queue metrics. */
316
+ total?: QueueMetrics;
317
+ workflow?: Record<string, QueueMetrics>;
318
+ }
286
319
  export interface AcceptInviteRequest {
287
320
  /**
288
321
  * @minLength 36
@@ -342,6 +375,14 @@ export interface EventData {
342
375
  /** The data for the event (JSON bytes). */
343
376
  data: string;
344
377
  }
378
+ export interface CreateEventRequest {
379
+ /** The key for the event. */
380
+ key: string;
381
+ /** The data for the event. */
382
+ data: object;
383
+ /** Additional metadata for the event. */
384
+ additionalMetadata?: object;
385
+ }
345
386
  export interface EventWorkflowRunSummary {
346
387
  /**
347
388
  * The number of pending runs.
@@ -404,7 +445,6 @@ export interface Workflow {
404
445
  lastRun?: WorkflowRun;
405
446
  /** The jobs of the workflow. */
406
447
  jobs?: Job[];
407
- deployment?: WorkflowDeploymentConfig;
408
448
  }
409
449
  export interface WorkflowConcurrency {
410
450
  /**
@@ -417,22 +457,6 @@ export interface WorkflowConcurrency {
417
457
  /** An action which gets the concurrency group for the WorkflowRun. */
418
458
  getConcurrencyGroup: string;
419
459
  }
420
- export interface WorkflowDeploymentConfig {
421
- metadata: APIResourceMeta;
422
- /** The repository name. */
423
- gitRepoName: string;
424
- /** The repository owner. */
425
- gitRepoOwner: string;
426
- /** The repository branch. */
427
- gitRepoBranch: string;
428
- /** The Github App installation. */
429
- githubAppInstallation?: GithubAppInstallation;
430
- /**
431
- * The id of the Github App installation.
432
- * @format uuid
433
- */
434
- githubAppInstallationId: string;
435
- }
436
460
  export interface WorkflowVersionMeta {
437
461
  metadata: APIResourceMeta;
438
462
  /** The version of the workflow. */
@@ -682,6 +706,33 @@ export interface StepRunEventList {
682
706
  pagination?: PaginationResponse;
683
707
  rows?: StepRunEvent[];
684
708
  }
709
+ export interface StepRunArchive {
710
+ stepRunId: string;
711
+ order: number;
712
+ input?: string;
713
+ output?: string;
714
+ /** @format date-time */
715
+ startedAt?: string;
716
+ error?: string;
717
+ /** @format date-time */
718
+ createdAt: string;
719
+ startedAtEpoch?: number;
720
+ /** @format date-time */
721
+ finishedAt?: string;
722
+ finishedAtEpoch?: number;
723
+ /** @format date-time */
724
+ timeoutAt?: string;
725
+ timeoutAtEpoch?: number;
726
+ /** @format date-time */
727
+ cancelledAt?: string;
728
+ cancelledAtEpoch?: number;
729
+ cancelledReason?: string;
730
+ cancelledError?: string;
731
+ }
732
+ export interface StepRunArchiveList {
733
+ pagination?: PaginationResponse;
734
+ rows?: StepRunArchive[];
735
+ }
685
736
  export interface WorkerList {
686
737
  pagination?: PaginationResponse;
687
738
  rows?: Worker[];
@@ -756,40 +807,6 @@ export interface TriggerWorkflowRunRequest {
756
807
  input: object;
757
808
  additionalMetadata?: object;
758
809
  }
759
- export interface LinkGithubRepositoryRequest {
760
- /**
761
- * The repository name.
762
- * @minLength 36
763
- * @maxLength 36
764
- */
765
- installationId: string;
766
- /** The repository name. */
767
- gitRepoName: string;
768
- /** The repository owner. */
769
- gitRepoOwner: string;
770
- /** The repository branch. */
771
- gitRepoBranch: string;
772
- }
773
- export interface GithubBranch {
774
- branch_name: string;
775
- is_default: boolean;
776
- }
777
- export interface GithubRepo {
778
- repo_owner: string;
779
- repo_name: string;
780
- }
781
- export interface GithubAppInstallation {
782
- metadata: APIResourceMeta;
783
- installation_settings_url: string;
784
- account_name: string;
785
- account_avatar_url: string;
786
- }
787
- export interface ListGithubAppInstallationsResponse {
788
- pagination: PaginationResponse;
789
- rows: GithubAppInstallation[];
790
- }
791
- export type ListGithubReposResponse = GithubRepo[];
792
- export type ListGithubBranchesResponse = GithubBranch[];
793
810
  export interface CreatePullRequestFromStepRun {
794
811
  branchName: string;
795
812
  }
@@ -894,3 +911,37 @@ export interface WorkflowMetrics {
894
911
  /** The total number of concurrency group keys. */
895
912
  groupKeyCount?: number;
896
913
  }
914
+ export interface WebhookWorker {
915
+ metadata: APIResourceMeta;
916
+ /** The name of the webhook worker. */
917
+ name: string;
918
+ /** The webhook url. */
919
+ url: string;
920
+ }
921
+ export interface WebhookWorkerCreated {
922
+ metadata: APIResourceMeta;
923
+ /** The name of the webhook worker. */
924
+ name: string;
925
+ /** The webhook url. */
926
+ url: string;
927
+ /** The secret key for validation. */
928
+ secret: string;
929
+ }
930
+ export interface WebhookWorkerCreateRequest {
931
+ /** The name of the webhook worker. */
932
+ name: string;
933
+ /** The webhook url. */
934
+ url: string;
935
+ /**
936
+ * The secret key for validation. If not provided, a random secret will be generated.
937
+ * @minLength 32
938
+ */
939
+ secret?: string;
940
+ }
941
+ export interface WebhookWorkerCreateResponse {
942
+ worker?: WebhookWorkerCreated;
943
+ }
944
+ export interface WebhookWorkerListResponse {
945
+ pagination?: PaginationResponse;
946
+ rows?: WebhookWorker[];
947
+ }
@@ -0,0 +1,58 @@
1
+ import { IncomingMessage, ServerResponse } from 'http';
2
+ import { Workflow } from '../../workflow';
3
+ import { Worker } from './worker';
4
+ export interface HandlerOpts {
5
+ secret: string;
6
+ }
7
+ export declare class WebhookHandler {
8
+ private worker;
9
+ private workflows;
10
+ constructor(worker: Worker, workflows: Workflow[]);
11
+ /**
12
+ * Handles a request with a provided body, secret, and signature.
13
+ *
14
+ * @param {string | undefined} body - The body of the request.
15
+ * @param {string | undefined} secret - The secret used for signature verification.
16
+ * @param {string | string[] | undefined | null} signature - The signature of the request.
17
+ *
18
+ * @throws {HatchetError} - If no signature is provided or the signature is not a string.
19
+ * @throws {HatchetError} - If no secret is provided.
20
+ * @throws {HatchetError} - If no body is provided.
21
+ */
22
+ handle(body: string | undefined, signature: string | string[] | undefined | null, secret: string | undefined): Promise<void>;
23
+ private checkSignature;
24
+ private getHealthcheckResponse;
25
+ /**
26
+ * Express Handler
27
+ *
28
+ * This method is an asynchronous function that returns an Express middleware handler.
29
+ * The handler function is responsible for handling incoming requests and invoking the
30
+ * corresponding logic based on the provided secret.
31
+ *
32
+ * @param {string} secret - The secret key used to authenticate and authorize the incoming requests.
33
+ *
34
+ * @return {Function} - An Express middleware handler function that receives the request and response objects.
35
+ */
36
+ expressHandler({ secret }: HandlerOpts): (req: any, res: any) => void;
37
+ /**
38
+ * A method that returns an HTTP request handler.
39
+ *
40
+ * @param {string} secret - The secret key used for verification.
41
+ *
42
+ * @returns {function} - An HTTP request handler function.
43
+ */
44
+ httpHandler({ secret }: HandlerOpts): (req: IncomingMessage, res: ServerResponse) => void;
45
+ /**
46
+ * A method that returns a Next.js request handler.
47
+ *
48
+ * @param {any} req - The request object received from Next.js.
49
+ * @param {string} secret - The secret key used to verify the request.
50
+ * @return {Promise<Response>} - A Promise that resolves with a Response object.
51
+ */
52
+ nextJSHandler({ secret }: HandlerOpts): {
53
+ GET: () => Promise<Response>;
54
+ POST: (req: Request) => Promise<Response>;
55
+ PUT: (req: Request) => Promise<Response>;
56
+ };
57
+ private getBody;
58
+ }
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.WebhookHandler = void 0;
16
+ const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error"));
17
+ const crypto_1 = require("crypto");
18
+ const okMessage = 'The Hatchet webhooks endpoint is up and running!';
19
+ class WebhookHandler {
20
+ // eslint-disable-next-line no-useless-constructor
21
+ constructor(worker, workflows
22
+ // eslint-disable-next-line no-empty-function
23
+ ) {
24
+ this.worker = worker;
25
+ this.workflows = workflows;
26
+ }
27
+ /**
28
+ * Handles a request with a provided body, secret, and signature.
29
+ *
30
+ * @param {string | undefined} body - The body of the request.
31
+ * @param {string | undefined} secret - The secret used for signature verification.
32
+ * @param {string | string[] | undefined | null} signature - The signature of the request.
33
+ *
34
+ * @throws {HatchetError} - If no signature is provided or the signature is not a string.
35
+ * @throws {HatchetError} - If no secret is provided.
36
+ * @throws {HatchetError} - If no body is provided.
37
+ */
38
+ handle(body, signature, secret) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ this.checkSignature(body, signature, secret);
41
+ const action = JSON.parse(body);
42
+ yield this.worker.handleAction(action);
43
+ });
44
+ }
45
+ checkSignature(body, signature, secret) {
46
+ if (!signature || typeof signature !== 'string') {
47
+ throw new hatchet_error_1.default('No signature provided');
48
+ }
49
+ if (!secret) {
50
+ throw new hatchet_error_1.default('No secret provided');
51
+ }
52
+ if (!body) {
53
+ throw new hatchet_error_1.default('No body provided');
54
+ }
55
+ // verify hmac signature
56
+ const actualSignature = (0, crypto_1.createHmac)('sha256', secret).update(body).digest('hex');
57
+ if (actualSignature !== signature) {
58
+ throw new hatchet_error_1.default(`Invalid signature, expected ${actualSignature}, got ${signature}`);
59
+ }
60
+ }
61
+ getHealthcheckResponse(body, signature, secret) {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ this.checkSignature(body, signature, secret);
64
+ for (const workflow of this.workflows) {
65
+ yield this.worker.registerWorkflow(workflow);
66
+ }
67
+ return {
68
+ actions: Object.keys(this.worker.action_registry),
69
+ };
70
+ });
71
+ }
72
+ /**
73
+ * Express Handler
74
+ *
75
+ * This method is an asynchronous function that returns an Express middleware handler.
76
+ * The handler function is responsible for handling incoming requests and invoking the
77
+ * corresponding logic based on the provided secret.
78
+ *
79
+ * @param {string} secret - The secret key used to authenticate and authorize the incoming requests.
80
+ *
81
+ * @return {Function} - An Express middleware handler function that receives the request and response objects.
82
+ */
83
+ expressHandler({ secret }) {
84
+ return (req, res) => {
85
+ if (req.method === 'GET') {
86
+ res.sendStatus(200);
87
+ res.send(okMessage);
88
+ return;
89
+ }
90
+ if (req.method === 'PUT') {
91
+ this.getHealthcheckResponse(req.body, req.headers['x-hatchet-signature'], secret)
92
+ .then((resp) => {
93
+ res.sendStatus(200);
94
+ res.json(resp);
95
+ })
96
+ .catch((err) => {
97
+ res.sendStatus(500);
98
+ this.worker.logger.error(`Error handling request: ${err.message}`);
99
+ });
100
+ return;
101
+ }
102
+ if (req.method !== 'POST') {
103
+ res.sendStatus(405);
104
+ res.json({ error: 'Method not allowed' });
105
+ return;
106
+ }
107
+ this.handle(req.body, req.headers['x-hatchet-signature'], secret)
108
+ .then(() => {
109
+ res.sendStatus(200);
110
+ })
111
+ .catch((err) => {
112
+ res.sendStatus(500);
113
+ this.worker.logger.error(`Error handling request: ${err.message}`);
114
+ });
115
+ };
116
+ }
117
+ /**
118
+ * A method that returns an HTTP request handler.
119
+ *
120
+ * @param {string} secret - The secret key used for verification.
121
+ *
122
+ * @returns {function} - An HTTP request handler function.
123
+ */
124
+ httpHandler({ secret }) {
125
+ return (req, res) => {
126
+ const handle = () => __awaiter(this, void 0, void 0, function* () {
127
+ if (req.method === 'GET') {
128
+ res.writeHead(200, { 'Content-Type': 'application/json' });
129
+ res.write(okMessage);
130
+ res.end();
131
+ return;
132
+ }
133
+ const body = yield this.getBody(req);
134
+ if (req.method === 'PUT') {
135
+ const resp = yield this.getHealthcheckResponse(body, req.headers['x-hatchet-signature'], secret);
136
+ res.writeHead(200, { 'Content-Type': 'application/json' });
137
+ res.write(JSON.stringify(resp));
138
+ res.end();
139
+ return;
140
+ }
141
+ if (req.method !== 'POST') {
142
+ res.writeHead(405, { 'Content-Type': 'application/json' });
143
+ res.write(JSON.stringify({ error: 'Method not allowed' }));
144
+ res.end();
145
+ return;
146
+ }
147
+ yield this.handle(body, req.headers['x-hatchet-signature'], secret);
148
+ res.writeHead(200, 'OK');
149
+ res.end();
150
+ });
151
+ handle().catch((e) => {
152
+ this.worker.logger.error(`Error handling request: ${e.message}`);
153
+ res.writeHead(500, 'Internal server error');
154
+ res.end();
155
+ });
156
+ };
157
+ }
158
+ /**
159
+ * A method that returns a Next.js request handler.
160
+ *
161
+ * @param {any} req - The request object received from Next.js.
162
+ * @param {string} secret - The secret key used to verify the request.
163
+ * @return {Promise<Response>} - A Promise that resolves with a Response object.
164
+ */
165
+ nextJSHandler({ secret }) {
166
+ const ok = () => __awaiter(this, void 0, void 0, function* () {
167
+ return new Response(okMessage, { status: 200 });
168
+ });
169
+ const f = (req) => __awaiter(this, void 0, void 0, function* () {
170
+ const sig = req.headers.get('x-hatchet-signature');
171
+ const body = yield req.text();
172
+ if (req.method === 'PUT') {
173
+ const resp = yield this.getHealthcheckResponse(body, sig, secret);
174
+ return new Response(JSON.stringify(resp), { status: 200 });
175
+ }
176
+ if (req.method !== 'POST') {
177
+ return new Response('Method not allowed', { status: 405 });
178
+ }
179
+ yield this.handle(body, sig, secret);
180
+ return new Response('ok', { status: 200 });
181
+ });
182
+ return {
183
+ GET: ok,
184
+ POST: f,
185
+ PUT: f,
186
+ };
187
+ }
188
+ getBody(req) {
189
+ return new Promise((resolve) => {
190
+ let body = '';
191
+ req.on('data', (chunk) => {
192
+ body += chunk;
193
+ });
194
+ req.on('end', () => {
195
+ resolve(body);
196
+ });
197
+ });
198
+ }
199
+ }
200
+ exports.WebhookHandler = WebhookHandler;
@@ -4,6 +4,8 @@ import { StepActionEvent, StepActionEventType, GroupKeyActionEvent, GroupKeyActi
4
4
  import HatchetPromise from '../../util/hatchet-promise/hatchet-promise';
5
5
  import { Workflow } from '../../workflow';
6
6
  import { Logger } from '../../util/logger';
7
+ import { WebhookHandler } from './handler';
8
+ import { WebhookWorkerCreateRequest } from '../rest/generated/data-contracts';
7
9
  import { Context, StepRunFunction } from '../../step';
8
10
  export type ActionRegistry = Record<Action['actionId'], Function>;
9
11
  export declare class Worker {
@@ -23,18 +25,22 @@ export declare class Worker {
23
25
  handleKill?: boolean;
24
26
  maxRuns?: number;
25
27
  });
28
+ private registerActions;
29
+ getHandler(workflows: Workflow[]): WebhookHandler;
30
+ registerWebhook(webhook: WebhookWorkerCreateRequest): Promise<import("axios").AxiosResponse<import("../rest/generated/data-contracts").WebhookWorkerCreated, any>>;
26
31
  /**
27
32
  * @deprecated use registerWorkflow instead
28
33
  */
29
34
  register_workflow(initWorkflow: Workflow): Promise<void>;
30
35
  registerWorkflow(initWorkflow: Workflow): Promise<void>;
31
36
  registerAction<T, K>(actionId: string, action: StepRunFunction<T, K>): void;
32
- handleStartStepRun(action: Action): void;
33
- handleStartGroupKeyRun(action: Action): void;
37
+ handleStartStepRun(action: Action): Promise<void>;
38
+ handleStartGroupKeyRun(action: Action): Promise<void>;
34
39
  getStepActionEvent(action: Action, eventType: StepActionEventType, payload?: any): StepActionEvent;
35
40
  getGroupKeyActionEvent(action: Action, eventType: GroupKeyActionEventType, payload?: any): GroupKeyActionEvent;
36
- handleCancelStepRun(action: Action): void;
41
+ handleCancelStepRun(action: Action): Promise<void>;
37
42
  stop(): Promise<void>;
38
43
  exitGracefully(handleKill: boolean): Promise<void>;
39
44
  start(): Promise<void>;
45
+ handleAction(action: Action): Promise<void>;
40
46
  }