@upstash/qstash 2.7.5 → 2.7.6

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/README.md +12 -4
  2. package/chunk-B3NB4QLV.mjs +2920 -0
  3. package/chunk-IJ3475FO.mjs +403 -0
  4. package/chunk-IJ5AEYLN.js +1 -0
  5. package/chunk-NMSGEGBP.js +403 -0
  6. package/chunk-S7JMIMW4.mjs +0 -0
  7. package/chunk-WQZ4U6LJ.js +2920 -0
  8. package/{dist/workflow/index.d.mts → client-aUVEwn93.d.mts} +868 -800
  9. package/{dist/nextjs/index.d.mts → client-aUVEwn93.d.ts} +871 -743
  10. package/cloudflare.d.mts +33 -0
  11. package/cloudflare.d.ts +33 -0
  12. package/cloudflare.js +37 -0
  13. package/cloudflare.mjs +37 -0
  14. package/h3.d.mts +17 -0
  15. package/h3.d.ts +17 -0
  16. package/h3.js +10 -0
  17. package/h3.mjs +10 -0
  18. package/hono.d.mts +25 -0
  19. package/hono.d.ts +25 -0
  20. package/hono.js +22 -0
  21. package/hono.mjs +22 -0
  22. package/index.d.mts +54 -0
  23. package/index.d.ts +54 -0
  24. package/index.js +41 -0
  25. package/index.mjs +41 -0
  26. package/nextjs.d.mts +38 -0
  27. package/nextjs.d.ts +38 -0
  28. package/nextjs.js +178 -0
  29. package/nextjs.mjs +178 -0
  30. package/nuxt.d.mts +12 -0
  31. package/nuxt.d.ts +12 -0
  32. package/nuxt.js +11 -0
  33. package/nuxt.mjs +11 -0
  34. package/package.json +1 -1
  35. package/solidjs.d.mts +22 -0
  36. package/solidjs.d.ts +22 -0
  37. package/solidjs.js +56 -0
  38. package/solidjs.mjs +56 -0
  39. package/svelte.d.mts +24 -0
  40. package/svelte.d.ts +24 -0
  41. package/svelte.js +53 -0
  42. package/svelte.mjs +53 -0
  43. package/workflow.d.mts +2 -0
  44. package/workflow.d.ts +2 -0
  45. package/workflow.js +18 -0
  46. package/workflow.mjs +18 -0
  47. package/dist/base/index.d.mts +0 -1279
  48. package/dist/base/index.mjs +0 -2
  49. package/dist/cloudflare/index.d.mts +0 -1652
  50. package/dist/cloudflare/index.mjs +0 -11
  51. package/dist/h3/index.d.mts +0 -1637
  52. package/dist/h3/index.mjs +0 -11
  53. package/dist/hono/index.d.mts +0 -1645
  54. package/dist/hono/index.mjs +0 -11
  55. package/dist/nextjs/index.mjs +0 -11
  56. package/dist/solidjs/index.d.mts +0 -1642
  57. package/dist/solidjs/index.mjs +0 -11
  58. package/dist/svelte/index.d.mts +0 -1644
  59. package/dist/svelte/index.mjs +0 -11
  60. package/dist/workflow/index.mjs +0 -11
@@ -1,5 +1,66 @@
1
1
  import { Ok, Err } from 'neverthrow';
2
2
 
3
+ /**
4
+ * Necessary to verify the signature of a request.
5
+ */
6
+ type ReceiverConfig = {
7
+ /**
8
+ * The current signing key. Get it from `https://console.upstash.com/qstash
9
+ */
10
+ currentSigningKey: string;
11
+ /**
12
+ * The next signing key. Get it from `https://console.upstash.com/qstash
13
+ */
14
+ nextSigningKey: string;
15
+ };
16
+ type VerifyRequest = {
17
+ /**
18
+ * The signature from the `upstash-signature` header.
19
+ */
20
+ signature: string;
21
+ /**
22
+ * The raw request body.
23
+ */
24
+ body: string;
25
+ /**
26
+ * URL of the endpoint where the request was sent to.
27
+ *
28
+ * Omit empty to disable checking the url.
29
+ */
30
+ url?: string;
31
+ /**
32
+ * Number of seconds to tolerate when checking `nbf` and `exp` claims, to deal with small clock differences among different servers
33
+ *
34
+ * @default 0
35
+ */
36
+ clockTolerance?: number;
37
+ };
38
+ declare class SignatureError extends Error {
39
+ constructor(message: string);
40
+ }
41
+ /**
42
+ * Receiver offers a simple way to verify the signature of a request.
43
+ */
44
+ declare class Receiver {
45
+ private readonly currentSigningKey;
46
+ private readonly nextSigningKey;
47
+ constructor(config: ReceiverConfig);
48
+ /**
49
+ * Verify the signature of a request.
50
+ *
51
+ * Tries to verify the signature with the current signing key.
52
+ * If that fails, maybe because you have rotated the keys recently, it will
53
+ * try to verify the signature with the next signing key.
54
+ *
55
+ * If that fails, the signature is invalid and a `SignatureError` is thrown.
56
+ */
57
+ verify(request: VerifyRequest): Promise<boolean>;
58
+ /**
59
+ * Verify signature with a specific signing key
60
+ */
61
+ private verifyWithKey;
62
+ }
63
+
3
64
  type State = "CREATED" | "ACTIVE" | "DELIVERED" | "ERROR" | "RETRY" | "FAILED";
4
65
  type HTTPMethods = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
5
66
  type Event = {
@@ -15,14 +76,69 @@ type Event = {
15
76
  header?: Record<string, string>;
16
77
  body?: string;
17
78
  };
79
+ type EventPayload = Omit<Event, "urlGroup"> & {
80
+ topicName: string;
81
+ };
82
+ type GetEventsPayload = {
83
+ cursor?: number;
84
+ events: EventPayload[];
85
+ };
86
+ type WithCursor<T> = T & {
87
+ cursor?: number;
88
+ };
18
89
  type BodyInit = Blob | FormData | URLSearchParams | ReadableStream<Uint8Array> | string;
19
90
  type HeadersInit = Headers | Record<string, string> | [string, string][] | IterableIterator<[string, string]>;
91
+ type RequestOptions = RequestInit & {
92
+ backend?: string;
93
+ };
94
+ type ChatRateLimit = {
95
+ "limit-requests": string | null;
96
+ "limit-tokens": string | null;
97
+ "remaining-requests": string | null;
98
+ "remaining-tokens": string | null;
99
+ "reset-requests": string | null;
100
+ "reset-tokens": string | null;
101
+ };
102
+ type RateLimit = {
103
+ limit: string | null;
104
+ remaining: string | null;
105
+ reset: string | null;
106
+ };
20
107
 
21
108
  type ProviderReturnType = {
22
109
  owner: "upstash" | "openai" | "custom";
23
110
  baseUrl: string;
24
111
  token: string;
25
112
  };
113
+ type AnalyticsConfig = {
114
+ name: "helicone";
115
+ token: string;
116
+ };
117
+ type AnalyticsSetup = {
118
+ baseURL?: string;
119
+ defaultHeaders?: Record<string, string | undefined>;
120
+ };
121
+ declare const setupAnalytics: (analytics: AnalyticsConfig | undefined, providerApiKey: string, providerBaseUrl?: string, provider?: "openai" | "upstash" | "custom") => AnalyticsSetup;
122
+ declare const upstash: () => {
123
+ owner: "upstash";
124
+ baseUrl: "https://qstash.upstash.io/llm";
125
+ token: string;
126
+ };
127
+ declare const openai: ({ token, }: {
128
+ token: string;
129
+ }) => {
130
+ owner: "openai";
131
+ baseUrl: "https://api.openai.com";
132
+ token: string;
133
+ };
134
+ declare const custom: ({ baseUrl, token, }: {
135
+ token: string;
136
+ baseUrl: string;
137
+ }) => {
138
+ owner: "custom";
139
+ baseUrl: string;
140
+ token: string;
141
+ };
26
142
 
27
143
  type ChatCompletionMessage = {
28
144
  role: "system" | "assistant" | "user";
@@ -191,64 +307,6 @@ type RetryConfig = false | {
191
307
  backoff?: (retryCount: number) => number;
192
308
  };
193
309
 
194
- /**
195
- * Necessary to verify the signature of a request.
196
- */
197
- type ReceiverConfig = {
198
- /**
199
- * The current signing key. Get it from `https://console.upstash.com/qstash
200
- */
201
- currentSigningKey: string;
202
- /**
203
- * The next signing key. Get it from `https://console.upstash.com/qstash
204
- */
205
- nextSigningKey: string;
206
- };
207
- type VerifyRequest = {
208
- /**
209
- * The signature from the `upstash-signature` header.
210
- */
211
- signature: string;
212
- /**
213
- * The raw request body.
214
- */
215
- body: string;
216
- /**
217
- * URL of the endpoint where the request was sent to.
218
- *
219
- * Omit empty to disable checking the url.
220
- */
221
- url?: string;
222
- /**
223
- * Number of seconds to tolerate when checking `nbf` and `exp` claims, to deal with small clock differences among different servers
224
- *
225
- * @default 0
226
- */
227
- clockTolerance?: number;
228
- };
229
- /**
230
- * Receiver offers a simple way to verify the signature of a request.
231
- */
232
- declare class Receiver {
233
- private readonly currentSigningKey;
234
- private readonly nextSigningKey;
235
- constructor(config: ReceiverConfig);
236
- /**
237
- * Verify the signature of a request.
238
- *
239
- * Tries to verify the signature with the current signing key.
240
- * If that fails, maybe because you have rotated the keys recently, it will
241
- * try to verify the signature with the next signing key.
242
- *
243
- * If that fails, the signature is invalid and a `SignatureError` is thrown.
244
- */
245
- verify(request: VerifyRequest): Promise<boolean>;
246
- /**
247
- * Verify signature with a specific signing key
248
- */
249
- private verifyWithKey;
250
- }
251
-
252
310
  type Message = {
253
311
  /**
254
312
  * A unique identifier for this message.
@@ -325,6 +383,9 @@ type Message = {
325
383
  */
326
384
  callerIp?: string;
327
385
  };
386
+ type MessagePayload = Omit<Message, "urlGroup"> & {
387
+ topicName: string;
388
+ };
328
389
  declare class Messages {
329
390
  private readonly http;
330
391
  constructor(http: Requester);
@@ -754,965 +815,972 @@ declare class UrlGroups {
754
815
  delete(name: string): Promise<void>;
755
816
  }
756
817
 
757
- type ClientConfig = {
818
+ /**
819
+ * Base class outlining steps. Basically, each step kind (run/sleep/sleepUntil)
820
+ * should have two methods: getPlanStep & getResultStep.
821
+ *
822
+ * getPlanStep works the same way for all so it's implemented here.
823
+ * The different step types will implement their own getResultStep method.
824
+ */
825
+ declare abstract class BaseLazyStep<TResult = unknown> {
826
+ readonly stepName: string;
827
+ abstract readonly stepType: StepType;
828
+ constructor(stepName: string);
758
829
  /**
759
- * Url of the QStash api server.
760
- *
761
- * This is only used for testing.
830
+ * plan step to submit when step will run parallel with other
831
+ * steps (parallel call state `first`)
762
832
  *
763
- * @default "https://qstash.upstash.io"
764
- */
765
- baseUrl?: string;
766
- /**
767
- * The authorization token from the upstash console.
833
+ * @param concurrent number of steps running parallel
834
+ * @param targetStep target step id corresponding to this step
835
+ * @returns
768
836
  */
769
- token: string;
837
+ abstract getPlanStep(concurrent: number, targetStep: number): Step<undefined>;
770
838
  /**
771
- * Configure how the client should retry requests.
839
+ * result step to submit after the step executes. Used in single step executions
840
+ * and when a plan step executes in parallel executions (parallel call state `partial`).
841
+ *
842
+ * @param concurrent
843
+ * @param stepId
772
844
  */
773
- retry?: RetryConfig;
845
+ abstract getResultStep(concurrent: number, stepId: number): Promise<Step<TResult>>;
846
+ }
847
+
848
+ declare const LOG_LEVELS: readonly ["DEBUG", "INFO", "SUBMIT", "WARN", "ERROR"];
849
+ type LogLevel = (typeof LOG_LEVELS)[number];
850
+ type ChatLogEntry = {
851
+ timestamp: number;
852
+ workflowRunId: string;
853
+ logLevel: LogLevel;
854
+ eventType: "ENDPOINT_START" | "SUBMIT_THIRD_PARTY_RESULT" | "CREATE_CONTEXT" | "SUBMIT_FIRST_INVOCATION" | "RUN_SINGLE" | "RUN_PARALLEL" | "SUBMIT_STEP" | "SUBMIT_CLEANUP" | "RESPONSE_WORKFLOW" | "RESPONSE_DEFAULT" | "ERROR";
855
+ details: unknown;
774
856
  };
775
- type PublishBatchRequest<TBody = BodyInit> = PublishRequest<TBody> & {
776
- queueName?: string;
857
+ type WorkflowLoggerOptions = {
858
+ logLevel: LogLevel;
859
+ logOutput: "console";
777
860
  };
778
- type PublishRequest<TBody = BodyInit> = {
861
+ declare class WorkflowLogger {
862
+ private logs;
863
+ private options;
864
+ private workflowRunId?;
865
+ constructor(options: WorkflowLoggerOptions);
866
+ log(level: LogLevel, eventType: ChatLogEntry["eventType"], details?: unknown): Promise<void>;
867
+ setWorkflowRunId(workflowRunId: string): void;
868
+ private writeToConsole;
869
+ private shouldLog;
870
+ static getLogger(verbose?: boolean | WorkflowLogger): WorkflowLogger | undefined;
871
+ }
872
+
873
+ declare class AutoExecutor {
874
+ private context;
875
+ private promises;
876
+ private activeLazyStepList?;
877
+ private debug?;
878
+ private readonly nonPlanStepCount;
879
+ private readonly steps;
880
+ private indexInCurrentList;
881
+ stepCount: number;
882
+ planStepCount: number;
883
+ protected executingStep: string | false;
884
+ constructor(context: WorkflowContext, steps: Step[], debug?: WorkflowLogger);
779
885
  /**
780
- * The message to send.
886
+ * Adds the step function to the list of step functions to run in
887
+ * parallel. After adding the function, defers the execution, so
888
+ * that if there is another step function to be added, it's also
889
+ * added.
781
890
  *
782
- * This can be anything, but please set the `Content-Type` header accordingly.
891
+ * After all functions are added, list of functions are executed.
892
+ * If there is a single function, it's executed by itself. If there
893
+ * are multiple, they are run in parallel.
783
894
  *
784
- * You can leave this empty if you want to send a message with no body.
785
- */
786
- body?: TBody;
787
- /**
788
- * Optionally send along headers with the message.
789
- * These headers will be sent to your destination.
895
+ * If a function is already executing (this.executingStep), this
896
+ * means that there is a nested step which is not allowed. In this
897
+ * case, addStep throws QStashWorkflowError.
790
898
  *
791
- * We highly recommend sending a `Content-Type` header along, as this will help your destination
792
- * server to understand the content of the message.
899
+ * @param stepInfo step plan to add
900
+ * @returns result of the step function
793
901
  */
794
- headers?: HeadersInit;
902
+ addStep<TResult>(stepInfo: BaseLazyStep<TResult>): Promise<TResult>;
795
903
  /**
796
- * Optionally delay the delivery of this message.
904
+ * Wraps a step function to set this.executingStep to step name
905
+ * before running and set this.executingStep to False after execution
906
+ * ends.
797
907
  *
798
- * In seconds.
908
+ * this.executingStep allows us to detect nested steps which are not
909
+ * allowed.
799
910
  *
800
- * @default undefined
911
+ * @param stepName name of the step being wrapped
912
+ * @param stepFunction step function to wrap
913
+ * @returns wrapped step function
801
914
  */
802
- delay?: Duration | number;
915
+ wrapStep<TResult = unknown>(stepName: string, stepFunction: StepFunction<TResult>): TResult | Promise<TResult>;
803
916
  /**
804
- * Optionally set the absolute delay of this message.
805
- * This will override the delay option.
806
- * The message will not delivered until the specified time.
807
- *
808
- * Unix timestamp in seconds.
917
+ * Executes a step:
918
+ * - If the step result is available in the steps, returns the result
919
+ * - If the result is not avaiable, runs the function
920
+ * - Sends the result to QStash
809
921
  *
810
- * @default undefined
922
+ * @param lazyStep lazy step to execute
923
+ * @returns step result
811
924
  */
812
- notBefore?: number;
925
+ protected runSingle<TResult>(lazyStep: BaseLazyStep<TResult>): Promise<TResult>;
813
926
  /**
814
- * Provide a unique id for deduplication. This id will be used to detect duplicate messages.
815
- * If a duplicate message is detected, the request will be accepted but not enqueued.
816
- *
817
- * We store deduplication ids for 90 days. Afterwards it is possible that the message with the
818
- * same deduplication id is delivered again.
819
- *
820
- * When scheduling a message, the deduplication happens before the schedule is created.
927
+ * Runs steps in parallel.
821
928
  *
822
- * @default undefined
929
+ * @param stepName parallel step name
930
+ * @param stepFunctions list of async functions to run in parallel
931
+ * @returns results of the functions run in parallel
823
932
  */
824
- deduplicationId?: string;
933
+ protected runParallel<TResults extends unknown[]>(parallelSteps: {
934
+ [K in keyof TResults]: BaseLazyStep<TResults[K]>;
935
+ }): Promise<TResults>;
825
936
  /**
826
- * If true, the message content will get hashed and used as deduplication id.
827
- * If a duplicate message is detected, the request will be accepted but not enqueued.
828
- *
829
- * The content based hash includes the following values:
830
- * - All headers, except Upstash-Authorization, this includes all headers you are sending.
831
- * - The entire raw request body The destination from the url path
937
+ * Determines the parallel call state
832
938
  *
833
- * We store deduplication ids for 90 days. Afterwards it is possible that the message with the
834
- * same deduplication id is delivered again.
939
+ * First filters the steps to get the steps which are after `initialStepCount` parameter.
835
940
  *
836
- * When scheduling a message, the deduplication happens before the schedule is created.
941
+ * Depending on the remaining steps, decides the parallel state:
942
+ * - "first": If there are no steps
943
+ * - "last" If there are equal to or more than `2 * parallelStepCount`. We multiply by two
944
+ * because each step in a parallel execution will have 2 steps: a plan step and a result
945
+ * step.
946
+ * - "partial": If the last step is a plan step
947
+ * - "discard": If the last step is not a plan step. This means that the parallel execution
948
+ * is in progress (there are still steps to run) and one step has finished and submitted
949
+ * its result to QStash
837
950
  *
838
- * @default false
951
+ * @param parallelStepCount number of steps to run in parallel
952
+ * @param initialStepCount steps after the parallel invocation
953
+ * @returns parallel call state
839
954
  */
840
- contentBasedDeduplication?: boolean;
955
+ protected getParallelCallState(parallelStepCount: number, initialStepCount: number): ParallelCallState;
841
956
  /**
842
- * In case your destination server is unavaialble or returns a status code outside of the 200-299
843
- * range, we will retry the request after a certain amount of time.
844
- *
845
- * Configure how many times you would like the delivery to be retried up to the maxRetries limit
846
- * defined in your plan.
957
+ * sends the steps to QStash as batch
847
958
  *
848
- * @default 3
959
+ * @param steps steps to send
849
960
  */
850
- retries?: number;
961
+ private submitStepsToQStash;
851
962
  /**
852
- * Use a failure callback url to handle messages that could not be delivered.
853
- *
854
- * The failure callback url must be publicly accessible
963
+ * Get the promise by executing the lazt steps list. If there is a single
964
+ * step, we call `runSingle`. Otherwise `runParallel` is called.
855
965
  *
856
- * @default undefined
966
+ * @param lazyStepList steps list to execute
967
+ * @returns promise corresponding to the execution
857
968
  */
858
- failureCallback?: string;
969
+ private getExecutionPromise;
859
970
  /**
860
- * The method to use when sending a request to your API
861
- *
862
- * @default `POST`
971
+ * @param lazyStepList steps we executed
972
+ * @param result result of the promise from `getExecutionPromise`
973
+ * @param index index of the current step
974
+ * @returns result[index] if lazyStepList > 1, otherwise result
863
975
  */
864
- method?: HTTPMethods;
976
+ private static getResult;
977
+ private deferExecution;
978
+ }
979
+
980
+ /**
981
+ * QStash workflow context
982
+ *
983
+ * See the docs for fields and methods https://upstash.com/docs/qstash/workflows/basics/context
984
+ */
985
+ declare class WorkflowContext<TInitialPayload = unknown> {
986
+ protected readonly executor: AutoExecutor;
987
+ protected readonly steps: Step[];
865
988
  /**
866
- * The HTTP timeout value to use while calling the destination URL.
867
- * When a timeout is specified, it will be used instead of the maximum timeout
868
- * value permitted by the QStash plan. It is useful in scenarios, where a message
869
- * should be delivered with a shorter timeout.
989
+ * QStash client of the workflow
870
990
  *
871
- * In seconds.
991
+ * Can be overwritten by passing `qstashClient` parameter in `serve`:
872
992
  *
873
- * @default undefined
993
+ * ```ts
994
+ * import { Client } from "@upstash/qstash"
995
+ *
996
+ * export const POST = serve(
997
+ * async (context) => {
998
+ * ...
999
+ * },
1000
+ * {
1001
+ * qstashClient: new Client({...})
1002
+ * }
1003
+ * )
1004
+ * ```
874
1005
  */
875
- timeout?: Duration | number;
876
- } & ({
1006
+ readonly qstashClient: WorkflowClient;
877
1007
  /**
878
- * The url where the message should be sent to.
1008
+ * Run id of the workflow
879
1009
  */
880
- url: string;
881
- urlGroup?: never;
882
- api?: never;
883
- topic?: never;
1010
+ readonly workflowRunId: string;
884
1011
  /**
885
- * Use a callback url to forward the response of your destination server to your callback url.
1012
+ * URL of the workflow
886
1013
  *
887
- * The callback url must be publicly accessible
1014
+ * Can be overwritten by passing a `url` parameter in `serve`:
888
1015
  *
889
- * @default undefined
890
- */
891
- callback?: string;
892
- } | {
893
- url?: never;
894
- /**
895
- * The url group the message should be sent to.
1016
+ * ```ts
1017
+ * export const POST = serve(
1018
+ * async (context) => {
1019
+ * ...
1020
+ * },
1021
+ * {
1022
+ * url: "new-url-value"
1023
+ * }
1024
+ * )
1025
+ * ```
896
1026
  */
897
- urlGroup: string;
898
- api?: never;
899
- topic?: never;
1027
+ readonly url: string;
900
1028
  /**
901
- * Use a callback url to forward the response of your destination server to your callback url.
1029
+ * URL to call in case of workflow failure with QStash failure callback
902
1030
  *
903
- * The callback url must be publicly accessible
1031
+ * https://upstash.com/docs/qstash/features/callbacks#what-is-a-failure-callback
904
1032
  *
905
- * @default undefined
906
- */
907
- callback?: string;
908
- } | {
909
- url?: string;
910
- urlGroup?: never;
911
- /**
912
- * The api endpoint the request should be sent to.
1033
+ * Can be overwritten by passing a `failureUrl` parameter in `serve`:
1034
+ *
1035
+ * ```ts
1036
+ * export const POST = serve(
1037
+ * async (context) => {
1038
+ * ...
1039
+ * },
1040
+ * {
1041
+ * failureUrl: "new-url-value"
1042
+ * }
1043
+ * )
1044
+ * ```
913
1045
  */
914
- api: {
915
- name: "llm";
916
- provider?: ProviderReturnType;
917
- analytics?: {
918
- name: "helicone";
919
- token: string;
920
- };
921
- };
1046
+ readonly failureUrl?: string;
922
1047
  /**
923
- * Use a callback url to forward the response of your destination server to your callback url.
1048
+ * Payload of the request which started the workflow.
924
1049
  *
925
- * The callback url must be publicly accessible
1050
+ * To specify its type, you can define `serve` as follows:
926
1051
  *
927
- * @default undefined
1052
+ * ```ts
1053
+ * // set requestPayload type to MyPayload:
1054
+ * export const POST = serve<MyPayload>(
1055
+ * async (context) => {
1056
+ * ...
1057
+ * }
1058
+ * )
1059
+ * ```
1060
+ *
1061
+ * By default, `serve` tries to apply `JSON.parse` to the request payload.
1062
+ * If your payload is encoded in a format other than JSON, you can utilize
1063
+ * the `initialPayloadParser` parameter:
1064
+ *
1065
+ * ```ts
1066
+ * export const POST = serve<MyPayload>(
1067
+ * async (context) => {
1068
+ * ...
1069
+ * },
1070
+ * {
1071
+ * initialPayloadParser: (initialPayload) => {return doSomething(initialPayload)}
1072
+ * }
1073
+ * )
1074
+ * ```
928
1075
  */
929
- callback: string;
930
- topic?: never;
931
- } | {
932
- url?: never;
933
- urlGroup?: never;
934
- api: never;
1076
+ readonly requestPayload: TInitialPayload;
935
1077
  /**
936
- * Deprecated. The topic the message should be sent to. Same as urlGroup
1078
+ * headers of the initial request
937
1079
  */
938
- topic?: string;
1080
+ readonly headers: Headers;
939
1081
  /**
940
- * Use a callback url to forward the response of your destination server to your callback url.
1082
+ * initial payload as a raw string
1083
+ */
1084
+ readonly rawInitialPayload: string;
1085
+ /**
1086
+ * Map of environment variables and their values.
941
1087
  *
942
- * The callback url must be publicly accessible
1088
+ * Can be set using the `env` option of serve:
943
1089
  *
944
- * @default undefined
1090
+ * ```ts
1091
+ * export const POST = serve<MyPayload>(
1092
+ * async (context) => {
1093
+ * const key = context.env["API_KEY"];
1094
+ * },
1095
+ * {
1096
+ * env: {
1097
+ * "API_KEY": "*****";
1098
+ * }
1099
+ * }
1100
+ * )
1101
+ * ```
1102
+ *
1103
+ * Default value is set to `process.env`.
945
1104
  */
946
- callback?: string;
947
- });
948
- type EventsRequest = {
949
- cursor?: number;
950
- filter?: EventsRequestFilter;
951
- };
952
- type EventsRequestFilter = {
953
- messageId?: string;
954
- state?: State;
955
- url?: string;
956
- urlGroup?: string;
957
- topicName?: string;
958
- api?: string;
959
- scheduleId?: string;
960
- queueName?: string;
961
- fromDate?: number;
962
- toDate?: number;
963
- count?: number;
964
- };
965
- type GetEventsResponse = {
966
- cursor?: number;
967
- events: Event[];
968
- };
969
- type QueueRequest = {
970
- queueName?: string;
971
- };
972
- declare class Client {
973
- http: Requester;
974
- private token;
975
- constructor(config: ClientConfig);
1105
+ readonly env: Record<string, string | undefined>;
1106
+ constructor({ qstashClient, workflowRunId, headers, steps, url, failureUrl, debug, initialPayload, rawInitialPayload, env, }: {
1107
+ qstashClient: WorkflowClient;
1108
+ workflowRunId: string;
1109
+ headers: Headers;
1110
+ steps: Step[];
1111
+ url: string;
1112
+ failureUrl?: string;
1113
+ debug?: WorkflowLogger;
1114
+ initialPayload: TInitialPayload;
1115
+ rawInitialPayload?: string;
1116
+ env?: Record<string, string | undefined>;
1117
+ });
976
1118
  /**
977
- * Access the urlGroup API.
1119
+ * Executes a workflow step
978
1120
  *
979
- * Create, read, update or delete urlGroups.
980
- */
981
- get urlGroups(): UrlGroups;
982
- /**
983
- * Deprecated. Use urlGroups instead.
1121
+ * ```typescript
1122
+ * const result = await context.run("step 1", () => {
1123
+ * return "result"
1124
+ * })
1125
+ * ```
984
1126
  *
985
- * Access the topic API.
1127
+ * Can also be called in parallel and the steps will be executed
1128
+ * simulatenously:
986
1129
  *
987
- * Create, read, update or delete topics.
1130
+ * ```typescript
1131
+ * const [result1, result2] = await Promise.all([
1132
+ * context.run("step 1", () => {
1133
+ * return "result1"
1134
+ * })
1135
+ * context.run("step 2", async () => {
1136
+ * return await fetchResults()
1137
+ * })
1138
+ * ])
1139
+ * ```
1140
+ *
1141
+ * @param stepName name of the step
1142
+ * @param stepFunction step function to be executed
1143
+ * @returns result of the step function
988
1144
  */
989
- get topics(): UrlGroups;
1145
+ run<TResult>(stepName: string, stepFunction: StepFunction<TResult>): Promise<TResult>;
990
1146
  /**
991
- * Access the dlq API.
1147
+ * Stops the execution for the duration provided.
992
1148
  *
993
- * List or remove messages from the DLQ.
1149
+ * @param stepName
1150
+ * @param duration sleep duration in seconds
1151
+ * @returns undefined
994
1152
  */
995
- get dlq(): DLQ;
1153
+ sleep(stepName: string, duration: number): Promise<void>;
996
1154
  /**
997
- * Access the message API.
1155
+ * Stops the execution until the date time provided.
998
1156
  *
999
- * Read or cancel messages.
1157
+ * @param stepName
1158
+ * @param datetime time to sleep until. Can be provided as a number (in unix seconds),
1159
+ * as a Date object or a string (passed to `new Date(datetimeString)`)
1160
+ * @returns undefined
1000
1161
  */
1001
- get messages(): Messages;
1162
+ sleepUntil(stepName: string, datetime: Date | string | number): Promise<void>;
1002
1163
  /**
1003
- * Access the schedule API.
1164
+ * Makes a third party call through QStash in order to make a
1165
+ * network call without consuming any runtime.
1004
1166
  *
1005
- * Create, read or delete schedules.
1167
+ * ```ts
1168
+ * const postResult = await context.call<string>(
1169
+ * "post call step",
1170
+ * `https://www.some-endpoint.com/api`,
1171
+ * "POST",
1172
+ * "my-payload"
1173
+ * );
1174
+ * ```
1175
+ *
1176
+ * tries to parse the result of the request as JSON. If it's
1177
+ * not a JSON which can be parsed, simply returns the response
1178
+ * body as it is.
1179
+ *
1180
+ * @param stepName
1181
+ * @param url url to call
1182
+ * @param method call method
1183
+ * @param body call body
1184
+ * @param headers call headers
1185
+ * @returns call result (parsed as JSON if possible)
1006
1186
  */
1007
- get schedules(): Schedules;
1187
+ call<TResult = unknown, TBody = unknown>(stepName: string, url: string, method: HTTPMethods, body?: TBody, headers?: Record<string, string>): Promise<TResult>;
1008
1188
  /**
1009
- * Access the workflow API.
1010
- *
1011
- * cancel workflows.
1189
+ * Adds steps to the executor. Needed so that it can be overwritten in
1190
+ * DisabledWorkflowContext.
1012
1191
  */
1013
- get workflow(): Workflow;
1192
+ protected addStep<TResult = unknown>(step: BaseLazyStep<TResult>): Promise<TResult>;
1193
+ }
1194
+ /**
1195
+ * Workflow context which throws QStashWorkflowAbort before running the steps.
1196
+ *
1197
+ * Used for making a dry run before running any steps to check authentication.
1198
+ *
1199
+ * Consider an endpoint like this:
1200
+ * ```ts
1201
+ * export const POST = serve({
1202
+ * routeFunction: context => {
1203
+ * if (context.headers.get("authentication") !== "Bearer secretPassword") {
1204
+ * console.error("Authentication failed.");
1205
+ * return;
1206
+ * }
1207
+ *
1208
+ * // ...
1209
+ * }
1210
+ * })
1211
+ * ```
1212
+ *
1213
+ * the serve method will first call the routeFunction with an DisabledWorkflowContext.
1214
+ * Here is the action we take in different cases
1215
+ * - "step-found": we will run the workflow related sections of `serve`.
1216
+ * - "run-ended": simply return success and end the workflow
1217
+ * - error: returns 500.
1218
+ */
1219
+ declare class DisabledWorkflowContext<TInitialPayload = unknown> extends WorkflowContext<TInitialPayload> {
1220
+ private static readonly disabledMessage;
1014
1221
  /**
1015
- * Access the queue API.
1222
+ * overwrite the WorkflowContext.addStep method to always raise QStashWorkflowAbort
1223
+ * error in order to stop the execution whenever we encounter a step.
1016
1224
  *
1017
- * Create, read, update or delete queues.
1225
+ * @param _step
1018
1226
  */
1019
- queue(request?: QueueRequest): Queue;
1227
+ protected addStep<TResult = unknown>(_step: BaseLazyStep<TResult>): Promise<TResult>;
1020
1228
  /**
1021
- * Access the Chat API
1229
+ * copies the passed context to create a DisabledWorkflowContext. Then, runs the
1230
+ * route function with the new context.
1022
1231
  *
1023
- * Call the create or prompt methods
1232
+ * - returns "run-ended" if there are no steps found or
1233
+ * if the auth failed and user called `return`
1234
+ * - returns "step-found" if DisabledWorkflowContext.addStep is called.
1235
+ * - if there is another error, returns the error.
1236
+ *
1237
+ * @param routeFunction
1024
1238
  */
1025
- chat(): Chat;
1026
- publish<TRequest extends PublishRequest>(request: TRequest): Promise<PublishResponse<TRequest>>;
1239
+ static tryAuthentication<TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, context: WorkflowContext<TInitialPayload>): Promise<Ok<"step-found" | "run-ended", never> | Err<never, Error>>;
1240
+ }
1241
+
1242
+ /**
1243
+ * Interface for Client with required methods
1244
+ *
1245
+ * Neeeded to resolve import issues
1246
+ */
1247
+ type WorkflowClient = {
1248
+ batchJSON: InstanceType<typeof Client>["batchJSON"];
1249
+ publishJSON: InstanceType<typeof Client>["publishJSON"];
1250
+ http: InstanceType<typeof Client>["http"];
1251
+ };
1252
+ /**
1253
+ * Interface for Receiver with required methods
1254
+ *
1255
+ * Neeeded to resolve import issues
1256
+ */
1257
+ type WorkflowReceiver = {
1258
+ verify: InstanceType<typeof Receiver>["verify"];
1259
+ };
1260
+ declare const StepTypes: readonly ["Initial", "Run", "SleepFor", "SleepUntil", "Call"];
1261
+ type StepType = (typeof StepTypes)[number];
1262
+ type ThirdPartyCallFields<TBody = unknown> = {
1027
1263
  /**
1028
- * publishJSON is a utility wrapper around `publish` that automatically serializes the body
1029
- * and sets the `Content-Type` header to `application/json`.
1264
+ * Third party call URL. Set when context.call is used.
1030
1265
  */
1031
- publishJSON<TBody = unknown, TRequest extends PublishRequest<TBody> = PublishRequest<TBody>>(request: TRequest): Promise<PublishResponse<TRequest>>;
1266
+ callUrl: string;
1032
1267
  /**
1033
- * Batch publish messages to QStash.
1268
+ * Third party call method. Set when context.call is used.
1034
1269
  */
1035
- batch(request: PublishBatchRequest[]): Promise<PublishResponse<PublishRequest>[]>;
1270
+ callMethod: HTTPMethods;
1036
1271
  /**
1037
- * Batch publish messages to QStash, serializing each body to JSON.
1272
+ * Third party call body. Set when context.call is used.
1038
1273
  */
1039
- batchJSON<TBody = unknown, TRequest extends PublishBatchRequest<TBody> = PublishBatchRequest<TBody>>(request: TRequest[]): Promise<PublishResponse<TRequest>[]>;
1274
+ callBody: TBody;
1040
1275
  /**
1041
- * Retrieve your logs.
1042
- *
1043
- * The logs endpoint is paginated and returns only 100 logs at a time.
1044
- * If you want to receive more logs, you can use the cursor to paginate.
1045
- *
1046
- * The cursor is a unix timestamp with millisecond precision
1047
- *
1048
- * @example
1049
- * ```ts
1050
- * let cursor = Date.now()
1051
- * const logs: Log[] = []
1052
- * while (cursor > 0) {
1053
- * const res = await qstash.logs({ cursor })
1054
- * logs.push(...res.logs)
1055
- * cursor = res.cursor ?? 0
1056
- * }
1057
- * ```
1276
+ * Third party call headers. Set when context.call is used.
1058
1277
  */
1059
- events(request?: EventsRequest): Promise<GetEventsResponse>;
1060
- }
1061
- type PublishToApiResponse = {
1062
- messageId: string;
1063
- };
1064
- type PublishToUrlResponse = PublishToApiResponse & {
1065
- url: string;
1066
- deduplicated?: boolean;
1278
+ callHeaders: Record<string, string>;
1067
1279
  };
1068
- type PublishToUrlGroupsResponse = PublishToUrlResponse[];
1069
- type PublishResponse<TRequest> = TRequest extends {
1070
- url: string;
1071
- } ? PublishToUrlResponse : TRequest extends {
1072
- urlGroup: string;
1073
- } ? PublishToUrlGroupsResponse : PublishToApiResponse;
1074
-
1075
- /**
1076
- * Base class outlining steps. Basically, each step kind (run/sleep/sleepUntil)
1077
- * should have two methods: getPlanStep & getResultStep.
1078
- *
1079
- * getPlanStep works the same way for all so it's implemented here.
1080
- * The different step types will implement their own getResultStep method.
1081
- */
1082
- declare abstract class BaseLazyStep<TResult = unknown> {
1083
- readonly stepName: string;
1084
- abstract readonly stepType: StepType;
1085
- constructor(stepName: string);
1280
+ type Step<TResult = unknown, TBody = unknown> = {
1086
1281
  /**
1087
- * plan step to submit when step will run parallel with other
1088
- * steps (parallel call state `first`)
1089
- *
1090
- * @param concurrent number of steps running parallel
1091
- * @param targetStep target step id corresponding to this step
1092
- * @returns
1282
+ * index of the step
1093
1283
  */
1094
- abstract getPlanStep(concurrent: number, targetStep: number): Step<undefined>;
1284
+ stepId: number;
1095
1285
  /**
1096
- * result step to submit after the step executes. Used in single step executions
1097
- * and when a plan step executes in parallel executions (parallel call state `partial`).
1098
- *
1099
- * @param concurrent
1100
- * @param stepId
1286
+ * name of the step
1101
1287
  */
1102
- abstract getResultStep(concurrent: number, stepId: number): Promise<Step<TResult>>;
1103
- }
1104
-
1105
- declare const LOG_LEVELS: readonly ["DEBUG", "INFO", "SUBMIT", "WARN", "ERROR"];
1106
- type LogLevel = (typeof LOG_LEVELS)[number];
1107
- type ChatLogEntry = {
1108
- timestamp: number;
1109
- workflowRunId: string;
1110
- logLevel: LogLevel;
1111
- eventType: "ENDPOINT_START" | "SUBMIT_THIRD_PARTY_RESULT" | "CREATE_CONTEXT" | "SUBMIT_FIRST_INVOCATION" | "RUN_SINGLE" | "RUN_PARALLEL" | "SUBMIT_STEP" | "SUBMIT_CLEANUP" | "RESPONSE_WORKFLOW" | "RESPONSE_DEFAULT" | "ERROR";
1112
- details: unknown;
1113
- };
1114
- type WorkflowLoggerOptions = {
1115
- logLevel: LogLevel;
1116
- logOutput: "console";
1117
- };
1118
- declare class WorkflowLogger {
1119
- private logs;
1120
- private options;
1121
- private workflowRunId?;
1122
- constructor(options: WorkflowLoggerOptions);
1123
- log(level: LogLevel, eventType: ChatLogEntry["eventType"], details?: unknown): Promise<void>;
1124
- setWorkflowRunId(workflowRunId: string): void;
1125
- private writeToConsole;
1126
- private shouldLog;
1127
- static getLogger(verbose?: boolean | WorkflowLogger): WorkflowLogger | undefined;
1128
- }
1129
-
1130
- declare class AutoExecutor {
1131
- private context;
1132
- private promises;
1133
- private activeLazyStepList?;
1134
- private debug?;
1135
- private readonly nonPlanStepCount;
1136
- private readonly steps;
1137
- private indexInCurrentList;
1138
- stepCount: number;
1139
- planStepCount: number;
1140
- protected executingStep: string | false;
1141
- constructor(context: WorkflowContext, steps: Step[], debug?: WorkflowLogger);
1288
+ stepName: string;
1142
1289
  /**
1143
- * Adds the step function to the list of step functions to run in
1144
- * parallel. After adding the function, defers the execution, so
1145
- * that if there is another step function to be added, it's also
1146
- * added.
1147
- *
1148
- * After all functions are added, list of functions are executed.
1149
- * If there is a single function, it's executed by itself. If there
1150
- * are multiple, they are run in parallel.
1151
- *
1152
- * If a function is already executing (this.executingStep), this
1153
- * means that there is a nested step which is not allowed. In this
1154
- * case, addStep throws QStashWorkflowError.
1155
- *
1156
- * @param stepInfo step plan to add
1157
- * @returns result of the step function
1290
+ * type of the step (Initial/Run/SleepFor/SleepUntil/Call)
1158
1291
  */
1159
- addStep<TResult>(stepInfo: BaseLazyStep<TResult>): Promise<TResult>;
1292
+ stepType: StepType;
1160
1293
  /**
1161
- * Wraps a step function to set this.executingStep to step name
1162
- * before running and set this.executingStep to False after execution
1163
- * ends.
1164
- *
1165
- * this.executingStep allows us to detect nested steps which are not
1166
- * allowed.
1167
- *
1168
- * @param stepName name of the step being wrapped
1169
- * @param stepFunction step function to wrap
1170
- * @returns wrapped step function
1294
+ * step result. Set if context.run or context.call are used.
1171
1295
  */
1172
- wrapStep<TResult = unknown>(stepName: string, stepFunction: StepFunction<TResult>): TResult | Promise<TResult>;
1296
+ out?: TResult;
1173
1297
  /**
1174
- * Executes a step:
1175
- * - If the step result is available in the steps, returns the result
1176
- * - If the result is not avaiable, runs the function
1177
- * - Sends the result to QStash
1178
- *
1179
- * @param lazyStep lazy step to execute
1180
- * @returns step result
1298
+ * sleep duration in seconds. Set when context.sleep is used.
1181
1299
  */
1182
- protected runSingle<TResult>(lazyStep: BaseLazyStep<TResult>): Promise<TResult>;
1300
+ sleepFor?: number;
1183
1301
  /**
1184
- * Runs steps in parallel.
1185
- *
1186
- * @param stepName parallel step name
1187
- * @param stepFunctions list of async functions to run in parallel
1188
- * @returns results of the functions run in parallel
1302
+ * unix timestamp (in seconds) to wait until. Set when context.sleepUntil is used.
1189
1303
  */
1190
- protected runParallel<TResults extends unknown[]>(parallelSteps: {
1191
- [K in keyof TResults]: BaseLazyStep<TResults[K]>;
1192
- }): Promise<TResults>;
1304
+ sleepUntil?: number;
1193
1305
  /**
1194
- * Determines the parallel call state
1195
- *
1196
- * First filters the steps to get the steps which are after `initialStepCount` parameter.
1197
- *
1198
- * Depending on the remaining steps, decides the parallel state:
1199
- * - "first": If there are no steps
1200
- * - "last" If there are equal to or more than `2 * parallelStepCount`. We multiply by two
1201
- * because each step in a parallel execution will have 2 steps: a plan step and a result
1202
- * step.
1203
- * - "partial": If the last step is a plan step
1204
- * - "discard": If the last step is not a plan step. This means that the parallel execution
1205
- * is in progress (there are still steps to run) and one step has finished and submitted
1206
- * its result to QStash
1207
- *
1208
- * @param parallelStepCount number of steps to run in parallel
1209
- * @param initialStepCount steps after the parallel invocation
1210
- * @returns parallel call state
1306
+ * number of steps running concurrently if the step is in a parallel run.
1307
+ * Set to 1 if step is not parallel.
1211
1308
  */
1212
- protected getParallelCallState(parallelStepCount: number, initialStepCount: number): ParallelCallState;
1309
+ concurrent: number;
1213
1310
  /**
1214
- * sends the steps to QStash as batch
1311
+ * target step of a plan step. In other words, the step to assign the
1312
+ * result of a plan step.
1215
1313
  *
1216
- * @param steps steps to send
1314
+ * undefined if the step is not a plan step (of a parallel run). Otherwise,
1315
+ * set to the target step.
1217
1316
  */
1218
- private submitStepsToQStash;
1317
+ targetStep?: number;
1318
+ } & (ThirdPartyCallFields<TBody> | {
1319
+ [P in keyof ThirdPartyCallFields]?: never;
1320
+ });
1321
+ type RawStep = {
1322
+ messageId: string;
1323
+ body: string;
1324
+ callType: "step" | "toCallback" | "fromCallback";
1325
+ };
1326
+ type SyncStepFunction<TResult> = () => TResult;
1327
+ type AsyncStepFunction<TResult> = () => Promise<TResult>;
1328
+ type StepFunction<TResult> = AsyncStepFunction<TResult> | SyncStepFunction<TResult>;
1329
+ type ParallelCallState = "first" | "partial" | "discard" | "last";
1330
+ type RouteFunction<TInitialPayload> = (context: WorkflowContext<TInitialPayload>) => Promise<void>;
1331
+ type FinishCondition = "success" | "duplicate-step" | "fromCallback" | "auth-fail" | "failure-callback";
1332
+ type WorkflowServeOptions<TResponse extends Response = Response, TInitialPayload = unknown> = {
1219
1333
  /**
1220
- * Get the promise by executing the lazt steps list. If there is a single
1221
- * step, we call `runSingle`. Otherwise `runParallel` is called.
1334
+ * QStash client
1335
+ */
1336
+ qstashClient?: WorkflowClient;
1337
+ /**
1338
+ * Function called to return a response after each step execution
1222
1339
  *
1223
- * @param lazyStepList steps list to execute
1224
- * @returns promise corresponding to the execution
1340
+ * @param workflowRunId
1341
+ * @returns response
1225
1342
  */
1226
- private getExecutionPromise;
1343
+ onStepFinish?: (workflowRunId: string, finishCondition: FinishCondition) => TResponse;
1227
1344
  /**
1228
- * @param lazyStepList steps we executed
1229
- * @param result result of the promise from `getExecutionPromise`
1230
- * @param index index of the current step
1231
- * @returns result[index] if lazyStepList > 1, otherwise result
1345
+ * Function to parse the initial payload passed by the user
1232
1346
  */
1233
- private static getResult;
1234
- private deferExecution;
1235
- }
1236
-
1237
- /**
1238
- * QStash workflow context
1239
- *
1240
- * See the docs for fields and methods https://upstash.com/docs/qstash/workflows/basics/context
1241
- */
1242
- declare class WorkflowContext<TInitialPayload = unknown> {
1243
- protected readonly executor: AutoExecutor;
1244
- protected readonly steps: Step[];
1347
+ initialPayloadParser?: (initialPayload: string) => TInitialPayload;
1245
1348
  /**
1246
- * QStash client of the workflow
1349
+ * Url of the endpoint where the workflow is set up.
1247
1350
  *
1248
- * Can be overwritten by passing `qstashClient` parameter in `serve`:
1351
+ * If not set, url will be inferred from the request.
1352
+ */
1353
+ url?: string;
1354
+ /**
1355
+ * Verbose mode
1249
1356
  *
1250
- * ```ts
1251
- * import { Client } from "@upstash/qstash"
1357
+ * Disabled if not set. If set to true, a logger is created automatically.
1252
1358
  *
1253
- * export const POST = serve(
1254
- * async (context) => {
1255
- * ...
1256
- * },
1257
- * {
1258
- * qstashClient: new Client({...})
1259
- * }
1260
- * )
1261
- * ```
1359
+ * Alternatively, a WorkflowLogger can be passed.
1262
1360
  */
1263
- readonly qstashClient: WorkflowClient;
1361
+ verbose?: WorkflowLogger | true;
1264
1362
  /**
1265
- * Run id of the workflow
1363
+ * Receiver to verify *all* requests by checking if they come from QStash
1364
+ *
1365
+ * By default, a receiver is created from the env variables
1366
+ * QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY if they are set.
1266
1367
  */
1267
- readonly workflowRunId: string;
1368
+ receiver?: WorkflowReceiver;
1268
1369
  /**
1269
- * URL of the workflow
1270
- *
1271
- * Can be overwritten by passing a `url` parameter in `serve`:
1272
- *
1273
- * ```ts
1274
- * export const POST = serve(
1275
- * async (context) => {
1276
- * ...
1277
- * },
1278
- * {
1279
- * url: "new-url-value"
1280
- * }
1281
- * )
1282
- * ```
1370
+ * Url to call if QStash retries are exhausted while executing the workflow
1283
1371
  */
1284
- readonly url: string;
1372
+ failureUrl?: string;
1285
1373
  /**
1286
- * URL to call in case of workflow failure with QStash failure callback
1287
- *
1288
- * https://upstash.com/docs/qstash/features/callbacks#what-is-a-failure-callback
1289
- *
1290
- * Can be overwritten by passing a `failureUrl` parameter in `serve`:
1374
+ * Failure function called when QStash retries are exhausted while executing
1375
+ * the workflow. Will overwrite `failureUrl` parameter with the workflow
1376
+ * endpoint if passed.
1291
1377
  *
1292
- * ```ts
1293
- * export const POST = serve(
1294
- * async (context) => {
1295
- * ...
1296
- * },
1297
- * {
1298
- * failureUrl: "new-url-value"
1299
- * }
1300
- * )
1301
- * ```
1378
+ * @param context workflow context at the moment of error
1379
+ * @param failStatus error status
1380
+ * @param failResponse error message
1381
+ * @returns void
1302
1382
  */
1303
- readonly failureUrl?: string;
1383
+ failureFunction?: (context: Omit<WorkflowContext, "run" | "sleepUntil" | "sleep" | "call">, failStatus: number, failResponse: string, failHeader: Record<string, string[]>) => Promise<void> | void;
1304
1384
  /**
1305
- * Payload of the request which started the workflow.
1306
- *
1307
- * To specify its type, you can define `serve` as follows:
1385
+ * Base Url of the workflow endpoint
1308
1386
  *
1309
- * ```ts
1310
- * // set requestPayload type to MyPayload:
1311
- * export const POST = serve<MyPayload>(
1312
- * async (context) => {
1313
- * ...
1314
- * }
1315
- * )
1316
- * ```
1387
+ * Can be used to set if there is a local tunnel or a proxy between
1388
+ * QStash and the workflow endpoint.
1317
1389
  *
1318
- * By default, `serve` tries to apply `JSON.parse` to the request payload.
1319
- * If your payload is encoded in a format other than JSON, you can utilize
1320
- * the `initialPayloadParser` parameter:
1390
+ * Will be set to the env variable UPSTASH_WORKFLOW_URL if not passed.
1391
+ * If the env variable is not set, the url will be infered as usual from
1392
+ * the `request.url` or the `url` parameter in `serve` options.
1321
1393
  *
1322
- * ```ts
1323
- * export const POST = serve<MyPayload>(
1324
- * async (context) => {
1325
- * ...
1326
- * },
1327
- * {
1328
- * initialPayloadParser: (initialPayload) => {return doSomething(initialPayload)}
1329
- * }
1330
- * )
1331
- * ```
1394
+ * @default undefined
1332
1395
  */
1333
- readonly requestPayload: TInitialPayload;
1396
+ baseUrl?: string;
1334
1397
  /**
1335
- * headers of the initial request
1398
+ * Optionally, one can pass an env object mapping environment
1399
+ * variables to their keys.
1400
+ *
1401
+ * Useful in cases like cloudflare with hono.
1336
1402
  */
1337
- readonly headers: Headers;
1403
+ env?: Record<string, string | undefined>;
1404
+ };
1405
+ /**
1406
+ * Payload passed as body in failureFunction
1407
+ */
1408
+ type FailureFunctionPayload = {
1338
1409
  /**
1339
- * initial payload as a raw string
1410
+ * error name
1340
1411
  */
1341
- readonly rawInitialPayload: string;
1412
+ error: string;
1342
1413
  /**
1343
- * Map of environment variables and their values.
1344
- *
1345
- * Can be set using the `env` option of serve:
1346
- *
1347
- * ```ts
1348
- * export const POST = serve<MyPayload>(
1349
- * async (context) => {
1350
- * const key = context.env["API_KEY"];
1351
- * },
1352
- * {
1353
- * env: {
1354
- * "API_KEY": "*****";
1355
- * }
1356
- * }
1357
- * )
1358
- * ```
1359
- *
1360
- * Default value is set to `process.env`.
1414
+ * error message
1361
1415
  */
1362
- readonly env: Record<string, string | undefined>;
1363
- constructor({ qstashClient, workflowRunId, headers, steps, url, failureUrl, debug, initialPayload, rawInitialPayload, env, }: {
1364
- qstashClient: WorkflowClient;
1365
- workflowRunId: string;
1366
- headers: Headers;
1367
- steps: Step[];
1368
- url: string;
1369
- failureUrl?: string;
1370
- debug?: WorkflowLogger;
1371
- initialPayload: TInitialPayload;
1372
- rawInitialPayload?: string;
1373
- env?: Record<string, string | undefined>;
1374
- });
1416
+ message: string;
1417
+ };
1418
+ /**
1419
+ * Makes all fields except the ones selected required
1420
+ */
1421
+ type RequiredExceptFields<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>>;
1422
+
1423
+ /**
1424
+ * Fills the options with default values if they are not provided.
1425
+ *
1426
+ * Default values for:
1427
+ * - qstashClient: QStash client created with QSTASH_URL and QSTASH_TOKEN env vars
1428
+ * - onStepFinish: returns a Response with workflowRunId & finish condition in the body (status: 200)
1429
+ * - initialPayloadParser: calls JSON.parse if initial request body exists.
1430
+ * - receiver: a Receiver if the required env vars are set
1431
+ * - baseUrl: env variable UPSTASH_WORKFLOW_URL
1432
+ *
1433
+ * @param options options including the client, onFinish and initialPayloadParser
1434
+ * @returns
1435
+ */
1436
+ declare const processOptions: <TResponse extends Response = Response, TInitialPayload = unknown>(options?: WorkflowServeOptions<TResponse, TInitialPayload>) => RequiredExceptFields<WorkflowServeOptions<TResponse, TInitialPayload>, "verbose" | "receiver" | "url" | "failureFunction" | "failureUrl" | "baseUrl">;
1437
+ /**
1438
+ * Creates an async method that handles incoming requests and runs the provided
1439
+ * route function as a workflow.
1440
+ *
1441
+ * @param routeFunction - A function that uses WorkflowContext as a parameter and runs a workflow.
1442
+ * @param options - Options including the client, onFinish callback, and initialPayloadParser.
1443
+ * @returns An async method that consumes incoming requests and runs the workflow.
1444
+ */
1445
+ declare const serve: <TInitialPayload = unknown, TRequest extends Request = Request, TResponse extends Response = Response>(routeFunction: RouteFunction<TInitialPayload>, options?: WorkflowServeOptions<TResponse, TInitialPayload>) => ((request: TRequest) => Promise<TResponse>);
1446
+
1447
+ declare class Workflow {
1448
+ private readonly http;
1449
+ constructor(http: Requester);
1375
1450
  /**
1376
- * Executes a workflow step
1377
- *
1378
- * ```typescript
1379
- * const result = await context.run("step 1", () => {
1380
- * return "result"
1381
- * })
1382
- * ```
1451
+ * Cancel an ongoing workflow
1383
1452
  *
1384
- * Can also be called in parallel and the steps will be executed
1385
- * simulatenously:
1453
+ * @param workflowRunId run id of the workflow to delete
1454
+ * @returns true if workflow is succesfully deleted. Otherwise throws QStashError
1455
+ */
1456
+ cancel(workflowRunId: string): Promise<true | {
1457
+ error: string;
1458
+ }>;
1459
+ }
1460
+
1461
+ type ClientConfig = {
1462
+ /**
1463
+ * Url of the QStash api server.
1386
1464
  *
1387
- * ```typescript
1388
- * const [result1, result2] = await Promise.all([
1389
- * context.run("step 1", () => {
1390
- * return "result1"
1391
- * })
1392
- * context.run("step 2", async () => {
1393
- * return await fetchResults()
1394
- * })
1395
- * ])
1396
- * ```
1465
+ * This is only used for testing.
1397
1466
  *
1398
- * @param stepName name of the step
1399
- * @param stepFunction step function to be executed
1400
- * @returns result of the step function
1467
+ * @default "https://qstash.upstash.io"
1401
1468
  */
1402
- run<TResult>(stepName: string, stepFunction: StepFunction<TResult>): Promise<TResult>;
1469
+ baseUrl?: string;
1403
1470
  /**
1404
- * Stops the execution for the duration provided.
1405
- *
1406
- * @param stepName
1407
- * @param duration sleep duration in seconds
1408
- * @returns undefined
1471
+ * The authorization token from the upstash console.
1409
1472
  */
1410
- sleep(stepName: string, duration: number): Promise<void>;
1473
+ token: string;
1411
1474
  /**
1412
- * Stops the execution until the date time provided.
1413
- *
1414
- * @param stepName
1415
- * @param datetime time to sleep until. Can be provided as a number (in unix seconds),
1416
- * as a Date object or a string (passed to `new Date(datetimeString)`)
1417
- * @returns undefined
1475
+ * Configure how the client should retry requests.
1418
1476
  */
1419
- sleepUntil(stepName: string, datetime: Date | string | number): Promise<void>;
1477
+ retry?: RetryConfig;
1478
+ };
1479
+ type PublishBatchRequest<TBody = BodyInit> = PublishRequest<TBody> & {
1480
+ queueName?: string;
1481
+ };
1482
+ type PublishRequest<TBody = BodyInit> = {
1420
1483
  /**
1421
- * Makes a third party call through QStash in order to make a
1422
- * network call without consuming any runtime.
1423
- *
1424
- * ```ts
1425
- * const postResult = await context.call<string>(
1426
- * "post call step",
1427
- * `https://www.some-endpoint.com/api`,
1428
- * "POST",
1429
- * "my-payload"
1430
- * );
1431
- * ```
1484
+ * The message to send.
1432
1485
  *
1433
- * tries to parse the result of the request as JSON. If it's
1434
- * not a JSON which can be parsed, simply returns the response
1435
- * body as it is.
1486
+ * This can be anything, but please set the `Content-Type` header accordingly.
1436
1487
  *
1437
- * @param stepName
1438
- * @param url url to call
1439
- * @param method call method
1440
- * @param body call body
1441
- * @param headers call headers
1442
- * @returns call result (parsed as JSON if possible)
1488
+ * You can leave this empty if you want to send a message with no body.
1443
1489
  */
1444
- call<TResult = unknown, TBody = unknown>(stepName: string, url: string, method: HTTPMethods, body?: TBody, headers?: Record<string, string>): Promise<TResult>;
1490
+ body?: TBody;
1445
1491
  /**
1446
- * Adds steps to the executor. Needed so that it can be overwritten in
1447
- * DisabledWorkflowContext.
1492
+ * Optionally send along headers with the message.
1493
+ * These headers will be sent to your destination.
1494
+ *
1495
+ * We highly recommend sending a `Content-Type` header along, as this will help your destination
1496
+ * server to understand the content of the message.
1448
1497
  */
1449
- protected addStep<TResult = unknown>(step: BaseLazyStep<TResult>): Promise<TResult>;
1450
- }
1451
- /**
1452
- * Workflow context which throws QStashWorkflowAbort before running the steps.
1453
- *
1454
- * Used for making a dry run before running any steps to check authentication.
1455
- *
1456
- * Consider an endpoint like this:
1457
- * ```ts
1458
- * export const POST = serve({
1459
- * routeFunction: context => {
1460
- * if (context.headers.get("authentication") !== "Bearer secretPassword") {
1461
- * console.error("Authentication failed.");
1462
- * return;
1463
- * }
1464
- *
1465
- * // ...
1466
- * }
1467
- * })
1468
- * ```
1469
- *
1470
- * the serve method will first call the routeFunction with an DisabledWorkflowContext.
1471
- * Here is the action we take in different cases
1472
- * - "step-found": we will run the workflow related sections of `serve`.
1473
- * - "run-ended": simply return success and end the workflow
1474
- * - error: returns 500.
1475
- */
1476
- declare class DisabledWorkflowContext<TInitialPayload = unknown> extends WorkflowContext<TInitialPayload> {
1477
- private static readonly disabledMessage;
1498
+ headers?: HeadersInit;
1478
1499
  /**
1479
- * overwrite the WorkflowContext.addStep method to always raise QStashWorkflowAbort
1480
- * error in order to stop the execution whenever we encounter a step.
1500
+ * Optionally delay the delivery of this message.
1481
1501
  *
1482
- * @param _step
1502
+ * In seconds.
1503
+ *
1504
+ * @default undefined
1483
1505
  */
1484
- protected addStep<TResult = unknown>(_step: BaseLazyStep<TResult>): Promise<TResult>;
1506
+ delay?: Duration | number;
1485
1507
  /**
1486
- * copies the passed context to create a DisabledWorkflowContext. Then, runs the
1487
- * route function with the new context.
1508
+ * Optionally set the absolute delay of this message.
1509
+ * This will override the delay option.
1510
+ * The message will not delivered until the specified time.
1488
1511
  *
1489
- * - returns "run-ended" if there are no steps found or
1490
- * if the auth failed and user called `return`
1491
- * - returns "step-found" if DisabledWorkflowContext.addStep is called.
1492
- * - if there is another error, returns the error.
1512
+ * Unix timestamp in seconds.
1493
1513
  *
1494
- * @param routeFunction
1514
+ * @default undefined
1495
1515
  */
1496
- static tryAuthentication<TInitialPayload = unknown>(routeFunction: RouteFunction<TInitialPayload>, context: WorkflowContext<TInitialPayload>): Promise<Ok<"step-found" | "run-ended", never> | Err<never, Error>>;
1497
- }
1498
-
1499
- /**
1500
- * Interface for Client with required methods
1501
- *
1502
- * Neeeded to resolve import issues
1503
- */
1504
- type WorkflowClient = {
1505
- batchJSON: InstanceType<typeof Client>["batchJSON"];
1506
- publishJSON: InstanceType<typeof Client>["publishJSON"];
1507
- http: InstanceType<typeof Client>["http"];
1508
- };
1509
- /**
1510
- * Interface for Receiver with required methods
1511
- *
1512
- * Neeeded to resolve import issues
1513
- */
1514
- type WorkflowReceiver = {
1515
- verify: InstanceType<typeof Receiver>["verify"];
1516
- };
1517
- declare const StepTypes: readonly ["Initial", "Run", "SleepFor", "SleepUntil", "Call"];
1518
- type StepType = (typeof StepTypes)[number];
1519
- type ThirdPartyCallFields<TBody = unknown> = {
1516
+ notBefore?: number;
1520
1517
  /**
1521
- * Third party call URL. Set when context.call is used.
1518
+ * Provide a unique id for deduplication. This id will be used to detect duplicate messages.
1519
+ * If a duplicate message is detected, the request will be accepted but not enqueued.
1520
+ *
1521
+ * We store deduplication ids for 90 days. Afterwards it is possible that the message with the
1522
+ * same deduplication id is delivered again.
1523
+ *
1524
+ * When scheduling a message, the deduplication happens before the schedule is created.
1525
+ *
1526
+ * @default undefined
1522
1527
  */
1523
- callUrl: string;
1528
+ deduplicationId?: string;
1524
1529
  /**
1525
- * Third party call method. Set when context.call is used.
1530
+ * If true, the message content will get hashed and used as deduplication id.
1531
+ * If a duplicate message is detected, the request will be accepted but not enqueued.
1532
+ *
1533
+ * The content based hash includes the following values:
1534
+ * - All headers, except Upstash-Authorization, this includes all headers you are sending.
1535
+ * - The entire raw request body The destination from the url path
1536
+ *
1537
+ * We store deduplication ids for 90 days. Afterwards it is possible that the message with the
1538
+ * same deduplication id is delivered again.
1539
+ *
1540
+ * When scheduling a message, the deduplication happens before the schedule is created.
1541
+ *
1542
+ * @default false
1526
1543
  */
1527
- callMethod: HTTPMethods;
1544
+ contentBasedDeduplication?: boolean;
1528
1545
  /**
1529
- * Third party call body. Set when context.call is used.
1546
+ * In case your destination server is unavaialble or returns a status code outside of the 200-299
1547
+ * range, we will retry the request after a certain amount of time.
1548
+ *
1549
+ * Configure how many times you would like the delivery to be retried up to the maxRetries limit
1550
+ * defined in your plan.
1551
+ *
1552
+ * @default 3
1530
1553
  */
1531
- callBody: TBody;
1554
+ retries?: number;
1532
1555
  /**
1533
- * Third party call headers. Set when context.call is used.
1556
+ * Use a failure callback url to handle messages that could not be delivered.
1557
+ *
1558
+ * The failure callback url must be publicly accessible
1559
+ *
1560
+ * @default undefined
1534
1561
  */
1535
- callHeaders: Record<string, string>;
1536
- };
1537
- type Step<TResult = unknown, TBody = unknown> = {
1562
+ failureCallback?: string;
1538
1563
  /**
1539
- * index of the step
1564
+ * The method to use when sending a request to your API
1565
+ *
1566
+ * @default `POST`
1540
1567
  */
1541
- stepId: number;
1568
+ method?: HTTPMethods;
1542
1569
  /**
1543
- * name of the step
1570
+ * The HTTP timeout value to use while calling the destination URL.
1571
+ * When a timeout is specified, it will be used instead of the maximum timeout
1572
+ * value permitted by the QStash plan. It is useful in scenarios, where a message
1573
+ * should be delivered with a shorter timeout.
1574
+ *
1575
+ * In seconds.
1576
+ *
1577
+ * @default undefined
1544
1578
  */
1545
- stepName: string;
1579
+ timeout?: Duration | number;
1580
+ } & ({
1546
1581
  /**
1547
- * type of the step (Initial/Run/SleepFor/SleepUntil/Call)
1582
+ * The url where the message should be sent to.
1548
1583
  */
1549
- stepType: StepType;
1584
+ url: string;
1585
+ urlGroup?: never;
1586
+ api?: never;
1587
+ topic?: never;
1550
1588
  /**
1551
- * step result. Set if context.run or context.call are used.
1589
+ * Use a callback url to forward the response of your destination server to your callback url.
1590
+ *
1591
+ * The callback url must be publicly accessible
1592
+ *
1593
+ * @default undefined
1552
1594
  */
1553
- out?: TResult;
1595
+ callback?: string;
1596
+ } | {
1597
+ url?: never;
1554
1598
  /**
1555
- * sleep duration in seconds. Set when context.sleep is used.
1599
+ * The url group the message should be sent to.
1556
1600
  */
1557
- sleepFor?: number;
1601
+ urlGroup: string;
1602
+ api?: never;
1603
+ topic?: never;
1558
1604
  /**
1559
- * unix timestamp (in seconds) to wait until. Set when context.sleepUntil is used.
1605
+ * Use a callback url to forward the response of your destination server to your callback url.
1606
+ *
1607
+ * The callback url must be publicly accessible
1608
+ *
1609
+ * @default undefined
1560
1610
  */
1561
- sleepUntil?: number;
1611
+ callback?: string;
1612
+ } | {
1613
+ url?: string;
1614
+ urlGroup?: never;
1562
1615
  /**
1563
- * number of steps running concurrently if the step is in a parallel run.
1564
- * Set to 1 if step is not parallel.
1616
+ * The api endpoint the request should be sent to.
1565
1617
  */
1566
- concurrent: number;
1618
+ api: {
1619
+ name: "llm";
1620
+ provider?: ProviderReturnType;
1621
+ analytics?: {
1622
+ name: "helicone";
1623
+ token: string;
1624
+ };
1625
+ };
1567
1626
  /**
1568
- * target step of a plan step. In other words, the step to assign the
1569
- * result of a plan step.
1627
+ * Use a callback url to forward the response of your destination server to your callback url.
1570
1628
  *
1571
- * undefined if the step is not a plan step (of a parallel run). Otherwise,
1572
- * set to the target step.
1629
+ * The callback url must be publicly accessible
1630
+ *
1631
+ * @default undefined
1573
1632
  */
1574
- targetStep?: number;
1575
- } & (ThirdPartyCallFields<TBody> | {
1576
- [P in keyof ThirdPartyCallFields]?: never;
1577
- });
1578
- type RawStep = {
1579
- messageId: string;
1580
- body: string;
1581
- callType: "step" | "toCallback" | "fromCallback";
1582
- };
1583
- type SyncStepFunction<TResult> = () => TResult;
1584
- type AsyncStepFunction<TResult> = () => Promise<TResult>;
1585
- type StepFunction<TResult> = AsyncStepFunction<TResult> | SyncStepFunction<TResult>;
1586
- type ParallelCallState = "first" | "partial" | "discard" | "last";
1587
- type RouteFunction<TInitialPayload> = (context: WorkflowContext<TInitialPayload>) => Promise<void>;
1588
- type FinishCondition = "success" | "duplicate-step" | "fromCallback" | "auth-fail" | "failure-callback";
1589
- type WorkflowServeOptions<TResponse extends Response = Response, TInitialPayload = unknown> = {
1633
+ callback: string;
1634
+ topic?: never;
1635
+ } | {
1636
+ url?: never;
1637
+ urlGroup?: never;
1638
+ api: never;
1590
1639
  /**
1591
- * QStash client
1640
+ * Deprecated. The topic the message should be sent to. Same as urlGroup
1592
1641
  */
1593
- qstashClient?: WorkflowClient;
1642
+ topic?: string;
1594
1643
  /**
1595
- * Function called to return a response after each step execution
1644
+ * Use a callback url to forward the response of your destination server to your callback url.
1596
1645
  *
1597
- * @param workflowRunId
1598
- * @returns response
1646
+ * The callback url must be publicly accessible
1647
+ *
1648
+ * @default undefined
1599
1649
  */
1600
- onStepFinish?: (workflowRunId: string, finishCondition: FinishCondition) => TResponse;
1650
+ callback?: string;
1651
+ });
1652
+ type PublishJsonRequest = Omit<PublishRequest, "body"> & {
1601
1653
  /**
1602
- * Function to parse the initial payload passed by the user
1654
+ * The message to send.
1655
+ * This can be anything as long as it can be serialized to JSON.
1603
1656
  */
1604
- initialPayloadParser?: (initialPayload: string) => TInitialPayload;
1657
+ body: unknown;
1658
+ };
1659
+ type EventsRequest = {
1660
+ cursor?: number;
1661
+ filter?: EventsRequestFilter;
1662
+ };
1663
+ type EventsRequestFilter = {
1664
+ messageId?: string;
1665
+ state?: State;
1666
+ url?: string;
1667
+ urlGroup?: string;
1668
+ topicName?: string;
1669
+ api?: string;
1670
+ scheduleId?: string;
1671
+ queueName?: string;
1672
+ fromDate?: number;
1673
+ toDate?: number;
1674
+ count?: number;
1675
+ };
1676
+ type GetEventsResponse = {
1677
+ cursor?: number;
1678
+ events: Event[];
1679
+ };
1680
+ type QueueRequest = {
1681
+ queueName?: string;
1682
+ };
1683
+ declare class Client {
1684
+ http: Requester;
1685
+ private token;
1686
+ constructor(config: ClientConfig);
1605
1687
  /**
1606
- * Url of the endpoint where the workflow is set up.
1688
+ * Access the urlGroup API.
1607
1689
  *
1608
- * If not set, url will be inferred from the request.
1690
+ * Create, read, update or delete urlGroups.
1609
1691
  */
1610
- url?: string;
1692
+ get urlGroups(): UrlGroups;
1611
1693
  /**
1612
- * Verbose mode
1694
+ * Deprecated. Use urlGroups instead.
1613
1695
  *
1614
- * Disabled if not set. If set to true, a logger is created automatically.
1696
+ * Access the topic API.
1615
1697
  *
1616
- * Alternatively, a WorkflowLogger can be passed.
1698
+ * Create, read, update or delete topics.
1617
1699
  */
1618
- verbose?: WorkflowLogger | true;
1700
+ get topics(): UrlGroups;
1619
1701
  /**
1620
- * Receiver to verify *all* requests by checking if they come from QStash
1702
+ * Access the dlq API.
1621
1703
  *
1622
- * By default, a receiver is created from the env variables
1623
- * QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY if they are set.
1704
+ * List or remove messages from the DLQ.
1624
1705
  */
1625
- receiver?: WorkflowReceiver;
1706
+ get dlq(): DLQ;
1626
1707
  /**
1627
- * Url to call if QStash retries are exhausted while executing the workflow
1708
+ * Access the message API.
1709
+ *
1710
+ * Read or cancel messages.
1628
1711
  */
1629
- failureUrl?: string;
1712
+ get messages(): Messages;
1630
1713
  /**
1631
- * Failure function called when QStash retries are exhausted while executing
1632
- * the workflow. Will overwrite `failureUrl` parameter with the workflow
1633
- * endpoint if passed.
1714
+ * Access the schedule API.
1634
1715
  *
1635
- * @param context workflow context at the moment of error
1636
- * @param failStatus error status
1637
- * @param failResponse error message
1638
- * @returns void
1716
+ * Create, read or delete schedules.
1639
1717
  */
1640
- failureFunction?: (context: Omit<WorkflowContext, "run" | "sleepUntil" | "sleep" | "call">, failStatus: number, failResponse: string, failHeader: Record<string, string[]>) => Promise<void> | void;
1718
+ get schedules(): Schedules;
1641
1719
  /**
1642
- * Base Url of the workflow endpoint
1643
- *
1644
- * Can be used to set if there is a local tunnel or a proxy between
1645
- * QStash and the workflow endpoint.
1720
+ * Access the workflow API.
1646
1721
  *
1647
- * Will be set to the env variable UPSTASH_WORKFLOW_URL if not passed.
1648
- * If the env variable is not set, the url will be infered as usual from
1649
- * the `request.url` or the `url` parameter in `serve` options.
1722
+ * cancel workflows.
1723
+ */
1724
+ get workflow(): Workflow;
1725
+ /**
1726
+ * Access the queue API.
1650
1727
  *
1651
- * @default undefined
1728
+ * Create, read, update or delete queues.
1652
1729
  */
1653
- baseUrl?: string;
1730
+ queue(request?: QueueRequest): Queue;
1654
1731
  /**
1655
- * Optionally, one can pass an env object mapping environment
1656
- * variables to their keys.
1732
+ * Access the Chat API
1657
1733
  *
1658
- * Useful in cases like cloudflare with hono.
1734
+ * Call the create or prompt methods
1659
1735
  */
1660
- env?: Record<string, string | undefined>;
1661
- };
1662
- /**
1663
- * Payload passed as body in failureFunction
1664
- */
1665
- type FailureFunctionPayload = {
1736
+ chat(): Chat;
1737
+ publish<TRequest extends PublishRequest>(request: TRequest): Promise<PublishResponse<TRequest>>;
1666
1738
  /**
1667
- * error name
1739
+ * publishJSON is a utility wrapper around `publish` that automatically serializes the body
1740
+ * and sets the `Content-Type` header to `application/json`.
1668
1741
  */
1669
- error: string;
1742
+ publishJSON<TBody = unknown, TRequest extends PublishRequest<TBody> = PublishRequest<TBody>>(request: TRequest): Promise<PublishResponse<TRequest>>;
1670
1743
  /**
1671
- * error message
1744
+ * Batch publish messages to QStash.
1672
1745
  */
1673
- message: string;
1674
- };
1675
- /**
1676
- * Makes all fields except the ones selected required
1677
- */
1678
- type RequiredExceptFields<T, K extends keyof T> = Omit<Required<T>, K> & Partial<Pick<T, K>>;
1679
-
1680
- /**
1681
- * Fills the options with default values if they are not provided.
1682
- *
1683
- * Default values for:
1684
- * - qstashClient: QStash client created with QSTASH_URL and QSTASH_TOKEN env vars
1685
- * - onStepFinish: returns a Response with workflowRunId & finish condition in the body (status: 200)
1686
- * - initialPayloadParser: calls JSON.parse if initial request body exists.
1687
- * - receiver: a Receiver if the required env vars are set
1688
- * - baseUrl: env variable UPSTASH_WORKFLOW_URL
1689
- *
1690
- * @param options options including the client, onFinish and initialPayloadParser
1691
- * @returns
1692
- */
1693
- declare const processOptions: <TResponse extends Response = Response, TInitialPayload = unknown>(options?: WorkflowServeOptions<TResponse, TInitialPayload>) => RequiredExceptFields<WorkflowServeOptions<TResponse, TInitialPayload>, "verbose" | "receiver" | "url" | "failureFunction" | "failureUrl" | "baseUrl">;
1694
- /**
1695
- * Creates an async method that handles incoming requests and runs the provided
1696
- * route function as a workflow.
1697
- *
1698
- * @param routeFunction - A function that uses WorkflowContext as a parameter and runs a workflow.
1699
- * @param options - Options including the client, onFinish callback, and initialPayloadParser.
1700
- * @returns An async method that consumes incoming requests and runs the workflow.
1701
- */
1702
- declare const serve: <TInitialPayload = unknown, TRequest extends Request = Request, TResponse extends Response = Response>(routeFunction: RouteFunction<TInitialPayload>, options?: WorkflowServeOptions<TResponse, TInitialPayload>) => ((request: TRequest) => Promise<TResponse>);
1703
-
1704
- declare class Workflow {
1705
- private readonly http;
1706
- constructor(http: Requester);
1746
+ batch(request: PublishBatchRequest[]): Promise<PublishResponse<PublishRequest>[]>;
1707
1747
  /**
1708
- * Cancel an ongoing workflow
1748
+ * Batch publish messages to QStash, serializing each body to JSON.
1749
+ */
1750
+ batchJSON<TBody = unknown, TRequest extends PublishBatchRequest<TBody> = PublishBatchRequest<TBody>>(request: TRequest[]): Promise<PublishResponse<TRequest>[]>;
1751
+ /**
1752
+ * Retrieve your logs.
1709
1753
  *
1710
- * @param workflowRunId run id of the workflow to delete
1711
- * @returns true if workflow is succesfully deleted. Otherwise throws QStashError
1754
+ * The logs endpoint is paginated and returns only 100 logs at a time.
1755
+ * If you want to receive more logs, you can use the cursor to paginate.
1756
+ *
1757
+ * The cursor is a unix timestamp with millisecond precision
1758
+ *
1759
+ * @example
1760
+ * ```ts
1761
+ * let cursor = Date.now()
1762
+ * const logs: Log[] = []
1763
+ * while (cursor > 0) {
1764
+ * const res = await qstash.logs({ cursor })
1765
+ * logs.push(...res.logs)
1766
+ * cursor = res.cursor ?? 0
1767
+ * }
1768
+ * ```
1712
1769
  */
1713
- cancel(workflowRunId: string): Promise<true | {
1714
- error: string;
1715
- }>;
1770
+ events(request?: EventsRequest): Promise<GetEventsResponse>;
1716
1771
  }
1772
+ type PublishToApiResponse = {
1773
+ messageId: string;
1774
+ };
1775
+ type PublishToUrlResponse = PublishToApiResponse & {
1776
+ url: string;
1777
+ deduplicated?: boolean;
1778
+ };
1779
+ type PublishToUrlGroupsResponse = PublishToUrlResponse[];
1780
+ type PublishResponse<TRequest> = TRequest extends {
1781
+ url: string;
1782
+ } ? PublishToUrlResponse : TRequest extends {
1783
+ urlGroup: string;
1784
+ } ? PublishToUrlGroupsResponse : PublishToApiResponse;
1717
1785
 
1718
- export { type AsyncStepFunction, DisabledWorkflowContext, type FailureFunctionPayload, type FinishCondition, type LogLevel, type ParallelCallState, type RawStep, type RequiredExceptFields, type RouteFunction, type Step, type StepFunction, type StepType, StepTypes, type SyncStepFunction, Workflow, type WorkflowClient, WorkflowContext, WorkflowLogger, type WorkflowLoggerOptions, type WorkflowReceiver, type WorkflowServeOptions, processOptions, serve };
1786
+ export { type AnalyticsConfig as $, type AddEndpointsRequest as A, type BodyInit as B, type ChatRateLimit as C, type ChatCompletion as D, type EventsRequest as E, type FailureFunctionPayload as F, type GetEventsResponse as G, type HTTPMethods as H, type ChatCompletionChunk as I, type StreamEnabled as J, type StreamDisabled as K, type StreamParameter as L, type Message as M, type PromptChatRequest as N, type OpenAIChatModel as O, type PublishBatchRequest as P, type QueueRequest as Q, type RateLimit as R, type Step as S, type ChatRequest as T, type UrlGroup as U, type VerifyRequest as V, type WithCursor as W, custom as X, openai as Y, upstash as Z, type ProviderReturnType as _, type ReceiverConfig as a, type AnalyticsSetup as a0, setupAnalytics as a1, type RouteFunction as a2, type WorkflowServeOptions as a3, Workflow as a4, processOptions as a5, serve as a6, WorkflowContext as a7, DisabledWorkflowContext as a8, type WorkflowClient as a9, type WorkflowReceiver as aa, StepTypes as ab, type StepType as ac, type RawStep as ad, type SyncStepFunction as ae, type AsyncStepFunction as af, type StepFunction as ag, type ParallelCallState as ah, type FinishCondition as ai, type RequiredExceptFields as aj, type LogLevel as ak, type WorkflowLoggerOptions as al, WorkflowLogger as am, SignatureError as b, Receiver as c, type PublishRequest as d, type PublishJsonRequest as e, Client as f, type PublishToApiResponse as g, type PublishToUrlResponse as h, type PublishToUrlGroupsResponse as i, type PublishResponse as j, type MessagePayload as k, Messages as l, type Schedule as m, type CreateScheduleRequest as n, Schedules as o, type Endpoint as p, type RemoveEndpointsRequest as q, UrlGroups as r, type State as s, type Event as t, type EventPayload as u, type GetEventsPayload as v, type HeadersInit as w, type RequestOptions as x, Chat as y, type ChatCompletionMessage as z };