dynamodb-reactive 0.1.0 → 0.1.1

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/server.d.ts CHANGED
@@ -1,2 +1,631 @@
1
- export * from '@dynamodb-reactive/server';
2
- //# sourceMappingURL=server.d.ts.map
1
+ import { z } from 'zod';
2
+ import { D as DynamoTable } from './table-CSJysZPQ.js';
3
+ import { A as AnyDynamoTable, F as FieldRef, a as FilterCondition, Q as QueryMetadata, J as JsonPatch } from './types-Ci7IieDA.js';
4
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
5
+ import { DynamoDBStreamEvent, APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
6
+
7
+ /**
8
+ * Context type for procedures
9
+ */
10
+ interface ProcedureContext<TContext = unknown> {
11
+ ctx: TContext & {
12
+ db: DatabaseContext;
13
+ };
14
+ input: unknown;
15
+ }
16
+ /**
17
+ * Database context provided to procedures
18
+ */
19
+ interface DatabaseContext {
20
+ query<TTable extends AnyDynamoTable>(table: TTable): QueryBuilder<TTable>;
21
+ get<TTable extends AnyDynamoTable>(table: TTable, key: TableKeyInput<TTable>): Promise<TableItem<TTable> | null>;
22
+ put<TTable extends AnyDynamoTable>(table: TTable, item: TableItem<TTable>): Promise<void>;
23
+ delete<TTable extends AnyDynamoTable>(table: TTable, key: TableKeyInput<TTable>): Promise<void>;
24
+ update<TTable extends AnyDynamoTable>(table: TTable, key: TableKeyInput<TTable>, updates: Partial<TableItem<TTable>>): Promise<TableItem<TTable>>;
25
+ }
26
+ /**
27
+ * Extract the item type from a DynamoTable
28
+ * Works with both the DynamoTable class and AnyDynamoTable interface
29
+ */
30
+ type TableItem<T extends AnyDynamoTable> = T extends DynamoTable<infer TSchema, any, any, any> ? z.infer<TSchema> : T extends {
31
+ schema: infer TSchema extends z.ZodTypeAny;
32
+ } ? z.infer<TSchema> : never;
33
+ /**
34
+ * Extract key input type from a DynamoTable
35
+ * Works with both the DynamoTable class and AnyDynamoTable interface
36
+ */
37
+ type TableKeyInput<T extends AnyDynamoTable> = T extends DynamoTable<infer TSchema, infer TPk, infer TSk, any> ? TSk extends keyof z.infer<TSchema> ? Pick<z.infer<TSchema>, TPk | TSk> : Pick<z.infer<TSchema>, TPk> : T extends {
38
+ schema: infer TSchema extends z.ZodTypeAny;
39
+ pk: infer TPk;
40
+ sk: infer TSk;
41
+ } ? TSk extends keyof z.infer<TSchema> ? Pick<z.infer<TSchema>, (TPk & keyof z.infer<TSchema>) | TSk> : Pick<z.infer<TSchema>, TPk & keyof z.infer<TSchema>> : never;
42
+ /**
43
+ * Query builder for type-safe DynamoDB queries
44
+ */
45
+ interface QueryBuilder<TTable extends AnyDynamoTable> {
46
+ filter(fn: (q: FilterBuilder<TTable>) => FilterCondition): QueryBuilder<TTable>;
47
+ useIndex(indexName: keyof TableIndexes<TTable>): QueryBuilder<TTable>;
48
+ take(limit: number): QueryBuilder<TTable>;
49
+ startFrom(key: TableKeyInput<TTable>): QueryBuilder<TTable>;
50
+ sortAscending(): QueryBuilder<TTable>;
51
+ sortDescending(): QueryBuilder<TTable>;
52
+ execute(): Promise<TableItem<TTable>[]>;
53
+ }
54
+ /**
55
+ * Filter builder for query conditions
56
+ */
57
+ interface FilterBuilder<TTable extends AnyDynamoTable> {
58
+ eq<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
59
+ ne<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
60
+ gt<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
61
+ gte<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
62
+ lt<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
63
+ lte<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
64
+ between<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, lower: TableItem<TTable>[K], upper: TableItem<TTable>[K]): FilterCondition;
65
+ beginsWith<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, string>, prefix: string): FilterCondition;
66
+ contains<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, string>, substring: string): FilterCondition;
67
+ and(...conditions: FilterCondition[]): FilterCondition;
68
+ or(...conditions: FilterCondition[]): FilterCondition;
69
+ not(condition: FilterCondition): FilterCondition;
70
+ }
71
+ /**
72
+ * Extract indexes from a DynamoTable
73
+ */
74
+ type TableIndexes<T extends AnyDynamoTable> = T extends DynamoTable<any, any, any, infer TIndexes> ? TIndexes : T extends {
75
+ indexes: infer TIndexes;
76
+ } ? TIndexes : never;
77
+ /**
78
+ * Procedure types
79
+ */
80
+ type ProcedureType = 'query' | 'mutation';
81
+ /**
82
+ * Procedure definition
83
+ */
84
+ interface ProcedureDefinition<TContext, TInput extends z.ZodTypeAny = z.ZodUndefined, TOutput = unknown> {
85
+ type: ProcedureType;
86
+ inputSchema?: TInput;
87
+ resolver: (opts: {
88
+ ctx: TContext & {
89
+ db: DatabaseContext;
90
+ };
91
+ input: z.infer<TInput>;
92
+ }) => Promise<TOutput> | TOutput;
93
+ }
94
+ /**
95
+ * Any procedure definition - used for generic constraints
96
+ * Uses 'any' for input/output to allow covariant assignment
97
+ */
98
+ type AnyProcedureDefinition<TContext> = ProcedureDefinition<TContext, any, any>;
99
+ /**
100
+ * Router definition
101
+ */
102
+ type RouterDefinition<TContext> = {
103
+ [key: string]: AnyProcedureDefinition<TContext> | RouterDefinition<TContext>;
104
+ };
105
+ /**
106
+ * Dependency information extracted from a query
107
+ */
108
+ interface QueryDependency {
109
+ tableName: string;
110
+ fieldName: string;
111
+ fieldValue: string;
112
+ indexName?: string;
113
+ }
114
+ /**
115
+ * Tracked query operation (for dependency extraction and stream processing)
116
+ */
117
+ interface TrackedQueryOperation {
118
+ tableName: string;
119
+ filters: FilterCondition[];
120
+ indexName?: string;
121
+ /** Primary key field name for the table */
122
+ pkField: string;
123
+ /** Sort key field name for the table (if any) */
124
+ skField?: string;
125
+ /** Sort field for ordering results */
126
+ sortField?: string;
127
+ /** Sort direction */
128
+ sortOrder?: 'asc' | 'desc';
129
+ /** Maximum number of results */
130
+ limit?: number;
131
+ }
132
+
133
+ /**
134
+ * Procedure builder for creating type-safe procedures
135
+ */
136
+ declare class ProcedureBuilder<TContext, TInput extends z.ZodType = z.ZodUndefined> {
137
+ private inputSchema?;
138
+ constructor(inputSchema?: TInput);
139
+ /**
140
+ * Define the input schema for the procedure
141
+ */
142
+ input<TNewInput extends z.ZodType>(schema: TNewInput): ProcedureBuilder<TContext, TNewInput>;
143
+ /**
144
+ * Define a query procedure (read-only operation)
145
+ */
146
+ query<TOutput>(resolver: (opts: {
147
+ ctx: TContext & {
148
+ db: DatabaseContext;
149
+ };
150
+ input: z.infer<TInput>;
151
+ }) => Promise<TOutput> | TOutput): ProcedureDefinition<TContext, TInput, TOutput>;
152
+ /**
153
+ * Define a mutation procedure (write operation)
154
+ */
155
+ mutation<TOutput>(resolver: (opts: {
156
+ ctx: TContext & {
157
+ db: DatabaseContext;
158
+ };
159
+ input: z.infer<TInput>;
160
+ }) => Promise<TOutput> | TOutput): ProcedureDefinition<TContext, TInput, TOutput>;
161
+ }
162
+ /**
163
+ * Check if a value is a procedure definition
164
+ */
165
+ declare function isProcedure(value: unknown): value is ProcedureDefinition<any, any, any>;
166
+ /**
167
+ * Execute a procedure with the given context and input
168
+ */
169
+ declare function executeProcedure<TContext, TInput extends z.ZodType, TOutput>(procedure: ProcedureDefinition<TContext, TInput, TOutput>, ctx: TContext & {
170
+ db: DatabaseContext;
171
+ }, rawInput: unknown): Promise<TOutput>;
172
+
173
+ /**
174
+ * Router class for organizing procedures
175
+ */
176
+ declare class Router<TContext, TRouter extends RouterDefinition<TContext>> {
177
+ readonly definition: TRouter;
178
+ constructor(definition: TRouter);
179
+ /**
180
+ * Get a procedure by its path (e.g., "todos.list")
181
+ */
182
+ getProcedure(path: string): ProcedureDefinition<TContext, any, any> | null;
183
+ /**
184
+ * Execute a procedure by its path
185
+ */
186
+ execute(path: string, ctx: TContext & {
187
+ db: DatabaseContext;
188
+ }, input: unknown): Promise<unknown>;
189
+ /**
190
+ * Get all procedure paths in the router
191
+ */
192
+ getProcedurePaths(): string[];
193
+ /**
194
+ * Check if a path is a query procedure
195
+ */
196
+ isQuery(path: string): boolean;
197
+ /**
198
+ * Check if a path is a mutation procedure
199
+ */
200
+ isMutation(path: string): boolean;
201
+ }
202
+ /**
203
+ * Create a router from a definition
204
+ */
205
+ declare function createRouter<TContext, TRouter extends RouterDefinition<TContext>>(definition: TRouter): Router<TContext, TRouter>;
206
+ /**
207
+ * Merge multiple routers into one
208
+ */
209
+ declare function mergeRouters<TContext>(...routers: Router<TContext, any>[]): Router<TContext, RouterDefinition<TContext>>;
210
+
211
+ /**
212
+ * ReactiveBuilder - The main builder returned by initReactive
213
+ */
214
+ interface ReactiveBuilder<TContext> {
215
+ /**
216
+ * Create a new procedure builder
217
+ */
218
+ procedure: ProcedureBuilder<TContext>;
219
+ /**
220
+ * Create a router from procedure definitions
221
+ */
222
+ router<TRouter extends RouterDefinition<TContext>>(definition: TRouter): Router<TContext, TRouter>;
223
+ }
224
+ /**
225
+ * Initialize the reactive system with a context type
226
+ *
227
+ * @example
228
+ * ```ts
229
+ * const t = initReactive<{ userId: string }>();
230
+ *
231
+ * export const appRouter = t.router({
232
+ * todos: {
233
+ * list: t.procedure
234
+ * .input(z.object({ taskListId: z.string() }))
235
+ * .query(({ ctx, input }) => {
236
+ * return ctx.db
237
+ * .query(TodoTable)
238
+ * .filter((q) => q.eq(TodoTable.field.taskListId, input.taskListId))
239
+ * .take(50);
240
+ * }),
241
+ * }
242
+ * });
243
+ * ```
244
+ */
245
+ declare function initReactive<TContext = Record<string, unknown>>(): ReactiveBuilder<TContext>;
246
+ /**
247
+ * Type helper to infer the router type
248
+ */
249
+ type InferRouterType<T> = T extends Router<infer TContext, infer TRouter> ? {
250
+ context: TContext;
251
+ router: TRouter;
252
+ } : never;
253
+ /**
254
+ * Type helper to get procedure input type
255
+ */
256
+ type InferProcedureInput<T> = T extends {
257
+ inputSchema: infer TSchema;
258
+ } ? TSchema extends z.ZodType ? z.infer<TSchema> : undefined : undefined;
259
+ /**
260
+ * Type helper to get procedure output type
261
+ */
262
+ type InferProcedureOutput<T> = T extends {
263
+ resolver: (...args: any) => infer TOutput;
264
+ } ? Awaited<TOutput> : unknown;
265
+
266
+ /**
267
+ * Extract dependencies from a tracked query operation
268
+ */
269
+ declare function extractDependencies(operation: TrackedQueryOperation): QueryDependency[];
270
+ /**
271
+ * Create a dependency key for the inverted index
272
+ * Format: "TableName#FieldName#FieldValue"
273
+ */
274
+ declare function createDependencyKey(dependency: QueryDependency): string;
275
+ /**
276
+ * Parse a dependency key back into its components
277
+ */
278
+ declare function parseDependencyKey(key: string): QueryDependency | null;
279
+ /**
280
+ * Extract affected dependency keys from a DynamoDB stream record
281
+ * This finds all keys that might be affected by a change
282
+ */
283
+ declare function extractAffectedKeys(tableName: string, item: Record<string, unknown>): string[];
284
+ /**
285
+ * Convert a TrackedQueryOperation to QueryMetadata for storage.
286
+ * Normalizes filter operators for evaluation.
287
+ */
288
+ declare function operationToQueryMetadata(operation: TrackedQueryOperation): QueryMetadata;
289
+ /**
290
+ * DependencyTracker - Tracks query operations during procedure execution
291
+ */
292
+ declare class DependencyTracker {
293
+ private operations;
294
+ /**
295
+ * Track a query operation
296
+ */
297
+ track(operation: TrackedQueryOperation): void;
298
+ /**
299
+ * Get all tracked operations
300
+ */
301
+ getOperations(): TrackedQueryOperation[];
302
+ /**
303
+ * Extract all dependencies from tracked operations
304
+ */
305
+ extractAll(): QueryDependency[];
306
+ /**
307
+ * Get all dependency keys for the inverted index
308
+ */
309
+ getDependencyKeys(): string[];
310
+ /**
311
+ * Get query metadata for the first tracked operation.
312
+ * Used for storing subscription state.
313
+ */
314
+ getQueryMetadata(): QueryMetadata | null;
315
+ /**
316
+ * Get the primary key field from the first operation
317
+ */
318
+ getPkField(): string | null;
319
+ /**
320
+ * Get the sort key field from the first operation
321
+ */
322
+ getSkField(): string | undefined;
323
+ /**
324
+ * Clear tracked operations
325
+ */
326
+ clear(): void;
327
+ }
328
+
329
+ /**
330
+ * Configuration for creating a database context
331
+ */
332
+ interface DbContextConfig {
333
+ client?: DynamoDBClient;
334
+ region?: string;
335
+ endpoint?: string;
336
+ }
337
+ /**
338
+ * Creates a database context for procedure execution
339
+ */
340
+ declare function createDbContext(config: DbContextConfig, dependencyTracker?: DependencyTracker): DatabaseContext;
341
+
342
+ /**
343
+ * Query execution function type
344
+ */
345
+ type QueryExecutor<TTable extends AnyDynamoTable> = (operation: TrackedQueryOperation, options: QueryOptions) => Promise<TableItem<TTable>[]>;
346
+ /**
347
+ * Query options
348
+ */
349
+ interface QueryOptions {
350
+ limit?: number;
351
+ startKey?: Record<string, unknown>;
352
+ ascending: boolean;
353
+ }
354
+ /**
355
+ * Implementation of QueryBuilder
356
+ */
357
+ declare class QueryBuilderImpl<TTable extends AnyDynamoTable> implements QueryBuilder<TTable> {
358
+ private table;
359
+ private filters;
360
+ private indexName?;
361
+ private limit?;
362
+ private startKey?;
363
+ private ascending;
364
+ private executor;
365
+ private operationTracker?;
366
+ constructor(table: TTable, executor: QueryExecutor<TTable>, operationTracker?: (op: TrackedQueryOperation) => void);
367
+ filter(fn: (q: FilterBuilder<TTable>) => FilterCondition): QueryBuilder<TTable>;
368
+ useIndex(indexName: string): QueryBuilder<TTable>;
369
+ take(limit: number): QueryBuilder<TTable>;
370
+ startFrom(key: TableKeyInput<TTable>): QueryBuilder<TTable>;
371
+ sortAscending(): QueryBuilder<TTable>;
372
+ sortDescending(): QueryBuilder<TTable>;
373
+ execute(): Promise<TableItem<TTable>[]>;
374
+ /**
375
+ * Get the current operation without executing
376
+ * Used for dependency extraction
377
+ */
378
+ getOperation(): TrackedQueryOperation;
379
+ }
380
+ /**
381
+ * Create a filter builder instance
382
+ */
383
+ declare function createFilterBuilder<TTable extends AnyDynamoTable>(): FilterBuilder<TTable>;
384
+
385
+ /**
386
+ * PartiQL statement with parameters
387
+ */
388
+ interface PartiQLStatement {
389
+ statement: string;
390
+ parameters: unknown[];
391
+ }
392
+ /**
393
+ * Build a PartiQL SELECT statement from a query operation
394
+ */
395
+ declare function buildSelectStatement(operation: TrackedQueryOperation): PartiQLStatement;
396
+ /**
397
+ * Build a PartiQL INSERT statement
398
+ */
399
+ declare function buildInsertStatement(tableName: string, item: Record<string, unknown>): PartiQLStatement;
400
+ /**
401
+ * Build a PartiQL UPDATE statement
402
+ */
403
+ declare function buildUpdateStatement(tableName: string, key: Record<string, unknown>, updates: Record<string, unknown>): PartiQLStatement;
404
+ /**
405
+ * Build a PartiQL DELETE statement
406
+ */
407
+ declare function buildDeleteStatement(tableName: string, key: Record<string, unknown>): PartiQLStatement;
408
+ /**
409
+ * Build a PartiQL GET statement (for single item by key)
410
+ */
411
+ declare function buildGetStatement(tableName: string, key: Record<string, unknown>): PartiQLStatement;
412
+
413
+ /**
414
+ * Generate JSON patches between two objects
415
+ * Uses RFC 6902 JSON Patch format
416
+ */
417
+ declare function generatePatches(oldValue: unknown, newValue: unknown): JsonPatch[];
418
+ /**
419
+ * Apply JSON patches to an object
420
+ * Returns the patched result
421
+ */
422
+ declare function applyPatches<T>(document: T, patches: JsonPatch[]): T;
423
+ /**
424
+ * Check if there are any changes between two values
425
+ */
426
+ declare function hasChanges(oldValue: unknown, newValue: unknown): boolean;
427
+ /**
428
+ * Create a minimal patch that only includes necessary operations
429
+ * Optimizes the patch by removing redundant operations
430
+ */
431
+ declare function optimizePatches(patches: JsonPatch[]): JsonPatch[];
432
+ /**
433
+ * Batch multiple patch sets into a single set
434
+ */
435
+ declare function batchPatches(patchSets: JsonPatch[][]): JsonPatch[];
436
+
437
+ /**
438
+ * Request types for the reactive handler
439
+ */
440
+ interface SubscribeRequest {
441
+ type: 'subscribe';
442
+ subscriptionId: string;
443
+ path: string;
444
+ input: unknown;
445
+ }
446
+ interface UnsubscribeRequest {
447
+ type: 'unsubscribe';
448
+ subscriptionId: string;
449
+ }
450
+ interface CallRequest {
451
+ type: 'call';
452
+ path: string;
453
+ input: unknown;
454
+ }
455
+ type ReactiveRequest = SubscribeRequest | UnsubscribeRequest | CallRequest;
456
+ /**
457
+ * Response types for the reactive handler
458
+ */
459
+ interface SnapshotResponse {
460
+ type: 'snapshot';
461
+ subscriptionId: string;
462
+ data: unknown;
463
+ }
464
+ interface PatchResponse {
465
+ type: 'patch';
466
+ subscriptionId: string;
467
+ patches: unknown[];
468
+ }
469
+ interface ResultResponse {
470
+ type: 'result';
471
+ data: unknown;
472
+ }
473
+ interface ErrorResponse {
474
+ type: 'error';
475
+ message: string;
476
+ subscriptionId?: string;
477
+ }
478
+ type ReactiveResponse = SnapshotResponse | PatchResponse | ResultResponse | ErrorResponse;
479
+ /**
480
+ * Configuration for the reactive handler
481
+ */
482
+ interface ReactiveHandlerConfig<TContext> {
483
+ router: Router<TContext, any>;
484
+ dbConfig?: DbContextConfig;
485
+ getContext: (connectionId: string) => Promise<TContext>;
486
+ ttlSeconds?: number;
487
+ /** Table names (uses defaults if not provided) */
488
+ connectionsTableName?: string;
489
+ dependenciesTableName?: string;
490
+ queriesTableName?: string;
491
+ }
492
+ /**
493
+ * Create a reactive handler for Next.js API routes or other HTTP servers.
494
+ * This handler is used for subscribe/call requests and stores queryMetadata
495
+ * for the stream handler to use later.
496
+ */
497
+ declare function createReactiveHandler<TContext>(config: ReactiveHandlerConfig<TContext>): {
498
+ handleRequest: (connectionId: string, request: ReactiveRequest) => Promise<ReactiveResponse>;
499
+ registerConnection: (connectionId: string, context?: Record<string, unknown>) => Promise<void>;
500
+ unregisterConnection: (connectionId: string) => Promise<void>;
501
+ };
502
+
503
+ /**
504
+ * Configuration for the stream handler.
505
+ * NOTE: Router is no longer required - stream processing uses stored query metadata.
506
+ */
507
+ interface StreamHandlerConfig {
508
+ dbConfig?: DbContextConfig;
509
+ apiGatewayEndpoint: string;
510
+ connectionsTableName?: string;
511
+ dependenciesTableName?: string;
512
+ queriesTableName?: string;
513
+ }
514
+ /**
515
+ * Create a DynamoDB stream handler for AWS Lambda.
516
+ * Uses stored query metadata to re-execute queries WITHOUT router code.
517
+ */
518
+ declare function createStreamHandler(config: StreamHandlerConfig): {
519
+ handler: (event: DynamoDBStreamEvent) => Promise<void>;
520
+ };
521
+ /**
522
+ * WebSocket connection handler for $connect
523
+ */
524
+ declare function createConnectHandler(config: Pick<StreamHandlerConfig, 'dbConfig' | 'connectionsTableName'>): (event: {
525
+ requestContext: {
526
+ connectionId: string;
527
+ authorizer?: Record<string, unknown>;
528
+ };
529
+ }) => Promise<{
530
+ statusCode: number;
531
+ }>;
532
+ /**
533
+ * WebSocket disconnection handler for $disconnect
534
+ */
535
+ declare function createDisconnectHandler(config: Pick<StreamHandlerConfig, 'dbConfig' | 'connectionsTableName' | 'queriesTableName' | 'dependenciesTableName'>): (event: {
536
+ requestContext: {
537
+ connectionId: string;
538
+ };
539
+ }) => Promise<{
540
+ statusCode: number;
541
+ }>;
542
+
543
+ /**
544
+ * Configuration for creating a reactive harness
545
+ */
546
+ interface ReactiveHarnessConfig<TContext> {
547
+ /**
548
+ * Function to get the context for a connection
549
+ * This is called on each request to build the procedure context
550
+ */
551
+ getContext?: (connectionId: string) => Promise<TContext>;
552
+ /**
553
+ * Optional database configuration
554
+ */
555
+ dbConfig?: DbContextConfig;
556
+ }
557
+ /**
558
+ * The reactive harness object containing all configuration needed for the engine
559
+ */
560
+ interface ReactiveHarness<TContext> {
561
+ getContext: (connectionId: string) => Promise<TContext>;
562
+ dbConfig?: DbContextConfig;
563
+ }
564
+ /**
565
+ * Create a reactive harness that encapsulates the router and context configuration.
566
+ *
567
+ * This is the only export needed from user code for the ReactiveEngine.
568
+ * The engine will use this harness to automatically create all WebSocket handlers.
569
+ *
570
+ * @example
571
+ * ```typescript
572
+ * // harness.ts - This is all you need in your handlers directory
573
+ * import { createReactiveHarness } from 'dynamodb-reactive/server';
574
+ * import { appRouter } from './router';
575
+ *
576
+ * export default createReactiveHarness({
577
+ * getContext: async (connectionId) => ({
578
+ * connectionId,
579
+ * }),
580
+ * });
581
+ * ```
582
+ */
583
+ declare function createReactiveHarness<TContext>(config: ReactiveHarnessConfig<TContext>): ReactiveHarness<TContext>;
584
+
585
+ /**
586
+ * Lambda handler implementations for the reactive WebSocket system.
587
+ *
588
+ * These handlers process WebSocket events and DynamoDB stream events
589
+ * WITHOUT requiring user router code at runtime.
590
+ *
591
+ * Stream processing uses stored query metadata to evaluate changes
592
+ * directly, rather than re-executing queries through a router.
593
+ */
594
+
595
+ /**
596
+ * Create all Lambda handlers.
597
+ * No user code required - all configuration comes from environment variables.
598
+ * The stream handler uses stored query metadata (PartiQL), not router code.
599
+ */
600
+ declare function createLambdaHandlers(): {
601
+ connectHandler: (event: APIGatewayProxyEvent) => Promise<APIGatewayProxyResult>;
602
+ disconnectHandler: (event: APIGatewayProxyEvent) => Promise<APIGatewayProxyResult>;
603
+ messageHandler: (event: APIGatewayProxyEvent) => Promise<APIGatewayProxyResult>;
604
+ streamHandler: (event: DynamoDBStreamEvent) => Promise<void>;
605
+ };
606
+
607
+ /**
608
+ * Filter evaluator for evaluating FilterCondition against DynamoDB records.
609
+ * Used by the stream handler to determine if a record matches a subscription's query.
610
+ */
611
+
612
+ /**
613
+ * Evaluate a filter condition against a record.
614
+ * Returns true if the record matches the filter.
615
+ */
616
+ declare function evaluateFilter(filter: FilterCondition, record: Record<string, unknown>): boolean;
617
+ /**
618
+ * Evaluate multiple filter conditions (all must match - AND logic).
619
+ */
620
+ declare function evaluateFilters(filters: FilterCondition[], record: Record<string, unknown>): boolean;
621
+ /**
622
+ * Sort records by a field.
623
+ */
624
+ declare function sortRecords(records: Record<string, unknown>[], sortField?: string, sortOrder?: 'asc' | 'desc'): Record<string, unknown>[];
625
+ /**
626
+ * Find the primary key value(s) from a record.
627
+ * Used to identify records for update/removal.
628
+ */
629
+ declare function getRecordKey(record: Record<string, unknown>, pkField: string, skField?: string): string;
630
+
631
+ export { AnyDynamoTable, type AnyProcedureDefinition, type CallRequest, type DatabaseContext, type DbContextConfig, DependencyTracker, type ErrorResponse, type FilterBuilder, FilterCondition, type InferProcedureInput, type InferProcedureOutput, type InferRouterType, type PartiQLStatement, type PatchResponse, ProcedureBuilder, type ProcedureContext, type ProcedureDefinition, type ProcedureType, type QueryBuilder, QueryBuilderImpl, type QueryDependency, type ReactiveBuilder, type ReactiveHandlerConfig, type ReactiveHarness, type ReactiveHarnessConfig, type ReactiveRequest, type ReactiveResponse, type ResultResponse, Router, type RouterDefinition, type SnapshotResponse, type StreamHandlerConfig, type SubscribeRequest, type TableItem, type TableKeyInput, type TrackedQueryOperation, type UnsubscribeRequest, applyPatches, batchPatches, buildDeleteStatement, buildGetStatement, buildInsertStatement, buildSelectStatement, buildUpdateStatement, createConnectHandler, createDbContext, createDependencyKey, createDisconnectHandler, createFilterBuilder, createLambdaHandlers, createReactiveHandler, createReactiveHarness, createRouter, createStreamHandler, evaluateFilter, evaluateFilters, executeProcedure, extractAffectedKeys, extractDependencies, generatePatches, getRecordKey, hasChanges, initReactive, isProcedure, mergeRouters, operationToQueryMetadata, optimizePatches, parseDependencyKey, sortRecords };