@upstash/qstash 2.9.1-rc.1 → 2.10.0

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.
@@ -505,32 +505,16 @@ type RetryConfig = false | {
505
505
  backoff?: (retryCount: number) => number;
506
506
  };
507
507
 
508
- type NeverAll<T> = {
509
- [K in keyof T]?: never;
510
- };
511
508
  type RequireAtLeastOne<T> = {
512
509
  [K in keyof T]-?: Required<Pick<T, K>>;
513
510
  }[keyof T];
514
- /**
515
- * Three-way exclusive union: at-least-one-filter OR `{ all: true }` OR IDs.
516
- * Exactly one branch can be satisfied at a time.
517
- *
518
- * The filter and all branches intentionally omit `NeverAll<Ids>` so that
519
- * TypeScript's `"key" in request` narrowing correctly isolates the IDs branch.
520
- * Excess-property checks on object literals still prevent mixing ID keys with filters.
521
- */
522
- type FilterAllOrIds<F extends Record<string, unknown>, Ids extends Record<string, unknown>> = (F & RequireAtLeastOne<F> & {
523
- all?: never;
524
- }) | ({
525
- all: true;
526
- } & NeverAll<F>) | (Ids & NeverAll<F> & {
527
- all?: never;
528
- });
511
+ type NeverKeys<T> = {
512
+ [K in keyof T]?: never;
513
+ };
514
+ /** Two-branch exclusive union: A or B, never both. */
515
+ type Exclusive<A, B> = (A & NeverKeys<B>) | (B & NeverKeys<A>);
529
516
  /** Shared filter fields accepted by every qstash & workflow endpoint. */
530
517
  type UniversalFilterFields = {
531
- /**
532
- * aslkdjasd
533
- */
534
518
  fromDate?: Date | number;
535
519
  toDate?: Date | number;
536
520
  callerIp?: string;
@@ -552,19 +536,100 @@ type DLQResponseFields = {
552
536
  /** Logs-specific filter fields exclusive to log endpoints. */
553
537
  type LogsFilterFields = {
554
538
  state?: State;
555
- messageIds?: string[];
556
539
  };
540
+ type DLQFilterFields = UniversalFilterFields & QStashIdentityFields & DLQResponseFields & {
541
+ /**
542
+ * @deprecated `api` filter has been removed from the API and will be ignored
543
+ */
544
+ api?: string;
545
+ };
546
+ type MessageCancelFilterFields = UniversalFilterFields & Omit<QStashIdentityFields, "messageId">;
557
547
  /**
558
- * Doesn't allow a single messageId because this is a bulk action
548
+ * Doesn't allow a single messageId because this is a bulk action.
549
+ * Cancel does not support cursor.
559
550
  */
560
- type MessageCancelFilters = FilterAllOrIds<UniversalFilterFields & Omit<QStashIdentityFields, "messageId">, {
551
+ type MessageCancelFilters = {
561
552
  messageIds: string[];
562
- }>;
563
- type DLQBulkActionFilters = FilterAllOrIds<UniversalFilterFields & QStashIdentityFields & DLQResponseFields, {
553
+ filter?: never;
554
+ all?: never;
555
+ count?: never;
556
+ } | ({
557
+ filter: RequireAtLeastOne<MessageCancelFilterFields>;
558
+ messageIds?: never;
559
+ all?: never;
560
+ } & MessageCancelCount) | ({
561
+ all: true;
562
+ messageIds?: never;
563
+ filter?: never;
564
+ } & MessageCancelCount);
565
+ type MessageCancelCount = {
566
+ /**
567
+ * Maximum number of messages to cancel per call.
568
+ *
569
+ * @default 100
570
+ */
571
+ count?: number;
572
+ };
573
+ /**
574
+ * DLQ bulk actions support three modes:
575
+ * - By dlqIds (no cursor)
576
+ * - By filter fields (with optional cursor)
577
+ * - All (with optional cursor)
578
+ */
579
+ type DLQBulkActionFilters = {
564
580
  dlqIds: string | string[];
581
+ filter?: never;
582
+ all?: never;
583
+ count?: never;
584
+ cursor?: never;
585
+ } | ({
586
+ filter: RequireAtLeastOne<DLQFilterFields>;
587
+ dlqIds?: never;
588
+ all?: never;
589
+ } & DLQBulkActionCount) | ({
590
+ all: true;
591
+ dlqIds?: never;
592
+ filter?: never;
593
+ } & DLQBulkActionCount);
594
+ type DLQBulkActionCount = {
595
+ cursor?: string;
596
+ /**
597
+ * Maximum number of messages to process per call.
598
+ *
599
+ * @default 100
600
+ */
601
+ count?: number;
602
+ };
603
+ type DLQListRequest = Exclusive<{
604
+ dlqIds: string | string[];
605
+ }, {
606
+ filter?: DLQFilterFields;
607
+ cursor?: string;
565
608
  }>;
566
- type DLQListFilters = UniversalFilterFields & QStashIdentityFields & DLQResponseFields;
567
- type LogsListFilters = UniversalFilterFields & QStashIdentityFields & LogsFilterFields & {
609
+ type LogsListRequest = Exclusive<{
610
+ messageIds: string[];
611
+ }, {
612
+ filter?: LogsListFilters;
613
+ /**
614
+ * Passing `number` may silently break due to JavaScript integer precision
615
+ * limits — cursor values can exceed `Number.MAX_SAFE_INTEGER`. Use `string` instead.
616
+ */
617
+ cursor?: string | number;
618
+ }>;
619
+ type LogsListFilters = UniversalFilterFields & Omit<QStashIdentityFields, "messageId"> & LogsFilterFields & {
620
+ /**
621
+ * @deprecated `api` filter has been removed from the API and will be ignored
622
+ */
623
+ api?: string;
624
+ /**
625
+ * @deprecated use `messageIds` in the root instead of `messageId` in the `filter` object
626
+ *
627
+ * Example:
628
+ * ```ts
629
+ * await client.logs({ messageIds: ["id1", "id2"] })
630
+ * ```
631
+ */
632
+ messageId?: string;
568
633
  /**
569
634
  * @deprecated use `urlGroup` instead
570
635
  */
@@ -707,8 +772,19 @@ declare class Messages {
707
772
  * Can be called with:
708
773
  * - A single messageId: `cancel("id")`
709
774
  * - An array of messageIds: `cancel(["id1", "id2"])`
710
- * - A filter object: `cancel({ flowControlKey: "key", label: "label" })`
775
+ * - A filter object: `cancel({ filter: { flowControlKey: "key", label: "label" } })`
711
776
  * - All messages: `cancel({ all: true })`
777
+ *
778
+ * Pass `count` to limit the number of messages processed per call (defaults to 100).
779
+ * Call in a loop until `cancelled` is 0:
780
+ *
781
+ * ```ts
782
+ * let cancelled: number;
783
+ * do {
784
+ * const result = await messages.cancel({ all: true, count: 100 });
785
+ * cancelled = result.cancelled;
786
+ * } while (cancelled > 0);
787
+ * ```
712
788
  */
713
789
  cancel(request: string | string[] | MessageCancelFilters): Promise<{
714
790
  cancelled: number;
@@ -761,15 +837,15 @@ declare class DLQ {
761
837
  constructor(http: Requester);
762
838
  /**
763
839
  * List messages in the dlq
840
+ *
841
+ * Can be called with:
842
+ * - Filters: `listMessages({ filter: { url: "https://example.com" } })`
843
+ * - DLQ IDs: `listMessages({ dlqIds: ["id1", "id2"] })`
844
+ * - No filter (list all): `listMessages()`
764
845
  */
765
846
  listMessages(options?: {
766
- cursor?: string;
767
847
  count?: number;
768
- /** Defaults to `latestFirst` */
769
- order?: "earliestFirst" | "latestFirst";
770
- trimBody?: number;
771
- filter?: DLQListFilters;
772
- }): Promise<{
848
+ } & DLQListRequest): Promise<{
773
849
  messages: DlqMessage[];
774
850
  cursor?: string;
775
851
  }>;
@@ -780,10 +856,19 @@ declare class DLQ {
780
856
  * - A single dlqId: `delete("id")`
781
857
  * - An array of dlqIds: `delete(["id1", "id2"])`
782
858
  * - An object with dlqIds: `delete({ dlqIds: ["id1", "id2"] })`
783
- * - A filter object: `delete({ url: "https://example.com", label: "label" })`
859
+ * - A filter object: `delete({ filter: { url: "https://example.com", label: "label" } })`
784
860
  * - All messages: `delete({ all: true })`
785
861
  *
786
- * Note: passing an empty array returns `{ deleted: 0 }` without making a request.
862
+ * Pass `count` to limit the number of messages processed per call (defaults to 100).
863
+ * Call in a loop until cursor is undefined:
864
+ *
865
+ * ```ts
866
+ * let cursor: string | undefined;
867
+ * do {
868
+ * const result = await dlq.delete({ all: true, count: 100, cursor });
869
+ * cursor = result.cursor;
870
+ * } while (cursor);
871
+ * ```
787
872
  */
788
873
  delete(request: string | string[] | DLQBulkActionFilters): Promise<{
789
874
  deleted: number;
@@ -807,10 +892,19 @@ declare class DLQ {
807
892
  * - A single dlqId: `retry("id")`
808
893
  * - An array of dlqIds: `retry(["id1", "id2"])`
809
894
  * - An object with dlqIds: `retry({ dlqIds: ["id1", "id2"] })`
810
- * - A filter object: `retry({ url: "https://example.com", label: "label" })`
895
+ * - A filter object: `retry({ filter: { url: "https://example.com", label: "label" } })`
811
896
  * - All messages: `retry({ all: true })`
812
897
  *
813
- * Note: passing an empty array returns `{ responses: [] }` without making a request.
898
+ * Pass `count` to limit the number of messages processed per call (defaults to 100).
899
+ * Call in a loop until cursor is undefined:
900
+ *
901
+ * ```ts
902
+ * let cursor: string | undefined;
903
+ * do {
904
+ * const result = await dlq.retry({ all: true, count: 100, cursor });
905
+ * cursor = result.cursor;
906
+ * } while (cursor);
907
+ * ```
814
908
  */
815
909
  retry(request: string | string[] | DLQBulkActionFilters): Promise<{
816
910
  cursor?: string;
@@ -820,6 +914,131 @@ declare class DLQ {
820
914
  }>;
821
915
  }
822
916
 
917
+ type FlowControlInfo = {
918
+ /**
919
+ * The flow control key.
920
+ */
921
+ flowControlKey: string;
922
+ /**
923
+ * The number of messages waiting in the wait list.
924
+ */
925
+ waitListSize: number;
926
+ /**
927
+ * The maximum parallelism configured for this flow control key.
928
+ */
929
+ parallelismMax: number;
930
+ /**
931
+ * The current number of active requests for this flow control key.
932
+ */
933
+ parallelismCount: number;
934
+ /**
935
+ * The maximum rate configured for this flow control key.
936
+ */
937
+ rateMax: number;
938
+ /**
939
+ * The current number of requests consumed in the current period.
940
+ */
941
+ rateCount: number;
942
+ /**
943
+ * The rate period in seconds.
944
+ */
945
+ ratePeriod: number;
946
+ /**
947
+ * The start time of the current rate period as a unix timestamp.
948
+ */
949
+ ratePeriodStart: number;
950
+ /**
951
+ * Whether message delivery is paused for this flow control key.
952
+ */
953
+ isPaused: boolean;
954
+ /**
955
+ * Whether the parallelism configuration is pinned.
956
+ */
957
+ isPinnedParallelism: boolean;
958
+ /**
959
+ * Whether the rate configuration is pinned.
960
+ */
961
+ isPinnedRate: boolean;
962
+ };
963
+ type GlobalParallelismInfo = {
964
+ /**
965
+ * The maximum global parallelism.
966
+ */
967
+ parallelismMax: number;
968
+ /**
969
+ * The current number of active requests globally.
970
+ */
971
+ parallelismCount: number;
972
+ };
973
+ type PinFlowControlOptions = {
974
+ /**
975
+ * The parallelism value to apply to the flow-control key.
976
+ */
977
+ parallelism?: number;
978
+ /**
979
+ * The rate value to apply to the flow-control key.
980
+ */
981
+ rate?: number;
982
+ /**
983
+ * The period value to apply to the flow-control key, in seconds.
984
+ */
985
+ period?: number;
986
+ };
987
+ type UnpinFlowControlOptions = {
988
+ /**
989
+ * Whether to unpin the parallelism configuration.
990
+ */
991
+ parallelism?: boolean;
992
+ /**
993
+ * Whether to unpin the rate configuration.
994
+ */
995
+ rate?: boolean;
996
+ };
997
+ declare class FlowControlApi {
998
+ private readonly http;
999
+ constructor(http: Requester);
1000
+ /**
1001
+ * Get a single flow control by key.
1002
+ */
1003
+ get(flowControlKey: string): Promise<FlowControlInfo>;
1004
+ /**
1005
+ * Get the global parallelism info.
1006
+ */
1007
+ getGlobalParallelism(): Promise<GlobalParallelismInfo>;
1008
+ /**
1009
+ * Pause message delivery for a flow-control key.
1010
+ *
1011
+ * Messages already in the waitlist will remain there.
1012
+ * New incoming messages will be added directly to the waitlist.
1013
+ */
1014
+ pause(flowControlKey: string): Promise<void>;
1015
+ /**
1016
+ * Resume message delivery for a flow-control key.
1017
+ */
1018
+ resume(flowControlKey: string): Promise<void>;
1019
+ /**
1020
+ * Pin a processing configuration for a flow-control key.
1021
+ *
1022
+ * While pinned, the system ignores configurations provided by incoming
1023
+ * messages and uses the pinned configuration instead.
1024
+ */
1025
+ pin(flowControlKey: string, options: PinFlowControlOptions): Promise<void>;
1026
+ /**
1027
+ * Remove the pinned configuration for a flow-control key.
1028
+ *
1029
+ * After unpinning, the system resumes updating the configuration
1030
+ * based on incoming messages.
1031
+ */
1032
+ unpin(flowControlKey: string, options: UnpinFlowControlOptions): Promise<void>;
1033
+ /**
1034
+ * Reset the rate configuration state for a flow-control key.
1035
+ *
1036
+ * Clears the current rate count and immediately ends the current period.
1037
+ * The current timestamp becomes the start of the new rate period.
1038
+ */
1039
+ resetRate(flowControlKey: string): Promise<void>;
1040
+ }
1041
+
823
1042
  declare class Chat {
824
1043
  private http;
825
1044
  private token;
@@ -1080,6 +1299,19 @@ type CreateScheduleRequest = {
1080
1299
  * @default undefined
1081
1300
  */
1082
1301
  label?: string;
1302
+ /**
1303
+ * Configure which fields should be redacted in logs.
1304
+ *
1305
+ * - `body: true` redacts the request body
1306
+ * - `header: true` redacts all headers
1307
+ * - `header: ["X"]` redacts specific headers (e.g., ["Authorization"])
1308
+ *
1309
+ * @default undefined
1310
+ */
1311
+ redact?: {
1312
+ body?: true;
1313
+ header?: true | string[];
1314
+ };
1083
1315
  } & Pick<PublishRequest, "retryDelay">;
1084
1316
  declare class Schedules {
1085
1317
  private readonly http;
@@ -2037,6 +2269,19 @@ type PublishRequest<TBody = BodyInit> = {
2037
2269
  * @default undefined
2038
2270
  */
2039
2271
  label?: string;
2272
+ /**
2273
+ * Configure which fields should be redacted in logs.
2274
+ *
2275
+ * - `body: true` redacts the request body
2276
+ * - `header: true` redacts all headers
2277
+ * - `header: ["X"]` redacts specific headers (e.g., ["Authorization"])
2278
+ *
2279
+ * @default undefined
2280
+ */
2281
+ redact?: {
2282
+ body?: true;
2283
+ header?: true | string[];
2284
+ };
2040
2285
  } & ({
2041
2286
  /**
2042
2287
  * The url where the message should be sent to.
@@ -2121,14 +2366,9 @@ type PublishJsonRequest = Omit<PublishRequest, "body"> & {
2121
2366
  body: unknown;
2122
2367
  };
2123
2368
  type LogsRequest = {
2124
- cursor?: string | number;
2125
2369
  /** Max 1000. Defaults to 10 when `groupBy` is used. */
2126
2370
  count?: number;
2127
- /** Defaults to `latestFirst` */
2128
- order?: "earliestFirst" | "latestFirst";
2129
- trimBody?: number;
2130
- filter?: LogsListFilters;
2131
- };
2371
+ } & LogsListRequest;
2132
2372
  /**
2133
2373
  * Deprecated. Use `LogsRequest` instead.
2134
2374
  *
@@ -2190,6 +2430,12 @@ declare class Client {
2190
2430
  * Create, read or delete schedules.
2191
2431
  */
2192
2432
  get schedules(): Schedules;
2433
+ /**
2434
+ * Access the flow control API.
2435
+ *
2436
+ * List, get, or reset flow controls.
2437
+ */
2438
+ get flowControl(): FlowControlApi;
2193
2439
  /**
2194
2440
  * Access the workflow API.
2195
2441
  *
@@ -2285,4 +2531,4 @@ type PublishResponse<TRequest> = TRequest extends {
2285
2531
  urlGroup: string;
2286
2532
  } ? PublishToUrlGroupsResponse : PublishToApiResponse;
2287
2533
 
2288
- export { type ChatCompletionChunk as $, type AddEndpointsRequest as A, BaseProvider as B, type ChatRateLimit as C, type LogPayload as D, type EmailOwner as E, type FailureFunctionPayload as F, type GetLogsResponse as G, type HTTPMethods as H, type EventPayload as I, type GetLogsPayload as J, type GetEventsPayload as K, type LLMOwner as L, type Message as M, type BodyInit as N, type HeadersInit as O, type ProviderInfo as P, type QueueRequest as Q, type RateLimit as R, type Step as S, type RequestOptions as T, type UniversalFilterFields as U, type VerifyRequest as V, type WithCursor as W, type FlowControl as X, Chat as Y, type ChatCompletionMessage as Z, type ChatCompletion as _, type ReceiverConfig as a, type StreamEnabled as a0, type StreamDisabled as a1, type StreamParameter as a2, type OpenAIChatModel as a3, type PromptChatRequest as a4, type ChatRequest as a5, upstash as a6, openai as a7, anthropic as a8, custom as a9, type RouteFunction as aa, type WorkflowServeOptions as ab, Workflow as ac, processOptions as ad, serve as ae, WorkflowContext as af, DisabledWorkflowContext as ag, type WorkflowClient as ah, type WorkflowReceiver as ai, StepTypes as aj, type StepType as ak, type RawStep as al, type SyncStepFunction as am, type AsyncStepFunction as an, type StepFunction as ao, type ParallelCallState as ap, type FinishCondition as aq, type RequiredExceptFields as ar, type LogLevel as as, type WorkflowLoggerOptions as at, WorkflowLogger as au, SignatureError as b, Receiver as c, type PublishBatchRequest as d, type PublishRequest as e, type PublishJsonRequest as f, type LogsRequest as g, type EventsRequest as h, type GetEventsResponse as i, Client as j, type PublishToApiResponse as k, type PublishToUrlResponse as l, type PublishToUrlGroupsResponse as m, type PublishResponse as n, type MessagePayload as o, Messages as p, type Schedule as q, type CreateScheduleRequest as r, Schedules as s, type Endpoint as t, type RemoveEndpointsRequest as u, type UrlGroup as v, UrlGroups as w, type State as x, type Log as y, type Event as z };
2534
+ export { type FlowControl as $, type AddEndpointsRequest as A, BaseProvider as B, type ChatRateLimit as C, UrlGroups as D, type EmailOwner as E, type FailureFunctionPayload as F, type GetLogsResponse as G, type State as H, type HTTPMethods as I, type Log as J, type Event as K, type LLMOwner as L, type Message as M, type LogPayload as N, type EventPayload as O, type ProviderInfo as P, type QueueRequest as Q, type RateLimit as R, type Step as S, type GetLogsPayload as T, type UnpinFlowControlOptions as U, type VerifyRequest as V, type GetEventsPayload as W, type WithCursor as X, type BodyInit as Y, type HeadersInit as Z, type RequestOptions as _, type ReceiverConfig as a, Chat as a0, type ChatCompletionMessage as a1, type ChatCompletion as a2, type ChatCompletionChunk as a3, type StreamEnabled as a4, type StreamDisabled as a5, type StreamParameter as a6, type OpenAIChatModel as a7, type PromptChatRequest as a8, type ChatRequest as a9, upstash as aa, openai as ab, anthropic as ac, custom as ad, type RouteFunction as ae, type WorkflowServeOptions as af, Workflow as ag, processOptions as ah, serve as ai, WorkflowContext as aj, DisabledWorkflowContext as ak, type WorkflowClient as al, type WorkflowReceiver as am, StepTypes as an, type StepType as ao, type RawStep as ap, type SyncStepFunction as aq, type AsyncStepFunction as ar, type StepFunction as as, type ParallelCallState as at, type FinishCondition as au, type RequiredExceptFields as av, type LogLevel as aw, type WorkflowLoggerOptions as ax, WorkflowLogger as ay, SignatureError as b, Receiver as c, type PublishBatchRequest as d, type PublishRequest as e, type PublishJsonRequest as f, type LogsRequest as g, type EventsRequest as h, type GetEventsResponse as i, Client as j, type PublishToApiResponse as k, type PublishToUrlResponse as l, type PublishToUrlGroupsResponse as m, type PublishResponse as n, type FlowControlInfo as o, type GlobalParallelismInfo as p, type PinFlowControlOptions as q, FlowControlApi as r, type MessagePayload as s, Messages as t, type Schedule as u, type CreateScheduleRequest as v, Schedules as w, type Endpoint as x, type RemoveEndpointsRequest as y, type UrlGroup as z };
package/cloudflare.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { aa as RouteFunction, ab as WorkflowServeOptions } from './client-Gv4WRTxB.mjs';
1
+ import { ae as RouteFunction, af as WorkflowServeOptions } from './client-CsM1dTnz.mjs';
2
2
  import 'neverthrow';
3
3
 
4
4
  type WorkflowBindings = {
package/cloudflare.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { aa as RouteFunction, ab as WorkflowServeOptions } from './client-Gv4WRTxB.js';
1
+ import { ae as RouteFunction, af as WorkflowServeOptions } from './client-CsM1dTnz.js';
2
2
  import 'neverthrow';
3
3
 
4
4
  type WorkflowBindings = {