@upstash/qstash 2.7.5 → 2.7.6-canary

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