@hatchet-dev/typescript-sdk 1.12.1 → 1.13.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 (60) hide show
  1. package/clients/hatchet-client/client-config.d.ts +59 -0
  2. package/clients/hatchet-client/client-config.js +7 -0
  3. package/clients/worker/worker.js +25 -1
  4. package/package.json +6 -6
  5. package/step.d.ts +18 -18
  6. package/v1/client/client.d.ts +30 -14
  7. package/v1/client/client.js +32 -4
  8. package/v1/client/worker/worker-internal.js +24 -1
  9. package/v1/declaration.d.ts +63 -15
  10. package/v1/declaration.js +66 -2
  11. package/v1/examples/cancellations/workflow.d.ts +2 -2
  12. package/v1/examples/child_workflows/workflow.d.ts +4 -4
  13. package/v1/examples/concurrency-rr/workflow.d.ts +2 -2
  14. package/v1/examples/dag/interface-workflow.d.ts +1 -1
  15. package/v1/examples/dag/workflow.d.ts +1 -1
  16. package/v1/examples/dag_match_condition/complex-workflow.d.ts +1 -1
  17. package/v1/examples/dag_match_condition/workflow.d.ts +1 -1
  18. package/v1/examples/deep/workflow.d.ts +6 -6
  19. package/v1/examples/durable-event/workflow.d.ts +2 -2
  20. package/v1/examples/durable-sleep/workflow.d.ts +1 -1
  21. package/v1/examples/hatchet-client.d.ts +1 -1
  22. package/v1/examples/high-memory/workflow-with-child.d.ts +2 -2
  23. package/v1/examples/inferred-typing/workflow.d.ts +4 -4
  24. package/v1/examples/landing_page/event-signaling.d.ts +1 -1
  25. package/v1/examples/landing_page/flow-control.d.ts +1 -1
  26. package/v1/examples/landing_page/task-routing.d.ts +1 -1
  27. package/v1/examples/middleware/client.d.ts +26 -0
  28. package/v1/examples/middleware/client.js +39 -0
  29. package/v1/examples/middleware/recipes.d.ts +1 -0
  30. package/v1/examples/middleware/recipes.js +95 -0
  31. package/v1/examples/middleware/run.d.ts +1 -0
  32. package/v1/examples/middleware/run.js +29 -0
  33. package/v1/examples/middleware/worker.d.ts +1 -0
  34. package/v1/examples/middleware/worker.js +24 -0
  35. package/v1/examples/middleware/workflow.d.ts +15 -0
  36. package/v1/examples/middleware/workflow.js +18 -0
  37. package/v1/examples/migration-guides/hatchet-client.d.ts +1 -1
  38. package/v1/examples/migration-guides/mergent.d.ts +1 -1
  39. package/v1/examples/multiple_wf_concurrency/workflow.d.ts +1 -1
  40. package/v1/examples/non_retryable/workflow.d.ts +1 -1
  41. package/v1/examples/on_cron/workflow.d.ts +1 -1
  42. package/v1/examples/on_event/workflow.d.ts +3 -3
  43. package/v1/examples/on_failure/workflow.d.ts +1 -1
  44. package/v1/examples/on_success/workflow.d.ts +1 -1
  45. package/v1/examples/priority/workflow.d.ts +4 -4
  46. package/v1/examples/quickstart/hatchet-client.d.ts +1 -1
  47. package/v1/examples/quickstart/workflows/first-task.d.ts +1 -1
  48. package/v1/examples/retries/workflow.d.ts +3 -3
  49. package/v1/examples/simple/stub-workflow.d.ts +1 -1
  50. package/v1/examples/simple/workflow-with-child.d.ts +2 -2
  51. package/v1/examples/simple/workflow.d.ts +1 -1
  52. package/v1/examples/simple/zod.d.ts +1 -1
  53. package/v1/examples/sticky/workflow.d.ts +1 -1
  54. package/v1/examples/streaming/workflow.d.ts +1 -1
  55. package/v1/examples/timeouts/workflow.d.ts +1 -1
  56. package/v1/examples/with_timeouts/workflow.d.ts +2 -2
  57. package/v1/types.d.ts +10 -1
  58. package/version.d.ts +1 -1
  59. package/version.js +1 -1
  60. package/workflow.d.ts +56 -56
@@ -1,5 +1,6 @@
1
1
  import { ChannelCredentials } from 'nice-grpc';
2
2
  import { z } from 'zod';
3
+ import type { Context } from '../../v1/client/worker/context';
3
4
  import { Logger, LogLevel } from '../../util/logger';
4
5
  declare const ClientTLSConfigSchema: z.ZodObject<{
5
6
  tls_strategy: z.ZodOptional<z.ZodEnum<["tls", "mtls", "none"]>>;
@@ -56,6 +57,16 @@ export declare const ClientConfigSchema: z.ZodObject<{
56
57
  log_level: z.ZodOptional<z.ZodEnum<["OFF", "DEBUG", "INFO", "WARN", "ERROR"]>>;
57
58
  tenant_id: z.ZodString;
58
59
  namespace: z.ZodOptional<z.ZodString>;
60
+ middleware: z.ZodOptional<z.ZodObject<{
61
+ before: z.ZodOptional<z.ZodAny>;
62
+ after: z.ZodOptional<z.ZodAny>;
63
+ }, "strip", z.ZodTypeAny, {
64
+ before?: any;
65
+ after?: any;
66
+ }, {
67
+ before?: any;
68
+ after?: any;
69
+ }>>;
59
70
  }, "strip", z.ZodTypeAny, {
60
71
  token: string;
61
72
  tls_config: {
@@ -74,6 +85,10 @@ export declare const ClientConfigSchema: z.ZodObject<{
74
85
  } | undefined;
75
86
  log_level?: "OFF" | "DEBUG" | "INFO" | "WARN" | "ERROR" | undefined;
76
87
  namespace?: string | undefined;
88
+ middleware?: {
89
+ before?: any;
90
+ after?: any;
91
+ } | undefined;
77
92
  }, {
78
93
  token: string;
79
94
  tls_config: {
@@ -92,12 +107,56 @@ export declare const ClientConfigSchema: z.ZodObject<{
92
107
  } | undefined;
93
108
  log_level?: "OFF" | "DEBUG" | "INFO" | "WARN" | "ERROR" | undefined;
94
109
  namespace?: string | undefined;
110
+ middleware?: {
111
+ before?: any;
112
+ after?: any;
113
+ } | undefined;
95
114
  }>;
96
115
  export type LogConstructor = (context: string, logLevel?: LogLevel) => Logger;
116
+ /**
117
+ * A middleware function that runs before every task invocation.
118
+ * Returns extra fields to replace the task input, or void to skip.
119
+ * @template T - The expected input type for the hook.
120
+ * @param input - The current task input.
121
+ * @param ctx - The task execution context.
122
+ * @returns The new input value, or void to pass through unchanged.
123
+ */
124
+ export type BeforeHookFn<T = any> = (input: T, ctx: Context<any>) => Record<string, any> | void | Promise<Record<string, any> | void>;
125
+ /**
126
+ * A middleware function that runs after every task invocation.
127
+ * Returns extra fields to replace the task output, or void to skip.
128
+ * @param output - The task output.
129
+ * @param ctx - The task execution context.
130
+ * @param input - The task input (after before-hooks have run).
131
+ * @returns The new output value, or void to pass through unchanged.
132
+ */
133
+ export type AfterHookFn<TOutput = any, TInput = any> = (output: TOutput, ctx: Context<any>, input: TInput) => Record<string, any> | void | Promise<Record<string, any> | void>;
134
+ /**
135
+ * Middleware hooks that run before/after every task invocation.
136
+ *
137
+ * Each hook can be a single function or an array of functions.
138
+ * When an array is provided the functions run in order and each
139
+ * result replaces the value (input for `before`, output for `after`).
140
+ *
141
+ * Return `void` (or `undefined`) from a hook to pass through unchanged.
142
+ */
143
+ export type TaskMiddleware<TInput = any, TOutput = any> = {
144
+ before?: BeforeHookFn<TInput> | readonly BeforeHookFn<TInput>[];
145
+ after?: AfterHookFn<TOutput, TInput> | readonly AfterHookFn<TOutput, TInput>[];
146
+ };
147
+ type NonVoidReturn<F> = F extends (...args: any[]) => infer R ? Exclude<Awaited<R>, void | undefined> : {};
148
+ type MergeReturns<T> = T extends readonly [infer F, ...infer Rest] ? NonVoidReturn<F> & MergeReturns<Rest> : {};
149
+ export type InferMiddlewareBefore<M> = M extends {
150
+ before: infer P;
151
+ } ? P extends (...args: any[]) => any ? NonVoidReturn<P> : P extends readonly any[] ? MergeReturns<P> : {} : {};
152
+ export type InferMiddlewareAfter<M> = M extends {
153
+ after: infer P;
154
+ } ? P extends (...args: any[]) => any ? NonVoidReturn<P> : P extends readonly any[] ? MergeReturns<P> : {} : {};
97
155
  export type ClientConfig = z.infer<typeof ClientConfigSchema> & {
98
156
  credentials?: ChannelCredentials;
99
157
  } & {
100
158
  logger: LogConstructor;
159
+ middleware?: TaskMiddleware;
101
160
  };
102
161
  export type ClientTLSConfig = z.infer<typeof ClientTLSConfigSchema>;
103
162
  export {};
@@ -13,6 +13,12 @@ const HealthcheckConfigSchema = zod_1.z.object({
13
13
  enabled: zod_1.z.boolean().optional().default(false),
14
14
  port: zod_1.z.number().optional().default(8001),
15
15
  });
16
+ const TaskMiddlewareSchema = zod_1.z
17
+ .object({
18
+ before: zod_1.z.any().optional(),
19
+ after: zod_1.z.any().optional(),
20
+ })
21
+ .optional();
16
22
  exports.ClientConfigSchema = zod_1.z.object({
17
23
  token: zod_1.z.string(),
18
24
  tls_config: ClientTLSConfigSchema,
@@ -22,4 +28,5 @@ exports.ClientConfigSchema = zod_1.z.object({
22
28
  log_level: zod_1.z.enum(['OFF', 'DEBUG', 'INFO', 'WARN', 'ERROR']).optional(),
23
29
  tenant_id: zod_1.z.string(),
24
30
  namespace: zod_1.z.string().optional(),
31
+ middleware: TaskMiddlewareSchema,
25
32
  });
@@ -184,7 +184,31 @@ class V0Worker {
184
184
  return;
185
185
  }
186
186
  const run = () => __awaiter(this, void 0, void 0, function* () {
187
- return step(context);
187
+ const { middleware } = this.client.config;
188
+ if (middleware === null || middleware === void 0 ? void 0 : middleware.before) {
189
+ const hooks = Array.isArray(middleware.before) ? middleware.before : [middleware.before];
190
+ for (const hook of hooks) {
191
+ const extra = yield hook(context.input, context);
192
+ if (extra !== undefined) {
193
+ const merged = Object.assign(Object.assign({}, context.input), extra);
194
+ context.input = merged;
195
+ if (context.data && typeof context.data === 'object') {
196
+ context.data.input = merged;
197
+ }
198
+ }
199
+ }
200
+ }
201
+ let result = yield step(context);
202
+ if (middleware === null || middleware === void 0 ? void 0 : middleware.after) {
203
+ const hooks = Array.isArray(middleware.after) ? middleware.after : [middleware.after];
204
+ for (const hook of hooks) {
205
+ const extra = yield hook(result, context, context.input);
206
+ if (extra !== undefined) {
207
+ result = Object.assign(Object.assign({}, result), extra);
208
+ }
209
+ }
210
+ }
211
+ return result;
188
212
  });
189
213
  const success = (result) => __awaiter(this, void 0, void 0, function* () {
190
214
  this.logger.info(`Task run ${action.taskRunExternalId} succeeded`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "1.12.1",
3
+ "version": "1.13.1",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -22,12 +22,12 @@
22
22
  "@tsd/typescript": "^5.8.2",
23
23
  "@types/jest": "^29.5.14",
24
24
  "@types/node": "^22.13.14",
25
- "@typescript-eslint/eslint-plugin": "^6.21.0",
26
- "@typescript-eslint/parser": "^6.21.0",
25
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
26
+ "@typescript-eslint/parser": "^7.0.0",
27
27
  "autoprefixer": "^10.4.21",
28
28
  "dotenv-cli": "^7.4.4",
29
29
  "eslint": "^8.56.0",
30
- "eslint-config-airbnb-typescript": "^17.1.0",
30
+ "eslint-config-airbnb-typescript": "^18.0.0",
31
31
  "eslint-config-prettier": "^9.1.0",
32
32
  "eslint-config-standard": "^17.1.0",
33
33
  "eslint-import-resolver-typescript": "^3.10.0",
@@ -57,12 +57,12 @@
57
57
  "@bufbuild/protobuf": "^2.2.5",
58
58
  "@types/qs": "^6.9.18",
59
59
  "abort-controller-x": "^0.4.3",
60
- "axios": "^1.11.0",
60
+ "axios": "^1.13.5",
61
61
  "long": "^5.3.1",
62
62
  "nice-grpc": "^2.1.12",
63
63
  "nice-grpc-common": "^2.0.2",
64
64
  "protobufjs": "^7.4.0",
65
- "qs": "^6.14.1",
65
+ "qs": "^6.14.2",
66
66
  "semver": "^7.7.1",
67
67
  "yaml": "^2.7.1",
68
68
  "zod": "^3.24.2",
package/step.d.ts CHANGED
@@ -25,17 +25,17 @@ export declare const CreateRateLimitSchema: z.ZodObject<{
25
25
  }, "strip", z.ZodTypeAny, {
26
26
  units: string | number;
27
27
  key?: string | undefined;
28
- duration?: RateLimitDuration | undefined;
29
- limit?: string | number | undefined;
30
28
  staticKey?: string | undefined;
31
29
  dynamicKey?: string | undefined;
30
+ limit?: string | number | undefined;
31
+ duration?: RateLimitDuration | undefined;
32
32
  }, {
33
33
  units: string | number;
34
34
  key?: string | undefined;
35
- duration?: RateLimitDuration | undefined;
36
- limit?: string | number | undefined;
37
35
  staticKey?: string | undefined;
38
36
  dynamicKey?: string | undefined;
37
+ limit?: string | number | undefined;
38
+ duration?: RateLimitDuration | undefined;
39
39
  }>;
40
40
  export declare const DesiredWorkerLabelSchema: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodObject<{
41
41
  value: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
@@ -45,13 +45,13 @@ export declare const DesiredWorkerLabelSchema: z.ZodOptional<z.ZodUnion<[z.ZodSt
45
45
  }, "strip", z.ZodTypeAny, {
46
46
  value: string | number;
47
47
  required?: boolean | undefined;
48
- comparator?: WorkerLabelComparator | undefined;
49
48
  weight?: number | undefined;
49
+ comparator?: WorkerLabelComparator | undefined;
50
50
  }, {
51
51
  value: string | number;
52
52
  required?: boolean | undefined;
53
- comparator?: WorkerLabelComparator | undefined;
54
53
  weight?: number | undefined;
54
+ comparator?: WorkerLabelComparator | undefined;
55
55
  }>]>>;
56
56
  export declare const CreateStepSchema: z.ZodObject<{
57
57
  name: z.ZodString;
@@ -68,17 +68,17 @@ export declare const CreateStepSchema: z.ZodObject<{
68
68
  }, "strip", z.ZodTypeAny, {
69
69
  units: string | number;
70
70
  key?: string | undefined;
71
- duration?: RateLimitDuration | undefined;
72
- limit?: string | number | undefined;
73
71
  staticKey?: string | undefined;
74
72
  dynamicKey?: string | undefined;
73
+ limit?: string | number | undefined;
74
+ duration?: RateLimitDuration | undefined;
75
75
  }, {
76
76
  units: string | number;
77
77
  key?: string | undefined;
78
- duration?: RateLimitDuration | undefined;
79
- limit?: string | number | undefined;
80
78
  staticKey?: string | undefined;
81
79
  dynamicKey?: string | undefined;
80
+ limit?: string | number | undefined;
81
+ duration?: RateLimitDuration | undefined;
82
82
  }>, "many">>;
83
83
  worker_labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodLazy<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodObject<{
84
84
  value: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
@@ -88,13 +88,13 @@ export declare const CreateStepSchema: z.ZodObject<{
88
88
  }, "strip", z.ZodTypeAny, {
89
89
  value: string | number;
90
90
  required?: boolean | undefined;
91
- comparator?: WorkerLabelComparator | undefined;
92
91
  weight?: number | undefined;
92
+ comparator?: WorkerLabelComparator | undefined;
93
93
  }, {
94
94
  value: string | number;
95
95
  required?: boolean | undefined;
96
- comparator?: WorkerLabelComparator | undefined;
97
96
  weight?: number | undefined;
97
+ comparator?: WorkerLabelComparator | undefined;
98
98
  }>]>>>>>;
99
99
  backoff: z.ZodOptional<z.ZodObject<{
100
100
  factor: z.ZodOptional<z.ZodNumber>;
@@ -114,16 +114,16 @@ export declare const CreateStepSchema: z.ZodObject<{
114
114
  rate_limits?: {
115
115
  units: string | number;
116
116
  key?: string | undefined;
117
- duration?: RateLimitDuration | undefined;
118
- limit?: string | number | undefined;
119
117
  staticKey?: string | undefined;
120
118
  dynamicKey?: string | undefined;
119
+ limit?: string | number | undefined;
120
+ duration?: RateLimitDuration | undefined;
121
121
  }[] | undefined;
122
122
  worker_labels?: Record<string, string | number | {
123
123
  value: string | number;
124
124
  required?: boolean | undefined;
125
- comparator?: WorkerLabelComparator | undefined;
126
125
  weight?: number | undefined;
126
+ comparator?: WorkerLabelComparator | undefined;
127
127
  } | undefined> | undefined;
128
128
  backoff?: {
129
129
  factor?: number | undefined;
@@ -137,16 +137,16 @@ export declare const CreateStepSchema: z.ZodObject<{
137
137
  rate_limits?: {
138
138
  units: string | number;
139
139
  key?: string | undefined;
140
- duration?: RateLimitDuration | undefined;
141
- limit?: string | number | undefined;
142
140
  staticKey?: string | undefined;
143
141
  dynamicKey?: string | undefined;
142
+ limit?: string | number | undefined;
143
+ duration?: RateLimitDuration | undefined;
144
144
  }[] | undefined;
145
145
  worker_labels?: Record<string, string | number | {
146
146
  value: string | number;
147
147
  required?: boolean | undefined;
148
- comparator?: WorkerLabelComparator | undefined;
149
148
  weight?: number | undefined;
149
+ comparator?: WorkerLabelComparator | undefined;
150
150
  } | undefined> | undefined;
151
151
  backoff?: {
152
152
  factor?: number | undefined;
@@ -1,4 +1,4 @@
1
- import { ClientConfig, HatchetClientOptions, LegacyHatchetClient } from '../../clients/hatchet-client';
1
+ import { ClientConfig, HatchetClientOptions, LegacyHatchetClient, TaskMiddleware, InferMiddlewareBefore, InferMiddlewareAfter } from '../../clients/hatchet-client';
2
2
  import { AxiosRequestConfig } from 'axios';
3
3
  import WorkflowRunRef from '../../util/workflow-run-ref';
4
4
  import { Workflow as V0Workflow } from '../../workflow';
@@ -12,7 +12,7 @@ import { MetricsClient } from './features/metrics';
12
12
  import { WorkersClient } from './features/workers';
13
13
  import { WorkflowsClient } from './features/workflows';
14
14
  import { RunsClient } from './features/runs';
15
- import { InputType, OutputType, UnknownInputType, StrictWorkflowOutputType } from '../types';
15
+ import { InputType, OutputType, UnknownInputType, StrictWorkflowOutputType, Resolved } from '../types';
16
16
  import { RatelimitsClient } from './features';
17
17
  import { AdminClient } from './admin';
18
18
  import { FiltersClient } from './features/filters';
@@ -21,11 +21,16 @@ import { CronClient } from './features/crons';
21
21
  import { CELClient } from './features/cel';
22
22
  import { TenantClient } from './features/tenant';
23
23
  import { WebhooksClient } from './features/webhooks';
24
+ type MergeIfNonEmpty<Base, Extra extends Record<string, any>> = keyof Extra extends never ? Base : Base & Extra;
24
25
  /**
25
26
  * HatchetV1 implements the main client interface for interacting with the Hatchet workflow engine.
26
27
  * It provides methods for creating and executing workflows, as well as managing workers.
28
+ *
29
+ * @template GlobalInput - Global input type required by all tasks. Set via `init<T>()`. Defaults to `{}`.
30
+ * @template MiddlewareBefore - Extra fields merged into task input by pre-middleware hooks. Inferred from middleware config.
31
+ * @template MiddlewareAfter - Extra fields merged into task output by post-middleware hooks. Inferred from middleware config.
27
32
  */
28
- export declare class HatchetClient implements IHatchetClient {
33
+ export declare class HatchetClient<GlobalInput extends Record<string, any> = {}, GlobalOutput extends Record<string, any> = {}, MiddlewareBefore extends Record<string, any> = {}, MiddlewareAfter extends Record<string, any> = {}> implements IHatchetClient {
29
34
  /** The underlying v0 client instance */
30
35
  _v0: LegacyHatchetClient;
31
36
  _api: Api;
@@ -47,12 +52,22 @@ export declare class HatchetClient implements IHatchetClient {
47
52
  constructor(config?: Partial<ClientConfig>, options?: HatchetClientOptions, axiosConfig?: AxiosRequestConfig);
48
53
  /**
49
54
  * Static factory method to create a new Hatchet client instance.
50
- * @param config - Optional configuration for the client
51
- * @param options - Optional client options
52
- * @param axiosConfig - Optional Axios configuration for HTTP requests
53
- * @returns A new Hatchet client instance
54
- */
55
- static init(config?: Partial<ClientConfig>, options?: HatchetClientOptions, axiosConfig?: AxiosRequestConfig): HatchetClient;
55
+ * @template T - Global input type required by all tasks created from this client. Defaults to `{}`.
56
+ * @template U - Global output type required by all tasks created from this client. Defaults to `{}`.
57
+ * @param config - Optional configuration for the client.
58
+ * @param options - Optional client options.
59
+ * @param axiosConfig - Optional Axios configuration for HTTP requests.
60
+ * @returns A new Hatchet client instance. Chain `.withMiddleware()` to attach typed middleware.
61
+ */
62
+ static init<T extends Record<string, any> = {}, U extends Record<string, any> = {}>(config?: Omit<Partial<ClientConfig>, 'middleware'>, options?: HatchetClientOptions, axiosConfig?: AxiosRequestConfig): HatchetClient<T, U>;
63
+ /**
64
+ * Attaches middleware to this client and returns a re-typed instance
65
+ * with inferred pre/post middleware types.
66
+ *
67
+ * Use this after `init<T, U>()` to get full middleware return-type inference
68
+ * that TypeScript can't provide when global types are explicitly set on `init`.
69
+ */
70
+ withMiddleware<const M extends TaskMiddleware<Resolved<GlobalInput, MiddlewareBefore>, Resolved<GlobalOutput, MiddlewareAfter>>>(middleware: M): HatchetClient<GlobalInput, GlobalOutput, MiddlewareBefore & InferMiddlewareBefore<M>, MiddlewareAfter & InferMiddlewareAfter<M>>;
56
71
  private _config;
57
72
  get config(): ClientConfig;
58
73
  /**
@@ -63,7 +78,7 @@ export declare class HatchetClient implements IHatchetClient {
63
78
  * @returns A new Workflow instance
64
79
  * @note It is possible to create an orphaned workflow if no client is available using @hatchet/client CreateWorkflow
65
80
  */
66
- workflow<I extends InputType = UnknownInputType, O extends StrictWorkflowOutputType = {}>(options: CreateWorkflowOpts): WorkflowDeclaration<I, O>;
81
+ workflow<I extends InputType = UnknownInputType, O extends StrictWorkflowOutputType = {}>(options: CreateWorkflowOpts): WorkflowDeclaration<I, O, Resolved<GlobalInput, MiddlewareBefore>>;
67
82
  /**
68
83
  * Creates a new task workflow.
69
84
  * Types can be explicitly specified as generics or inferred from the function signature.
@@ -72,7 +87,7 @@ export declare class HatchetClient implements IHatchetClient {
72
87
  * @param options Task configuration options
73
88
  * @returns A TaskWorkflowDeclaration instance
74
89
  */
75
- task<I extends InputType = UnknownInputType, O extends OutputType = void>(options: CreateTaskWorkflowOpts<I, O>): TaskWorkflowDeclaration<I, O>;
90
+ task<I extends InputType = UnknownInputType, O extends OutputType = void>(options: CreateTaskWorkflowOpts<I & Resolved<GlobalInput, MiddlewareBefore>, MergeIfNonEmpty<O, GlobalOutput>>): TaskWorkflowDeclaration<I, O, GlobalInput, GlobalOutput, MiddlewareBefore, MiddlewareAfter>;
76
91
  /**
77
92
  * Creates a new task workflow with types inferred from the function parameter.
78
93
  * @template Fn The type of the task function with input and output extending JsonObject
@@ -81,7 +96,7 @@ export declare class HatchetClient implements IHatchetClient {
81
96
  */
82
97
  task<Fn extends (input: I, ctx?: any) => O | Promise<O>, I extends InputType = Parameters<Fn>[0] | UnknownInputType, O extends OutputType = ReturnType<Fn> extends Promise<infer P> ? P extends OutputType ? P : void : ReturnType<Fn> extends OutputType ? ReturnType<Fn> : void>(options: {
83
98
  fn: Fn;
84
- } & Omit<CreateTaskWorkflowOpts<I, O>, 'fn'>): TaskWorkflowDeclaration<I, O>;
99
+ } & Omit<CreateTaskWorkflowOpts<I, O>, 'fn'>): TaskWorkflowDeclaration<I, O, GlobalInput, GlobalOutput, MiddlewareBefore, MiddlewareAfter>;
85
100
  /**
86
101
  * Creates a new durable task workflow.
87
102
  * Types can be explicitly specified as generics or inferred from the function signature.
@@ -90,7 +105,7 @@ export declare class HatchetClient implements IHatchetClient {
90
105
  * @param options Durable task configuration options
91
106
  * @returns A TaskWorkflowDeclaration instance for a durable task
92
107
  */
93
- durableTask<I extends InputType, O extends OutputType>(options: CreateDurableTaskWorkflowOpts<I, O>): TaskWorkflowDeclaration<I, O>;
108
+ durableTask<I extends InputType, O extends OutputType>(options: CreateDurableTaskWorkflowOpts<I & Resolved<GlobalInput, MiddlewareBefore>, MergeIfNonEmpty<O, GlobalOutput>>): TaskWorkflowDeclaration<I, O, GlobalInput, GlobalOutput, MiddlewareBefore, MiddlewareAfter>;
94
109
  /**
95
110
  * Creates a new durable task workflow with types inferred from the function parameter.
96
111
  * @template Fn The type of the durable task function with input and output extending JsonObject
@@ -99,7 +114,7 @@ export declare class HatchetClient implements IHatchetClient {
99
114
  */
100
115
  durableTask<Fn extends (input: I, ctx: V0DurableContext<I>) => O | Promise<O>, I extends InputType = Parameters<Fn>[0], O extends OutputType = ReturnType<Fn> extends Promise<infer P> ? P extends OutputType ? P : void : ReturnType<Fn> extends OutputType ? ReturnType<Fn> : void>(options: {
101
116
  fn: Fn;
102
- } & Omit<CreateDurableTaskWorkflowOpts<I, O>, 'fn'>): TaskWorkflowDeclaration<I, O>;
117
+ } & Omit<CreateDurableTaskWorkflowOpts<I, O>, 'fn'>): TaskWorkflowDeclaration<I, O, GlobalInput, GlobalOutput, MiddlewareBefore, MiddlewareAfter>;
103
118
  /**
104
119
  * Triggers a workflow run without waiting for completion.
105
120
  * @template I - The input type for the workflow
@@ -255,3 +270,4 @@ export declare class HatchetClient implements IHatchetClient {
255
270
  v0webhooks(workflows: V0Workflow[]): import("../../clients/worker/handler").WebhookHandler;
256
271
  runRef<T extends Record<string, any> = any>(id: string): WorkflowRunRef<T>;
257
272
  }
273
+ export {};
@@ -41,6 +41,10 @@ const webhooks_1 = require("./features/webhooks");
41
41
  /**
42
42
  * HatchetV1 implements the main client interface for interacting with the Hatchet workflow engine.
43
43
  * It provides methods for creating and executing workflows, as well as managing workers.
44
+ *
45
+ * @template GlobalInput - Global input type required by all tasks. Set via `init<T>()`. Defaults to `{}`.
46
+ * @template MiddlewareBefore - Extra fields merged into task input by pre-middleware hooks. Inferred from middleware config.
47
+ * @template MiddlewareAfter - Extra fields merged into task output by post-middleware hooks. Inferred from middleware config.
44
48
  */
45
49
  class HatchetClient {
46
50
  /**
@@ -105,14 +109,38 @@ class HatchetClient {
105
109
  }
106
110
  /**
107
111
  * Static factory method to create a new Hatchet client instance.
108
- * @param config - Optional configuration for the client
109
- * @param options - Optional client options
110
- * @param axiosConfig - Optional Axios configuration for HTTP requests
111
- * @returns A new Hatchet client instance
112
+ * @template T - Global input type required by all tasks created from this client. Defaults to `{}`.
113
+ * @template U - Global output type required by all tasks created from this client. Defaults to `{}`.
114
+ * @param config - Optional configuration for the client.
115
+ * @param options - Optional client options.
116
+ * @param axiosConfig - Optional Axios configuration for HTTP requests.
117
+ * @returns A new Hatchet client instance. Chain `.withMiddleware()` to attach typed middleware.
112
118
  */
113
119
  static init(config, options, axiosConfig) {
114
120
  return new HatchetClient(config, options, axiosConfig);
115
121
  }
122
+ /**
123
+ * Attaches middleware to this client and returns a re-typed instance
124
+ * with inferred pre/post middleware types.
125
+ *
126
+ * Use this after `init<T, U>()` to get full middleware return-type inference
127
+ * that TypeScript can't provide when global types are explicitly set on `init`.
128
+ */
129
+ withMiddleware(middleware) {
130
+ const existing = this._config.middleware || {};
131
+ const toArray = (v) => {
132
+ if (v == null)
133
+ return [];
134
+ if (Array.isArray(v))
135
+ return [...v];
136
+ return [v];
137
+ };
138
+ this._config.middleware = {
139
+ before: [...toArray(existing.before), ...toArray(middleware.before)],
140
+ after: [...toArray(existing.after), ...toArray(middleware.after)],
141
+ };
142
+ return this;
143
+ }
116
144
  get config() {
117
145
  return this._config;
118
146
  }
@@ -424,7 +424,30 @@ class V1Worker {
424
424
  childIndex: 0,
425
425
  desiredWorkerId: this.workerId || '',
426
426
  });
427
- return step(context);
427
+ const { middleware } = this.client.config;
428
+ if (middleware === null || middleware === void 0 ? void 0 : middleware.before) {
429
+ const hooks = Array.isArray(middleware.before) ? middleware.before : [middleware.before];
430
+ for (const hook of hooks) {
431
+ const returned = yield hook(context.input, context);
432
+ if (returned !== undefined) {
433
+ context.input = returned;
434
+ if (context.data && typeof context.data === 'object') {
435
+ context.data.input = returned;
436
+ }
437
+ }
438
+ }
439
+ }
440
+ let result = yield step(context);
441
+ if (middleware === null || middleware === void 0 ? void 0 : middleware.after) {
442
+ const hooks = Array.isArray(middleware.after) ? middleware.after : [middleware.after];
443
+ for (const hook of hooks) {
444
+ const returned = yield hook(result, context, context.input);
445
+ if (returned !== undefined) {
446
+ result = returned;
447
+ }
448
+ }
449
+ }
450
+ return result;
428
451
  });
429
452
  const success = (result) => __awaiter(this, void 0, void 0, function* () {
430
453
  try {
@@ -6,7 +6,7 @@ import { IHatchetClient } from './client/client.interface';
6
6
  import { CreateWorkflowTaskOpts, CreateOnFailureTaskOpts, TaskFn, CreateWorkflowDurableTaskOpts, CreateBaseTaskOpts, CreateOnSuccessTaskOpts, Concurrency, DurableTaskFn } from './task';
7
7
  import { Duration } from './client/duration';
8
8
  import { MetricsClient } from './client/features/metrics';
9
- import { InputType, OutputType, UnknownInputType, JsonObject } from './types';
9
+ import { InputType, OutputType, UnknownInputType, JsonObject, Resolved } from './types';
10
10
  import { Context, DurableContext } from './client/worker/context';
11
11
  export declare enum Priority {
12
12
  LOW = 1,
@@ -290,7 +290,7 @@ export declare class BaseWorkflowDeclaration<I extends InputType = UnknownInputT
290
290
  */
291
291
  get name(): string;
292
292
  }
293
- export declare class WorkflowDeclaration<I extends InputType = UnknownInputType, O extends OutputType = void> extends BaseWorkflowDeclaration<I, O> {
293
+ export declare class WorkflowDeclaration<I extends InputType = UnknownInputType, O extends OutputType = void, MiddlewareBefore extends Record<string, any> = {}> extends BaseWorkflowDeclaration<I, O> {
294
294
  /**
295
295
  * Adds a task to the workflow.
296
296
  * The return type will be either the property on O that corresponds to the task name,
@@ -300,7 +300,7 @@ export declare class WorkflowDeclaration<I extends InputType = UnknownInputType,
300
300
  * @param options The task configuration options.
301
301
  * @returns The task options that were added.
302
302
  */
303
- task<Name extends string, Fn extends Name extends keyof O ? (input: I, ctx: Context<I>) => O[Name] extends OutputType ? O[Name] | Promise<O[Name]> : void : (input: I, ctx: Context<I>) => void, FnReturn = ReturnType<Fn> extends Promise<infer P> ? P : ReturnType<Fn>, TO extends OutputType = Name extends keyof O ? O[Name] extends OutputType ? O[Name] : never : FnReturn extends OutputType ? FnReturn : never>(options: (Omit<CreateWorkflowTaskOpts<I, TO>, 'fn'> & {
303
+ task<Name extends string, Fn extends Name extends keyof O ? (input: I & MiddlewareBefore, ctx: Context<I & MiddlewareBefore>) => O[Name] extends OutputType ? O[Name] | Promise<O[Name]> : void : (input: I & MiddlewareBefore, ctx: Context<I & MiddlewareBefore>) => void, FnReturn = ReturnType<Fn> extends Promise<infer P> ? P : ReturnType<Fn>, TO extends OutputType = Name extends keyof O ? O[Name] extends OutputType ? O[Name] : never : FnReturn extends OutputType ? FnReturn : never>(options: (Omit<CreateWorkflowTaskOpts<I, TO>, 'fn'> & {
304
304
  name: Name;
305
305
  fn?: Fn;
306
306
  }) | TaskWorkflowDeclaration<I, TO>): CreateWorkflowTaskOpts<I, TO>;
@@ -335,25 +335,73 @@ export declare class WorkflowDeclaration<I extends InputType = UnknownInputType,
335
335
  * @param options The task configuration options.
336
336
  * @returns The task options that were added.
337
337
  */
338
- durableTask<Name extends string, Fn extends Name extends keyof O ? (input: I, ctx: DurableContext<I>) => O[Name] extends OutputType ? O[Name] | Promise<O[Name]> : void : (input: I, ctx: DurableContext<I>) => void, FnReturn = ReturnType<Fn> extends Promise<infer P> ? P : ReturnType<Fn>, TO extends OutputType = Name extends keyof O ? O[Name] extends OutputType ? O[Name] : never : FnReturn extends OutputType ? FnReturn : never>(options: Omit<CreateWorkflowTaskOpts<I, TO>, 'fn'> & {
338
+ durableTask<Name extends string, Fn extends Name extends keyof O ? (input: I & MiddlewareBefore, ctx: DurableContext<I & MiddlewareBefore>) => O[Name] extends OutputType ? O[Name] | Promise<O[Name]> : void : (input: I & MiddlewareBefore, ctx: DurableContext<I & MiddlewareBefore>) => void, FnReturn = ReturnType<Fn> extends Promise<infer P> ? P : ReturnType<Fn>, TO extends OutputType = Name extends keyof O ? O[Name] extends OutputType ? O[Name] : never : FnReturn extends OutputType ? FnReturn : never>(options: Omit<CreateWorkflowTaskOpts<I, TO>, 'fn'> & {
339
339
  name: Name;
340
340
  fn: Fn;
341
341
  }): CreateWorkflowDurableTaskOpts<I, TO>;
342
342
  }
343
- export declare class TaskWorkflowDeclaration<I extends InputType = UnknownInputType, O extends OutputType = void> extends BaseWorkflowDeclaration<I, O> {
343
+ /**
344
+ * A standalone task workflow that can be run, scheduled, or triggered via cron.
345
+ *
346
+ * @template I - The task-specific input type.
347
+ * @template O - The task output type.
348
+ * @template GlobalInput - Global input type from the client, merged into all run/schedule/cron input signatures.
349
+ * @template MiddlewareBefore - Extra fields added to the task fn input by pre-middleware hooks.
350
+ * @template MiddlewareAfter - Extra fields merged into the task output by post-middleware hooks.
351
+ */
352
+ export declare class TaskWorkflowDeclaration<I extends InputType = UnknownInputType, O extends OutputType = void, GlobalInput extends Record<string, any> = {}, GlobalOutput extends Record<string, any> = {}, MiddlewareBefore extends Record<string, any> = {}, MiddlewareAfter extends Record<string, any> = {}> extends BaseWorkflowDeclaration<I, O> {
344
353
  _standalone_task_name: string;
345
- constructor(options: CreateTaskWorkflowOpts<I, O>, client?: IHatchetClient);
346
- run(input: I, options?: RunOpts): Promise<O>;
347
- run(input: I[], options?: RunOpts): Promise<O[]>;
354
+ constructor(options: CreateTaskWorkflowOpts<any, any>, client?: IHatchetClient);
348
355
  /**
349
- * Triggers a workflow run without waiting for completion.
350
- * @param input The input data for the workflow.
351
- * @param options Optional configuration for this workflow run.
352
- * @returns A WorkflowRunRef containing the run ID and methods to get results and interact with the run.
353
- * @throws Error if the workflow is not bound to a Hatchet client.
356
+ * Triggers a task run and waits for the result.
357
+ * @param input - The input data for the task, including global input fields.
358
+ * @param options - Optional configuration for this task run.
359
+ * @returns A promise that resolves with the task output merged with post-middleware fields.
360
+ */
361
+ runAndWait(input: I & GlobalInput, options?: RunOpts): Promise<O & Resolved<GlobalOutput, MiddlewareAfter>>;
362
+ runAndWait(input: (I & GlobalInput)[], options?: RunOpts): Promise<(O & Resolved<GlobalOutput, MiddlewareAfter>)[]>;
363
+ /**
364
+ * Triggers a task run and waits for the result.
365
+ * @param input - The input data for the task, including global input fields.
366
+ * @param options - Optional configuration for this task run.
367
+ * @returns A promise that resolves with the task output merged with post-middleware fields.
368
+ */
369
+ run(input: I & GlobalInput, options?: RunOpts): Promise<O & Resolved<GlobalOutput, MiddlewareAfter>>;
370
+ run(input: (I & GlobalInput)[], options?: RunOpts): Promise<(O & Resolved<GlobalOutput, MiddlewareAfter>)[]>;
371
+ /**
372
+ * Triggers a task run without waiting for completion.
373
+ * @param input - The input data for the task, including global input fields.
374
+ * @param options - Optional configuration for this task run.
375
+ * @returns A WorkflowRunRef containing the run ID and methods to get results.
376
+ */
377
+ runNoWait(input: I & GlobalInput, options?: RunOpts): Promise<WorkflowRunRef<O & Resolved<GlobalOutput, MiddlewareAfter>>>;
378
+ runNoWait(input: (I & GlobalInput)[], options?: RunOpts): Promise<WorkflowRunRef<O & Resolved<GlobalOutput, MiddlewareAfter>>[]>;
379
+ /**
380
+ * Schedules the task to run at a specific date and time.
381
+ * @param enqueueAt - The date when the task should be triggered.
382
+ * @param input - The input data for the task, including global input fields.
383
+ * @param options - Optional configuration for this task run.
384
+ * @returns A promise that resolves with the scheduled workflow details.
385
+ */
386
+ schedule(enqueueAt: Date, input: I & GlobalInput, options?: RunOpts): Promise<ScheduledWorkflows>;
387
+ /**
388
+ * Schedules the task to run after a specified delay.
389
+ * @param duration - The delay in seconds before the task should run.
390
+ * @param input - The input data for the task, including global input fields.
391
+ * @param options - Optional configuration for this task run.
392
+ * @returns A promise that resolves with the scheduled workflow details.
393
+ */
394
+ delay(duration: number, input: I & GlobalInput, options?: RunOpts): Promise<ScheduledWorkflows>;
395
+ /**
396
+ * Creates a cron schedule for the task.
397
+ * @param name - The name of the cron schedule.
398
+ * @param expression - The cron expression defining the schedule.
399
+ * @param input - The input data for the task, including global input fields.
400
+ * @param options - Optional configuration for this task run.
401
+ * @returns A promise that resolves with the cron workflow details.
354
402
  */
355
- runNoWait(input: I, options?: RunOpts): Promise<WorkflowRunRef<O>>;
356
- runNoWait(input: I[], options?: RunOpts): Promise<WorkflowRunRef<O>[]>;
403
+ cron(name: string, expression: string, input: I & GlobalInput, options?: RunOpts): Promise<CronWorkflows>;
404
+ /** Returns the underlying task definition for this declaration. */
357
405
  get taskDef(): CreateWorkflowTaskOpts<any, any>;
358
406
  }
359
407
  /**