@durable-streams/server 0.3.1 → 0.3.3

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.
package/dist/index.d.cts CHANGED
@@ -1,3 +1,5 @@
1
+ import { IncomingMessage, ServerResponse } from "node:http";
2
+
1
3
  //#region src/types.d.ts
2
4
  /**
3
5
  * Types for the in-memory durable streams test server.
@@ -5,6 +7,12 @@
5
7
  /**
6
8
  * A single message in a stream.
7
9
  */
10
+ /**
11
+ * Types for the in-memory durable streams test server.
12
+ */
13
+ /**
14
+ * A single message in a stream.
15
+ */
8
16
  interface StreamMessage {
9
17
  /**
10
18
  * The raw bytes of the message.
@@ -172,6 +180,13 @@ interface TestServerOptions {
172
180
  * Default: October 9, 2024 00:00:00 UTC.
173
181
  */
174
182
  cursorEpoch?: Date;
183
+ /**
184
+ * Enable webhook subscriptions.
185
+ * Pull-wake subscription routes are always mounted, but type=webhook creates
186
+ * are rejected unless this is true.
187
+ * Default: false.
188
+ */
189
+ webhooks?: boolean;
175
190
  }
176
191
  /**
177
192
  * Producer state for idempotent writes.
@@ -466,7 +481,6 @@ interface FileBackedStreamStoreOptions {
466
481
  */
467
482
  declare class FileBackedStreamStore {
468
483
  private db;
469
- private fileManager;
470
484
  private fileHandlePool;
471
485
  private pendingLongPolls;
472
486
  private dataDir;
@@ -475,6 +489,13 @@ declare class FileBackedStreamStore {
475
489
  * Key: "{streamPath}:{producerId}"
476
490
  */
477
491
  private producerLocks;
492
+ /**
493
+ * Per-stream append locks. Serializes the read-modify-write of currentOffset
494
+ * across all concurrent appenders on the same stream so the LMDB-tracked
495
+ * offset cannot drift behind the file's actual byte position.
496
+ * Key: streamPath
497
+ */
498
+ private streamAppendLocks;
478
499
  constructor(options: FileBackedStreamStoreOptions);
479
500
  /**
480
501
  * Recover streams from disk on startup.
@@ -505,6 +526,15 @@ declare class FileBackedStreamStore {
505
526
  */
506
527
  private acquireProducerLock;
507
528
  /**
529
+ * Acquire a per-stream append lock that serializes the read-modify-write
530
+ * of currentOffset across all concurrent appenders on the same stream.
531
+ * Without this, two concurrent appends can read the same starting
532
+ * currentOffset, both compute their newOffset, both write a frame to the
533
+ * file, but only one of their LMDB updates wins — leaving currentOffset
534
+ * lagging the file's actual byte position. Returns a release function.
535
+ */
536
+ private acquireStreamAppendLock;
537
+ /**
508
538
  * Get the current epoch for a producer on a stream.
509
539
  * Returns undefined if the producer doesn't exist or stream not found.
510
540
  */
@@ -550,9 +580,15 @@ declare class FileBackedStreamStore {
550
580
  * whose refcount drops to zero.
551
581
  */
552
582
  private deleteWithCascade;
583
+ /**
584
+ * Public append entry point. Serializes concurrent appends to the same
585
+ * stream so the read-modify-write of currentOffset cannot interleave —
586
+ * see acquireStreamAppendLock for the underlying race.
587
+ */
553
588
  append(streamPath: string, data: Uint8Array, options?: AppendOptions & {
554
589
  isInitialCreate?: boolean;
555
590
  }): Promise<StreamMessage | AppendResult | null>;
591
+ private appendInner;
556
592
  /**
557
593
  * Append with producer serialization for concurrent request handling.
558
594
  * This ensures that validation+append is atomic per producer.
@@ -673,6 +709,8 @@ declare class DurableStreamTestServer {
673
709
  private isShuttingDown;
674
710
  /** Injected faults for testing retry/resilience */
675
711
  private injectedFaults;
712
+ private subscriptionManager;
713
+ private subscriptionRoutes;
676
714
  constructor(options?: TestServerOptions);
677
715
  /**
678
716
  * Start the server.
@@ -742,6 +780,7 @@ declare class DurableStreamTestServer {
742
780
  * Handle POST - append data
743
781
  */
744
782
  private handleAppend;
783
+ private notifyStreamAppend;
745
784
  /**
746
785
  * Handle DELETE - delete stream
747
786
  */
@@ -864,4 +903,221 @@ declare function generateResponseCursor(clientCursor: string | undefined, option
864
903
  declare function handleCursorCollision(currentCursor: string, previousCursor: string | undefined, options?: CursorOptions): string;
865
904
 
866
905
  //#endregion
867
- export { CursorOptions, DEFAULT_CURSOR_EPOCH, DEFAULT_CURSOR_INTERVAL_SECONDS, DurableStreamTestServer, FileBackedStreamStore, PendingLongPoll, Stream, StreamLifecycleEvent, StreamLifecycleHook, StreamMessage, StreamStore, TestServerOptions, calculateCursor, createRegistryHooks, decodeStreamPath, encodeStreamPath, generateResponseCursor, handleCursorCollision };
906
+ //#region src/crypto.d.ts
907
+ interface WebhookPublicJwk {
908
+ kty: `OKP`;
909
+ crv: `Ed25519`;
910
+ x: string;
911
+ kid: string;
912
+ use: `sig`;
913
+ alg: `EdDSA`;
914
+ }
915
+ interface WebhookJwks {
916
+ keys: Array<WebhookPublicJwk>;
917
+ }
918
+ /**
919
+ * Generate a unique wake ID.
920
+ */
921
+
922
+ declare function getWebhookJwks(): WebhookJwks;
923
+
924
+ //#endregion
925
+ //#region src/subscription-types.d.ts
926
+ /**
927
+ * Sign a webhook payload for the Webhook-Signature header.
928
+ * Format: t=<timestamp>,kid=<key_id>,ed25519=<base64url_signature>
929
+ */
930
+ type SubscriptionType = `webhook` | `pull-wake`;
931
+ type SubscriptionStatus = `active` | `failed`;
932
+ type SubscriptionLinkType = `glob` | `explicit`;
933
+ interface SubscriptionStreamLink {
934
+ path: string;
935
+ link_types: Set<SubscriptionLinkType>;
936
+ acked_offset: string;
937
+ }
938
+ interface SubscriptionWebhookConfig {
939
+ url: string;
940
+ }
941
+ interface SubscriptionRecord {
942
+ id: string;
943
+ type: SubscriptionType;
944
+ pattern?: string;
945
+ webhook?: SubscriptionWebhookConfig;
946
+ wake_stream?: string;
947
+ lease_ttl_ms: number;
948
+ description?: string;
949
+ created_at: string;
950
+ status: SubscriptionStatus;
951
+ config_hash: string;
952
+ streams: Map<string, SubscriptionStreamLink>;
953
+ generation: number;
954
+ wake_id: string | null;
955
+ wake_snapshot: Map<string, string>;
956
+ token: string | null;
957
+ holder: string | null;
958
+ lease_timer: ReturnType<typeof setTimeout> | null;
959
+ retry_count: number;
960
+ retry_timer: ReturnType<typeof setTimeout> | null;
961
+ next_attempt_at: number | null;
962
+ }
963
+ interface SubscriptionStreamInfo {
964
+ path: string;
965
+ link_type: SubscriptionLinkType;
966
+ acked_offset: string;
967
+ tail_offset: string;
968
+ has_pending: boolean;
969
+ }
970
+ interface SubscriptionCreateInput {
971
+ type: SubscriptionType;
972
+ pattern?: string;
973
+ streams: Array<string>;
974
+ webhook?: {
975
+ url: string;
976
+ };
977
+ wake_stream?: string;
978
+ lease_ttl_ms: number;
979
+ description?: string;
980
+ }
981
+ interface SubscriptionCallbackRequest {
982
+ wake_id?: string;
983
+ generation?: number;
984
+ acks?: Array<{
985
+ stream?: string;
986
+ path?: string;
987
+ offset: string;
988
+ }>;
989
+ done?: boolean;
990
+ }
991
+ type SubscriptionErrorCode = `INVALID_REQUEST` | `SUBSCRIPTION_NOT_FOUND` | `SUBSCRIPTION_ALREADY_EXISTS` | `WEBHOOK_URL_REJECTED` | `TOKEN_INVALID` | `TOKEN_EXPIRED` | `FENCED` | `ALREADY_CLAIMED` | `NO_PENDING_WORK` | `INVALID_OFFSET`;
992
+ interface SubscriptionError {
993
+ code: SubscriptionErrorCode;
994
+ message: string;
995
+ current_holder?: string;
996
+ generation?: number;
997
+ }
998
+
999
+ //#endregion
1000
+ //#region src/subscription-manager.d.ts
1001
+ interface StreamLike {
1002
+ currentOffset: string;
1003
+ softDeleted?: boolean;
1004
+ }
1005
+ interface SubscriptionStreamStore {
1006
+ has: (path: string) => boolean;
1007
+ get: (path: string) => StreamLike | undefined;
1008
+ list: () => Array<string>;
1009
+ append: (path: string, data: Uint8Array) => unknown;
1010
+ }
1011
+ declare function validateWebhookUrl(rawUrl: string): {
1012
+ ok: true;
1013
+ } | {
1014
+ ok: false;
1015
+ message: string;
1016
+ };
1017
+ declare class SubscriptionManager {
1018
+ private readonly subscriptions;
1019
+ private readonly streamStore;
1020
+ private readonly callbackBaseUrl;
1021
+ private readonly webhooksEnabled;
1022
+ private isShuttingDown;
1023
+ constructor(opts: {
1024
+ callbackBaseUrl: string;
1025
+ streamStore: SubscriptionStreamStore;
1026
+ webhooksEnabled?: boolean;
1027
+ });
1028
+ createOrConfirm(id: string, input: SubscriptionCreateInput): {
1029
+ subscription: SubscriptionRecord;
1030
+ created: boolean;
1031
+ } | {
1032
+ error: SubscriptionError;
1033
+ };
1034
+ get(id: string): SubscriptionRecord | undefined;
1035
+ delete(id: string): boolean;
1036
+ addExplicitStreams(id: string, streams: Array<string>): boolean;
1037
+ removeExplicitStream(id: string, streamPath: string): boolean;
1038
+ onStreamAppend(absolutePath: string): Promise<void>;
1039
+ onStreamDeleted(absolutePath: string): void;
1040
+ handleWebhookCallback(id: string, token: string, request: SubscriptionCallbackRequest): Promise<{
1041
+ status: number;
1042
+ body: Record<string, unknown>;
1043
+ }>;
1044
+ claim(id: string, worker: string): Promise<{
1045
+ status: number;
1046
+ body: Record<string, unknown>;
1047
+ }>;
1048
+ ack(id: string, token: string, request: SubscriptionCallbackRequest): Promise<{
1049
+ status: number;
1050
+ body: Record<string, unknown>;
1051
+ }>;
1052
+ release(id: string, token: string, request: SubscriptionCallbackRequest): Promise<{
1053
+ status: number;
1054
+ body?: Record<string, unknown>;
1055
+ }>;
1056
+ serialize(subscription: SubscriptionRecord): Record<string, unknown>;
1057
+ getWebhookJwks(): ReturnType<typeof getWebhookJwks>;
1058
+ shutdown(): void;
1059
+ private maybeWake;
1060
+ private createWake;
1061
+ private deliverWebhook;
1062
+ private scheduleWebhookRetry;
1063
+ private writePullWakeEvent;
1064
+ private autoAckWakeSnapshot;
1065
+ private applyAcks;
1066
+ private validateWakeToken;
1067
+ private triggerNextWakeIfPending;
1068
+ private hasPendingWork;
1069
+ private firstPendingStream;
1070
+ private streamInfos;
1071
+ private linkStream;
1072
+ private listStreams;
1073
+ private getTailOffset;
1074
+ private subscriptionActionUrl;
1075
+ private webhookJwksUrl;
1076
+ private webhookSigningMetadata;
1077
+ private extendLease;
1078
+ private clearLease;
1079
+ private tokenSubject;
1080
+ private errorResponse;
1081
+ }
1082
+
1083
+ //#endregion
1084
+ //#region src/subscription-routes.d.ts
1085
+ declare class SubscriptionRoutes {
1086
+ private readonly manager;
1087
+ constructor(manager: SubscriptionManager);
1088
+ handleRequest(method: string, path: string, req: IncomingMessage, res: ServerResponse): Promise<boolean>;
1089
+ private handleBase;
1090
+ private handleJwks;
1091
+ private handleStreams;
1092
+ private handleStream;
1093
+ private handleCallback;
1094
+ private handleClaim;
1095
+ private handleAck;
1096
+ private handleRelease;
1097
+ private parseCreateInput;
1098
+ private parseRoute;
1099
+ private readBearerToken;
1100
+ private readJson;
1101
+ private writeManagerResult;
1102
+ private writeJson;
1103
+ private writeError;
1104
+ private methodNotAllowed;
1105
+ }
1106
+
1107
+ //#endregion
1108
+ //#region src/glob.d.ts
1109
+ /**
1110
+ * Glob pattern matching for webhook subscription patterns.
1111
+ *
1112
+ * Supports:
1113
+ * - `*` matches exactly one path segment
1114
+ * - `**` matches zero or more path segments (recursive)
1115
+ * - Literal segments match exactly
1116
+ */
1117
+ /**
1118
+ * Match a stream path against a glob pattern.
1119
+ */
1120
+ declare function globMatch(pattern: string, path: string): boolean;
1121
+
1122
+ //#endregion
1123
+ export { CursorOptions, DEFAULT_CURSOR_EPOCH, DEFAULT_CURSOR_INTERVAL_SECONDS, DurableStreamTestServer, FileBackedStreamStore, PendingLongPoll, Stream, StreamLifecycleEvent, StreamLifecycleHook, StreamMessage, StreamStore, SubscriptionCallbackRequest, SubscriptionCreateInput, SubscriptionError, SubscriptionErrorCode, SubscriptionManager, SubscriptionRecord, SubscriptionRoutes, SubscriptionStatus, SubscriptionStreamInfo, SubscriptionStreamLink, SubscriptionType, TestServerOptions, calculateCursor, createRegistryHooks, decodeStreamPath, encodeStreamPath, generateResponseCursor, globMatch, handleCursorCollision, validateWebhookUrl };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { IncomingMessage, ServerResponse } from "node:http";
2
+
1
3
  //#region src/types.d.ts
2
4
  /**
3
5
  * Types for the in-memory durable streams test server.
@@ -5,6 +7,12 @@
5
7
  /**
6
8
  * A single message in a stream.
7
9
  */
10
+ /**
11
+ * Types for the in-memory durable streams test server.
12
+ */
13
+ /**
14
+ * A single message in a stream.
15
+ */
8
16
  interface StreamMessage {
9
17
  /**
10
18
  * The raw bytes of the message.
@@ -172,6 +180,13 @@ interface TestServerOptions {
172
180
  * Default: October 9, 2024 00:00:00 UTC.
173
181
  */
174
182
  cursorEpoch?: Date;
183
+ /**
184
+ * Enable webhook subscriptions.
185
+ * Pull-wake subscription routes are always mounted, but type=webhook creates
186
+ * are rejected unless this is true.
187
+ * Default: false.
188
+ */
189
+ webhooks?: boolean;
175
190
  }
176
191
  /**
177
192
  * Producer state for idempotent writes.
@@ -466,7 +481,6 @@ interface FileBackedStreamStoreOptions {
466
481
  */
467
482
  declare class FileBackedStreamStore {
468
483
  private db;
469
- private fileManager;
470
484
  private fileHandlePool;
471
485
  private pendingLongPolls;
472
486
  private dataDir;
@@ -475,6 +489,13 @@ declare class FileBackedStreamStore {
475
489
  * Key: "{streamPath}:{producerId}"
476
490
  */
477
491
  private producerLocks;
492
+ /**
493
+ * Per-stream append locks. Serializes the read-modify-write of currentOffset
494
+ * across all concurrent appenders on the same stream so the LMDB-tracked
495
+ * offset cannot drift behind the file's actual byte position.
496
+ * Key: streamPath
497
+ */
498
+ private streamAppendLocks;
478
499
  constructor(options: FileBackedStreamStoreOptions);
479
500
  /**
480
501
  * Recover streams from disk on startup.
@@ -505,6 +526,15 @@ declare class FileBackedStreamStore {
505
526
  */
506
527
  private acquireProducerLock;
507
528
  /**
529
+ * Acquire a per-stream append lock that serializes the read-modify-write
530
+ * of currentOffset across all concurrent appenders on the same stream.
531
+ * Without this, two concurrent appends can read the same starting
532
+ * currentOffset, both compute their newOffset, both write a frame to the
533
+ * file, but only one of their LMDB updates wins — leaving currentOffset
534
+ * lagging the file's actual byte position. Returns a release function.
535
+ */
536
+ private acquireStreamAppendLock;
537
+ /**
508
538
  * Get the current epoch for a producer on a stream.
509
539
  * Returns undefined if the producer doesn't exist or stream not found.
510
540
  */
@@ -550,9 +580,15 @@ declare class FileBackedStreamStore {
550
580
  * whose refcount drops to zero.
551
581
  */
552
582
  private deleteWithCascade;
583
+ /**
584
+ * Public append entry point. Serializes concurrent appends to the same
585
+ * stream so the read-modify-write of currentOffset cannot interleave —
586
+ * see acquireStreamAppendLock for the underlying race.
587
+ */
553
588
  append(streamPath: string, data: Uint8Array, options?: AppendOptions & {
554
589
  isInitialCreate?: boolean;
555
590
  }): Promise<StreamMessage | AppendResult | null>;
591
+ private appendInner;
556
592
  /**
557
593
  * Append with producer serialization for concurrent request handling.
558
594
  * This ensures that validation+append is atomic per producer.
@@ -673,6 +709,8 @@ declare class DurableStreamTestServer {
673
709
  private isShuttingDown;
674
710
  /** Injected faults for testing retry/resilience */
675
711
  private injectedFaults;
712
+ private subscriptionManager;
713
+ private subscriptionRoutes;
676
714
  constructor(options?: TestServerOptions);
677
715
  /**
678
716
  * Start the server.
@@ -742,6 +780,7 @@ declare class DurableStreamTestServer {
742
780
  * Handle POST - append data
743
781
  */
744
782
  private handleAppend;
783
+ private notifyStreamAppend;
745
784
  /**
746
785
  * Handle DELETE - delete stream
747
786
  */
@@ -864,4 +903,221 @@ declare function generateResponseCursor(clientCursor: string | undefined, option
864
903
  declare function handleCursorCollision(currentCursor: string, previousCursor: string | undefined, options?: CursorOptions): string;
865
904
 
866
905
  //#endregion
867
- export { CursorOptions, DEFAULT_CURSOR_EPOCH, DEFAULT_CURSOR_INTERVAL_SECONDS, DurableStreamTestServer, FileBackedStreamStore, PendingLongPoll, Stream, StreamLifecycleEvent, StreamLifecycleHook, StreamMessage, StreamStore, TestServerOptions, calculateCursor, createRegistryHooks, decodeStreamPath, encodeStreamPath, generateResponseCursor, handleCursorCollision };
906
+ //#region src/crypto.d.ts
907
+ interface WebhookPublicJwk {
908
+ kty: `OKP`;
909
+ crv: `Ed25519`;
910
+ x: string;
911
+ kid: string;
912
+ use: `sig`;
913
+ alg: `EdDSA`;
914
+ }
915
+ interface WebhookJwks {
916
+ keys: Array<WebhookPublicJwk>;
917
+ }
918
+ /**
919
+ * Generate a unique wake ID.
920
+ */
921
+
922
+ declare function getWebhookJwks(): WebhookJwks;
923
+
924
+ //#endregion
925
+ //#region src/subscription-types.d.ts
926
+ /**
927
+ * Sign a webhook payload for the Webhook-Signature header.
928
+ * Format: t=<timestamp>,kid=<key_id>,ed25519=<base64url_signature>
929
+ */
930
+ type SubscriptionType = `webhook` | `pull-wake`;
931
+ type SubscriptionStatus = `active` | `failed`;
932
+ type SubscriptionLinkType = `glob` | `explicit`;
933
+ interface SubscriptionStreamLink {
934
+ path: string;
935
+ link_types: Set<SubscriptionLinkType>;
936
+ acked_offset: string;
937
+ }
938
+ interface SubscriptionWebhookConfig {
939
+ url: string;
940
+ }
941
+ interface SubscriptionRecord {
942
+ id: string;
943
+ type: SubscriptionType;
944
+ pattern?: string;
945
+ webhook?: SubscriptionWebhookConfig;
946
+ wake_stream?: string;
947
+ lease_ttl_ms: number;
948
+ description?: string;
949
+ created_at: string;
950
+ status: SubscriptionStatus;
951
+ config_hash: string;
952
+ streams: Map<string, SubscriptionStreamLink>;
953
+ generation: number;
954
+ wake_id: string | null;
955
+ wake_snapshot: Map<string, string>;
956
+ token: string | null;
957
+ holder: string | null;
958
+ lease_timer: ReturnType<typeof setTimeout> | null;
959
+ retry_count: number;
960
+ retry_timer: ReturnType<typeof setTimeout> | null;
961
+ next_attempt_at: number | null;
962
+ }
963
+ interface SubscriptionStreamInfo {
964
+ path: string;
965
+ link_type: SubscriptionLinkType;
966
+ acked_offset: string;
967
+ tail_offset: string;
968
+ has_pending: boolean;
969
+ }
970
+ interface SubscriptionCreateInput {
971
+ type: SubscriptionType;
972
+ pattern?: string;
973
+ streams: Array<string>;
974
+ webhook?: {
975
+ url: string;
976
+ };
977
+ wake_stream?: string;
978
+ lease_ttl_ms: number;
979
+ description?: string;
980
+ }
981
+ interface SubscriptionCallbackRequest {
982
+ wake_id?: string;
983
+ generation?: number;
984
+ acks?: Array<{
985
+ stream?: string;
986
+ path?: string;
987
+ offset: string;
988
+ }>;
989
+ done?: boolean;
990
+ }
991
+ type SubscriptionErrorCode = `INVALID_REQUEST` | `SUBSCRIPTION_NOT_FOUND` | `SUBSCRIPTION_ALREADY_EXISTS` | `WEBHOOK_URL_REJECTED` | `TOKEN_INVALID` | `TOKEN_EXPIRED` | `FENCED` | `ALREADY_CLAIMED` | `NO_PENDING_WORK` | `INVALID_OFFSET`;
992
+ interface SubscriptionError {
993
+ code: SubscriptionErrorCode;
994
+ message: string;
995
+ current_holder?: string;
996
+ generation?: number;
997
+ }
998
+
999
+ //#endregion
1000
+ //#region src/subscription-manager.d.ts
1001
+ interface StreamLike {
1002
+ currentOffset: string;
1003
+ softDeleted?: boolean;
1004
+ }
1005
+ interface SubscriptionStreamStore {
1006
+ has: (path: string) => boolean;
1007
+ get: (path: string) => StreamLike | undefined;
1008
+ list: () => Array<string>;
1009
+ append: (path: string, data: Uint8Array) => unknown;
1010
+ }
1011
+ declare function validateWebhookUrl(rawUrl: string): {
1012
+ ok: true;
1013
+ } | {
1014
+ ok: false;
1015
+ message: string;
1016
+ };
1017
+ declare class SubscriptionManager {
1018
+ private readonly subscriptions;
1019
+ private readonly streamStore;
1020
+ private readonly callbackBaseUrl;
1021
+ private readonly webhooksEnabled;
1022
+ private isShuttingDown;
1023
+ constructor(opts: {
1024
+ callbackBaseUrl: string;
1025
+ streamStore: SubscriptionStreamStore;
1026
+ webhooksEnabled?: boolean;
1027
+ });
1028
+ createOrConfirm(id: string, input: SubscriptionCreateInput): {
1029
+ subscription: SubscriptionRecord;
1030
+ created: boolean;
1031
+ } | {
1032
+ error: SubscriptionError;
1033
+ };
1034
+ get(id: string): SubscriptionRecord | undefined;
1035
+ delete(id: string): boolean;
1036
+ addExplicitStreams(id: string, streams: Array<string>): boolean;
1037
+ removeExplicitStream(id: string, streamPath: string): boolean;
1038
+ onStreamAppend(absolutePath: string): Promise<void>;
1039
+ onStreamDeleted(absolutePath: string): void;
1040
+ handleWebhookCallback(id: string, token: string, request: SubscriptionCallbackRequest): Promise<{
1041
+ status: number;
1042
+ body: Record<string, unknown>;
1043
+ }>;
1044
+ claim(id: string, worker: string): Promise<{
1045
+ status: number;
1046
+ body: Record<string, unknown>;
1047
+ }>;
1048
+ ack(id: string, token: string, request: SubscriptionCallbackRequest): Promise<{
1049
+ status: number;
1050
+ body: Record<string, unknown>;
1051
+ }>;
1052
+ release(id: string, token: string, request: SubscriptionCallbackRequest): Promise<{
1053
+ status: number;
1054
+ body?: Record<string, unknown>;
1055
+ }>;
1056
+ serialize(subscription: SubscriptionRecord): Record<string, unknown>;
1057
+ getWebhookJwks(): ReturnType<typeof getWebhookJwks>;
1058
+ shutdown(): void;
1059
+ private maybeWake;
1060
+ private createWake;
1061
+ private deliverWebhook;
1062
+ private scheduleWebhookRetry;
1063
+ private writePullWakeEvent;
1064
+ private autoAckWakeSnapshot;
1065
+ private applyAcks;
1066
+ private validateWakeToken;
1067
+ private triggerNextWakeIfPending;
1068
+ private hasPendingWork;
1069
+ private firstPendingStream;
1070
+ private streamInfos;
1071
+ private linkStream;
1072
+ private listStreams;
1073
+ private getTailOffset;
1074
+ private subscriptionActionUrl;
1075
+ private webhookJwksUrl;
1076
+ private webhookSigningMetadata;
1077
+ private extendLease;
1078
+ private clearLease;
1079
+ private tokenSubject;
1080
+ private errorResponse;
1081
+ }
1082
+
1083
+ //#endregion
1084
+ //#region src/subscription-routes.d.ts
1085
+ declare class SubscriptionRoutes {
1086
+ private readonly manager;
1087
+ constructor(manager: SubscriptionManager);
1088
+ handleRequest(method: string, path: string, req: IncomingMessage, res: ServerResponse): Promise<boolean>;
1089
+ private handleBase;
1090
+ private handleJwks;
1091
+ private handleStreams;
1092
+ private handleStream;
1093
+ private handleCallback;
1094
+ private handleClaim;
1095
+ private handleAck;
1096
+ private handleRelease;
1097
+ private parseCreateInput;
1098
+ private parseRoute;
1099
+ private readBearerToken;
1100
+ private readJson;
1101
+ private writeManagerResult;
1102
+ private writeJson;
1103
+ private writeError;
1104
+ private methodNotAllowed;
1105
+ }
1106
+
1107
+ //#endregion
1108
+ //#region src/glob.d.ts
1109
+ /**
1110
+ * Glob pattern matching for webhook subscription patterns.
1111
+ *
1112
+ * Supports:
1113
+ * - `*` matches exactly one path segment
1114
+ * - `**` matches zero or more path segments (recursive)
1115
+ * - Literal segments match exactly
1116
+ */
1117
+ /**
1118
+ * Match a stream path against a glob pattern.
1119
+ */
1120
+ declare function globMatch(pattern: string, path: string): boolean;
1121
+
1122
+ //#endregion
1123
+ export { CursorOptions, DEFAULT_CURSOR_EPOCH, DEFAULT_CURSOR_INTERVAL_SECONDS, DurableStreamTestServer, FileBackedStreamStore, PendingLongPoll, Stream, StreamLifecycleEvent, StreamLifecycleHook, StreamMessage, StreamStore, SubscriptionCallbackRequest, SubscriptionCreateInput, SubscriptionError, SubscriptionErrorCode, SubscriptionManager, SubscriptionRecord, SubscriptionRoutes, SubscriptionStatus, SubscriptionStreamInfo, SubscriptionStreamLink, SubscriptionType, TestServerOptions, calculateCursor, createRegistryHooks, decodeStreamPath, encodeStreamPath, generateResponseCursor, globMatch, handleCursorCollision, validateWebhookUrl };