@delta-base/core 1.4.0 → 1.5.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.
package/dist/index.d.ts CHANGED
@@ -81,6 +81,22 @@ declare namespace EventBusAPI {
81
81
  earliest: "earliest";
82
82
  }>>>;
83
83
  }, z.core.$strip>;
84
+ const ReplayRequestSchema: z.ZodObject<{
85
+ fromGlobalPosition: z.ZodOptional<z.ZodNumber>;
86
+ fromCreatedAt: z.ZodOptional<z.ZodString>;
87
+ toGlobalPosition: z.ZodOptional<z.ZodNumber>;
88
+ toCreatedAt: z.ZodOptional<z.ZodString>;
89
+ eventTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
90
+ }, z.core.$strip>;
91
+ const ReplayStatusResponseSchema: z.ZodObject<{
92
+ inProgress: z.ZodBoolean;
93
+ startPosition: z.ZodNullable<z.ZodNumber>;
94
+ targetPosition: z.ZodNullable<z.ZodNumber>;
95
+ currentPosition: z.ZodNumber;
96
+ processedCount: z.ZodNumber;
97
+ estimatedEvents: z.ZodNumber;
98
+ startedAt: z.ZodNullable<z.ZodString>;
99
+ }, z.core.$strip>;
84
100
  const UpdateSubscriptionRequestSchema: z.ZodObject<{
85
101
  eventFilter: z.ZodOptional<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"*">, z.ZodString, z.ZodString, z.ZodString]>, z.ZodArray<z.ZodUnion<readonly [z.ZodLiteral<"*">, z.ZodString, z.ZodString, z.ZodString]>>]>>;
86
102
  subscriberConfig: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -1008,6 +1024,222 @@ declare namespace EventBusAPI {
1008
1024
  status: 409;
1009
1025
  };
1010
1026
  };
1027
+ } & {
1028
+ "/event-stores/:eventStoreName/subscriptions/:subscriberId/replay": {
1029
+ $post: {
1030
+ input: {
1031
+ param: {
1032
+ eventStoreName: string;
1033
+ subscriberId: string;
1034
+ };
1035
+ } & {
1036
+ json: {
1037
+ fromGlobalPosition?: number | undefined;
1038
+ fromCreatedAt?: string | undefined;
1039
+ toGlobalPosition?: number | undefined;
1040
+ toCreatedAt?: string | undefined;
1041
+ eventTypes?: string[] | undefined;
1042
+ };
1043
+ };
1044
+ output: {
1045
+ error: string;
1046
+ message: string;
1047
+ details?: {
1048
+ [x: string]: any;
1049
+ } | undefined;
1050
+ };
1051
+ outputFormat: "json";
1052
+ status: 400;
1053
+ } | {
1054
+ input: {
1055
+ param: {
1056
+ eventStoreName: string;
1057
+ subscriberId: string;
1058
+ };
1059
+ } & {
1060
+ json: {
1061
+ fromGlobalPosition?: number | undefined;
1062
+ fromCreatedAt?: string | undefined;
1063
+ toGlobalPosition?: number | undefined;
1064
+ toCreatedAt?: string | undefined;
1065
+ eventTypes?: string[] | undefined;
1066
+ };
1067
+ };
1068
+ output: {
1069
+ error: string;
1070
+ message: string;
1071
+ details?: {
1072
+ [x: string]: any;
1073
+ } | undefined;
1074
+ };
1075
+ outputFormat: "json";
1076
+ status: 401;
1077
+ } | {
1078
+ input: {
1079
+ param: {
1080
+ eventStoreName: string;
1081
+ subscriberId: string;
1082
+ };
1083
+ } & {
1084
+ json: {
1085
+ fromGlobalPosition?: number | undefined;
1086
+ fromCreatedAt?: string | undefined;
1087
+ toGlobalPosition?: number | undefined;
1088
+ toCreatedAt?: string | undefined;
1089
+ eventTypes?: string[] | undefined;
1090
+ };
1091
+ };
1092
+ output: {
1093
+ error: string;
1094
+ message: string;
1095
+ details?: {
1096
+ [x: string]: any;
1097
+ } | undefined;
1098
+ };
1099
+ outputFormat: "json";
1100
+ status: 404;
1101
+ } | {
1102
+ input: {
1103
+ param: {
1104
+ eventStoreName: string;
1105
+ subscriberId: string;
1106
+ };
1107
+ } & {
1108
+ json: {
1109
+ fromGlobalPosition?: number | undefined;
1110
+ fromCreatedAt?: string | undefined;
1111
+ toGlobalPosition?: number | undefined;
1112
+ toCreatedAt?: string | undefined;
1113
+ eventTypes?: string[] | undefined;
1114
+ };
1115
+ };
1116
+ output: {
1117
+ error: string;
1118
+ message: string;
1119
+ details?: {
1120
+ [x: string]: any;
1121
+ } | undefined;
1122
+ };
1123
+ outputFormat: "json";
1124
+ status: 500;
1125
+ } | {
1126
+ input: {
1127
+ param: {
1128
+ eventStoreName: string;
1129
+ subscriberId: string;
1130
+ };
1131
+ } & {
1132
+ json: {
1133
+ fromGlobalPosition?: number | undefined;
1134
+ fromCreatedAt?: string | undefined;
1135
+ toGlobalPosition?: number | undefined;
1136
+ toCreatedAt?: string | undefined;
1137
+ eventTypes?: string[] | undefined;
1138
+ };
1139
+ };
1140
+ output: {
1141
+ error: string;
1142
+ message: string;
1143
+ details?: {
1144
+ [x: string]: any;
1145
+ } | undefined;
1146
+ };
1147
+ outputFormat: "json";
1148
+ status: 409;
1149
+ } | {
1150
+ input: {
1151
+ param: {
1152
+ eventStoreName: string;
1153
+ subscriberId: string;
1154
+ };
1155
+ } & {
1156
+ json: {
1157
+ fromGlobalPosition?: number | undefined;
1158
+ fromCreatedAt?: string | undefined;
1159
+ toGlobalPosition?: number | undefined;
1160
+ toCreatedAt?: string | undefined;
1161
+ eventTypes?: string[] | undefined;
1162
+ };
1163
+ };
1164
+ output: {
1165
+ message: string;
1166
+ fromPosition: number;
1167
+ estimatedEvents: number;
1168
+ };
1169
+ outputFormat: "json";
1170
+ status: 202;
1171
+ };
1172
+ };
1173
+ } & {
1174
+ "/event-stores/:eventStoreName/subscriptions/:subscriberId/replay": {
1175
+ $get: {
1176
+ input: {
1177
+ param: {
1178
+ eventStoreName: string;
1179
+ subscriberId: string;
1180
+ };
1181
+ };
1182
+ output: {
1183
+ error: string;
1184
+ message: string;
1185
+ details?: {
1186
+ [x: string]: any;
1187
+ } | undefined;
1188
+ };
1189
+ outputFormat: "json";
1190
+ status: 401;
1191
+ } | {
1192
+ input: {
1193
+ param: {
1194
+ eventStoreName: string;
1195
+ subscriberId: string;
1196
+ };
1197
+ };
1198
+ output: {
1199
+ error: string;
1200
+ message: string;
1201
+ details?: {
1202
+ [x: string]: any;
1203
+ } | undefined;
1204
+ };
1205
+ outputFormat: "json";
1206
+ status: 404;
1207
+ } | {
1208
+ input: {
1209
+ param: {
1210
+ eventStoreName: string;
1211
+ subscriberId: string;
1212
+ };
1213
+ };
1214
+ output: {
1215
+ error: string;
1216
+ message: string;
1217
+ details?: {
1218
+ [x: string]: any;
1219
+ } | undefined;
1220
+ };
1221
+ outputFormat: "json";
1222
+ status: 500;
1223
+ } | {
1224
+ input: {
1225
+ param: {
1226
+ eventStoreName: string;
1227
+ subscriberId: string;
1228
+ };
1229
+ };
1230
+ output: {
1231
+ inProgress: boolean;
1232
+ startPosition: number | null;
1233
+ targetPosition: number | null;
1234
+ currentPosition: number;
1235
+ processedCount: number;
1236
+ estimatedEvents: number;
1237
+ startedAt: string | null;
1238
+ };
1239
+ outputFormat: "json";
1240
+ status: 200;
1241
+ };
1242
+ };
1011
1243
  }, "/">;
1012
1244
  }
1013
1245
 
@@ -2997,6 +3229,14 @@ declare class EventBusDurableObject extends DurableObject<Env> {
2997
3229
  transaction_id: string;
2998
3230
  created: string;
2999
3231
  }[]): Promise<void>;
3232
+ /**
3233
+ * Coordinates fetching events for replay from EventStoreDO
3234
+ * @param fromGlobalPosition - The global position to start fetching from
3235
+ * @param limit - Maximum number of events to fetch
3236
+ * @param eventFilter - Optional event type filter (supports wildcards)
3237
+ * @returns Array of events for replay
3238
+ */
3239
+ getEventsForReplay(fromGlobalPosition: number, limit: number, eventFilter?: string): Promise<EventMessage[]>;
3000
3240
  private getMatchingSubscriptions;
3001
3241
  private requestDelivery;
3002
3242
  private processOutboxBatch;
@@ -3084,6 +3324,25 @@ declare class EventBusDurableObject extends DurableObject<Env> {
3084
3324
  legacyCount: number;
3085
3325
  legacyOutboxCount: number;
3086
3326
  }>;
3327
+ /**
3328
+ * Checks how many SubscriberDOs still need event_store_id backfilled.
3329
+ * Queries each SubscriberDO's config to check if event_store_id is set.
3330
+ */
3331
+ getBackfillStatus(): Promise<{
3332
+ total: number;
3333
+ backfilled: number;
3334
+ pending: number;
3335
+ complete: boolean;
3336
+ }>;
3337
+ /**
3338
+ * Backfills event_store_id on all SubscriberDOs for this EventBusDO.
3339
+ * Idempotent — safe to run multiple times. Calls setEventStoreId()
3340
+ * on each SubscriberDO that has a subscriber_do_id.
3341
+ */
3342
+ backfillEventStoreIds(): Promise<{
3343
+ updated: number;
3344
+ failed: number;
3345
+ }>;
3087
3346
  /**
3088
3347
  * Reconstructs an EventMessage from a subscriptions_outbox row
3089
3348
  */
@@ -3276,6 +3535,24 @@ declare class EventStoreDurableObject extends DurableObject<Env> {
3276
3535
  * @returns Promise resolving to filtered events and optional count
3277
3536
  */
3278
3537
  queryEvents(params?: EventsQueryParams): Promise<QueryEventsResult>;
3538
+ /**
3539
+ * Gets events for replay starting from a specific global position
3540
+ * @param fromGlobalPosition - The global position to start fetching from
3541
+ * @param limit - Maximum number of events to fetch
3542
+ * @param eventFilter - Optional event type filter (supports wildcards like "orders.*")
3543
+ * @returns Array of events for replay
3544
+ */
3545
+ getEventsForReplay(fromGlobalPosition: number, limit: number, eventFilter?: string): Promise<EventMessage[]>;
3546
+ /**
3547
+ * Resolves an ISO datetime to the nearest global position at or after that time.
3548
+ * Returns 0 if no events exist at or after the given datetime.
3549
+ */
3550
+ resolveCreatedAtToPosition(createdAt: string): number;
3551
+ /**
3552
+ * Returns the maximum global position across all non-archived events.
3553
+ * Returns 0 if no events exist.
3554
+ */
3555
+ getHeadPosition(): number;
3279
3556
  /**
3280
3557
  * Queries streams based on filtering parameters
3281
3558
  * @param params - Query parameters for filtering streams
@@ -3634,23 +3911,79 @@ declare class EventStoreManagerDurableObject extends DurableObject<Env> {
3634
3911
 
3635
3912
  interface SubscriberInitConfig {
3636
3913
  subscriberId: string;
3914
+ eventStoreId: string;
3637
3915
  subscriberType: SubscriberType;
3638
3916
  subscriberConfig: SubscriberTypeConfig['config'];
3639
3917
  eventFilter: string;
3640
3918
  retryPolicy: RetryPolicy;
3641
3919
  }
3920
+ interface ReplayOptions {
3921
+ fromGlobalPosition?: number;
3922
+ fromCreatedAt?: string;
3923
+ toGlobalPosition?: number;
3924
+ toCreatedAt?: string;
3925
+ eventTypes?: string[];
3926
+ }
3927
+ interface ReplayStatus {
3928
+ inProgress: boolean;
3929
+ startPosition: number | null;
3930
+ targetPosition: number | null;
3931
+ currentPosition: number;
3932
+ processedCount: number;
3933
+ estimatedEvents: number;
3934
+ startedAt: string | null;
3935
+ }
3642
3936
  type SubscriberStatus = 'ACTIVE' | 'PAUSED' | 'ERROR';
3643
3937
  declare class SubscriberDurableObject extends DurableObject<Env> {
3644
3938
  private readonly BATCH_SIZE;
3645
3939
  private readonly MAX_BATCHES_PER_ALARM;
3940
+ private readonly REPLAY_BATCH_SIZE;
3941
+ private readonly REPLAY_DELAY_MS;
3646
3942
  private isAlarmActive;
3647
3943
  private isSchedulingAlarm;
3648
3944
  sql: SqlStorage;
3649
3945
  constructor(state: DurableObjectState, env: Env);
3650
3946
  private initializeTables;
3947
+ /**
3948
+ * Handles schema migrations for existing SubscriberDOs.
3949
+ * Uses PRAGMA table_info to detect missing columns and adds them.
3950
+ * This runs in blockConcurrencyWhile so it's safe on every wake.
3951
+ */
3952
+ private migrateSchema;
3953
+ private ensureConfigColumn;
3954
+ private ensureCursorColumn;
3651
3955
  initialize(config: SubscriberInitConfig): void;
3956
+ /**
3957
+ * Returns whether this subscriber has event_store_id set in its config.
3958
+ * Used by the backfill status check.
3959
+ */
3960
+ hasEventStoreId(): boolean;
3961
+ /**
3962
+ * Sets the event store ID for this subscriber.
3963
+ * Used by backfill migration for existing DOs that were created
3964
+ * before event_store_id was added to the config table.
3965
+ */
3966
+ setEventStoreId(eventStoreId: string): void;
3652
3967
  setCursor(position: number): void;
3968
+ replay(options: ReplayOptions): Promise<void>;
3969
+ /**
3970
+ * Resolves an ISO datetime to the nearest global position at or after that time.
3971
+ */
3972
+ private resolveCreatedAtToPosition;
3973
+ /**
3974
+ * Fetches the current head (max) global position from EventStoreDO.
3975
+ */
3976
+ private fetchHeadPosition;
3977
+ getReplayStatus(): ReplayStatus;
3978
+ private getSubscriberId;
3979
+ private completeReplay;
3653
3980
  enqueue(events: EventMessage[]): Promise<void>;
3981
+ /**
3982
+ * Internal enqueue that inserts events without replay guard logic.
3983
+ * Used by both public enqueue() and processReplayBatch().
3984
+ */
3985
+ private enqueueInternal;
3986
+ private isReplayInProgress;
3654
3987
  private requestAlarm;
3655
3988
  private getConfigRow;
3656
3989
  private getSubscriberStatus;
@@ -3666,6 +3999,14 @@ declare class SubscriberDurableObject extends DurableObject<Env> {
3666
3999
  private updateRetryState;
3667
4000
  private deliverEvent;
3668
4001
  alarm(): Promise<void>;
4002
+ /**
4003
+ * Fetches and enqueues the next batch of replay events.
4004
+ * @returns The number of events fetched in this batch (0 means replay fetching is done).
4005
+ */
4006
+ private processReplayBatch;
4007
+ private getEventStoreId;
4008
+ private getEventFilter;
4009
+ private scheduleReplayAlarm;
3669
4010
  }
3670
4011
 
3671
4012
  interface ConnectionListOptions {
@@ -5788,6 +6129,222 @@ declare const routes: hono_hono_base.HonoBase<{
5788
6129
  status: 409;
5789
6130
  };
5790
6131
  };
6132
+ } & {
6133
+ "/event-stores/:eventStoreName/subscriptions/:subscriberId/replay": {
6134
+ $post: {
6135
+ input: {
6136
+ param: {
6137
+ eventStoreName: string;
6138
+ subscriberId: string;
6139
+ };
6140
+ } & {
6141
+ json: {
6142
+ fromGlobalPosition?: number | undefined;
6143
+ fromCreatedAt?: string | undefined;
6144
+ toGlobalPosition?: number | undefined;
6145
+ toCreatedAt?: string | undefined;
6146
+ eventTypes?: string[] | undefined;
6147
+ };
6148
+ };
6149
+ output: {
6150
+ error: string;
6151
+ message: string;
6152
+ details?: {
6153
+ [x: string]: any;
6154
+ } | undefined;
6155
+ };
6156
+ outputFormat: "json";
6157
+ status: 400;
6158
+ } | {
6159
+ input: {
6160
+ param: {
6161
+ eventStoreName: string;
6162
+ subscriberId: string;
6163
+ };
6164
+ } & {
6165
+ json: {
6166
+ fromGlobalPosition?: number | undefined;
6167
+ fromCreatedAt?: string | undefined;
6168
+ toGlobalPosition?: number | undefined;
6169
+ toCreatedAt?: string | undefined;
6170
+ eventTypes?: string[] | undefined;
6171
+ };
6172
+ };
6173
+ output: {
6174
+ error: string;
6175
+ message: string;
6176
+ details?: {
6177
+ [x: string]: any;
6178
+ } | undefined;
6179
+ };
6180
+ outputFormat: "json";
6181
+ status: 401;
6182
+ } | {
6183
+ input: {
6184
+ param: {
6185
+ eventStoreName: string;
6186
+ subscriberId: string;
6187
+ };
6188
+ } & {
6189
+ json: {
6190
+ fromGlobalPosition?: number | undefined;
6191
+ fromCreatedAt?: string | undefined;
6192
+ toGlobalPosition?: number | undefined;
6193
+ toCreatedAt?: string | undefined;
6194
+ eventTypes?: string[] | undefined;
6195
+ };
6196
+ };
6197
+ output: {
6198
+ error: string;
6199
+ message: string;
6200
+ details?: {
6201
+ [x: string]: any;
6202
+ } | undefined;
6203
+ };
6204
+ outputFormat: "json";
6205
+ status: 404;
6206
+ } | {
6207
+ input: {
6208
+ param: {
6209
+ eventStoreName: string;
6210
+ subscriberId: string;
6211
+ };
6212
+ } & {
6213
+ json: {
6214
+ fromGlobalPosition?: number | undefined;
6215
+ fromCreatedAt?: string | undefined;
6216
+ toGlobalPosition?: number | undefined;
6217
+ toCreatedAt?: string | undefined;
6218
+ eventTypes?: string[] | undefined;
6219
+ };
6220
+ };
6221
+ output: {
6222
+ error: string;
6223
+ message: string;
6224
+ details?: {
6225
+ [x: string]: any;
6226
+ } | undefined;
6227
+ };
6228
+ outputFormat: "json";
6229
+ status: 500;
6230
+ } | {
6231
+ input: {
6232
+ param: {
6233
+ eventStoreName: string;
6234
+ subscriberId: string;
6235
+ };
6236
+ } & {
6237
+ json: {
6238
+ fromGlobalPosition?: number | undefined;
6239
+ fromCreatedAt?: string | undefined;
6240
+ toGlobalPosition?: number | undefined;
6241
+ toCreatedAt?: string | undefined;
6242
+ eventTypes?: string[] | undefined;
6243
+ };
6244
+ };
6245
+ output: {
6246
+ error: string;
6247
+ message: string;
6248
+ details?: {
6249
+ [x: string]: any;
6250
+ } | undefined;
6251
+ };
6252
+ outputFormat: "json";
6253
+ status: 409;
6254
+ } | {
6255
+ input: {
6256
+ param: {
6257
+ eventStoreName: string;
6258
+ subscriberId: string;
6259
+ };
6260
+ } & {
6261
+ json: {
6262
+ fromGlobalPosition?: number | undefined;
6263
+ fromCreatedAt?: string | undefined;
6264
+ toGlobalPosition?: number | undefined;
6265
+ toCreatedAt?: string | undefined;
6266
+ eventTypes?: string[] | undefined;
6267
+ };
6268
+ };
6269
+ output: {
6270
+ message: string;
6271
+ fromPosition: number;
6272
+ estimatedEvents: number;
6273
+ };
6274
+ outputFormat: "json";
6275
+ status: 202;
6276
+ };
6277
+ };
6278
+ } & {
6279
+ "/event-stores/:eventStoreName/subscriptions/:subscriberId/replay": {
6280
+ $get: {
6281
+ input: {
6282
+ param: {
6283
+ eventStoreName: string;
6284
+ subscriberId: string;
6285
+ };
6286
+ };
6287
+ output: {
6288
+ error: string;
6289
+ message: string;
6290
+ details?: {
6291
+ [x: string]: any;
6292
+ } | undefined;
6293
+ };
6294
+ outputFormat: "json";
6295
+ status: 401;
6296
+ } | {
6297
+ input: {
6298
+ param: {
6299
+ eventStoreName: string;
6300
+ subscriberId: string;
6301
+ };
6302
+ };
6303
+ output: {
6304
+ error: string;
6305
+ message: string;
6306
+ details?: {
6307
+ [x: string]: any;
6308
+ } | undefined;
6309
+ };
6310
+ outputFormat: "json";
6311
+ status: 404;
6312
+ } | {
6313
+ input: {
6314
+ param: {
6315
+ eventStoreName: string;
6316
+ subscriberId: string;
6317
+ };
6318
+ };
6319
+ output: {
6320
+ error: string;
6321
+ message: string;
6322
+ details?: {
6323
+ [x: string]: any;
6324
+ } | undefined;
6325
+ };
6326
+ outputFormat: "json";
6327
+ status: 500;
6328
+ } | {
6329
+ input: {
6330
+ param: {
6331
+ eventStoreName: string;
6332
+ subscriberId: string;
6333
+ };
6334
+ };
6335
+ output: {
6336
+ inProgress: boolean;
6337
+ startPosition: number | null;
6338
+ targetPosition: number | null;
6339
+ currentPosition: number;
6340
+ processedCount: number;
6341
+ estimatedEvents: number;
6342
+ startedAt: string | null;
6343
+ };
6344
+ outputFormat: "json";
6345
+ status: 200;
6346
+ };
6347
+ };
5791
6348
  }, "/api"> | hono_types.MergeSchemaPath<{
5792
6349
  "/event-stores/:eventStoreName/events/ws": {
5793
6350
  $get: {