dynamodb-reactive 0.1.21 → 0.2.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.
Files changed (46) hide show
  1. package/README.md +378 -153
  2. package/dist/client-r_tnzwqi.d.ts +224 -0
  3. package/dist/client.cjs +1023 -0
  4. package/dist/client.cjs.map +1 -0
  5. package/dist/client.d.cts +6 -0
  6. package/dist/client.d.ts +4 -70
  7. package/dist/client.js +1013 -1
  8. package/dist/client.js.map +1 -1
  9. package/dist/core.cjs +232 -0
  10. package/dist/core.cjs.map +1 -0
  11. package/dist/core.d.cts +4 -0
  12. package/dist/core.d.ts +3 -3
  13. package/dist/core.js +222 -1
  14. package/dist/core.js.map +1 -1
  15. package/dist/index.cjs +232 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +157 -0
  18. package/dist/index.d.ts +103 -56
  19. package/dist/index.js +222 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/infra.cjs +623 -0
  22. package/dist/infra.cjs.map +1 -0
  23. package/dist/infra.d.cts +119 -0
  24. package/dist/infra.d.ts +50 -102
  25. package/dist/infra.js +371 -144
  26. package/dist/infra.js.map +1 -1
  27. package/dist/react.cjs +1250 -0
  28. package/dist/react.cjs.map +1 -0
  29. package/dist/react.d.cts +68 -0
  30. package/dist/react.d.ts +68 -3
  31. package/dist/react.js +1237 -1
  32. package/dist/react.js.map +1 -1
  33. package/dist/server.cjs +2351 -0
  34. package/dist/server.cjs.map +1 -0
  35. package/dist/server.d.cts +364 -0
  36. package/dist/server.d.ts +58 -313
  37. package/dist/server.js +1855 -1208
  38. package/dist/server.js.map +1 -1
  39. package/dist/{table-tN3D4Tm-.d.ts → table-BijJ73pX.d.ts} +2 -34
  40. package/dist/{types-ISMJfyIv.d.ts → types-LMLk8JVC.d.ts} +56 -30
  41. package/package.json +79 -41
  42. package/dist/chunk-2A7GJ2UO.js +0 -1088
  43. package/dist/chunk-2A7GJ2UO.js.map +0 -1
  44. package/dist/chunk-ZAJA4KBE.js +0 -150
  45. package/dist/chunk-ZAJA4KBE.js.map +0 -1
  46. package/dist/react-B2b5RIz_.d.ts +0 -549
@@ -0,0 +1,364 @@
1
+ import { z } from 'zod';
2
+ import { A as AnyDynamoTable, a as FilterCondition } from './types-LMLk8JVC.js';
3
+ import { FieldRef, QueryMetadata, ConnectionEntry } from './core.cjs';
4
+ import { DynamoTable } from './core.cjs';
5
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
6
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
7
+ import * as aws_lambda from 'aws-lambda';
8
+ import { APIGatewayProxyEvent, APIGatewayProxyResult, DynamoDBStreamEvent } from 'aws-lambda';
9
+ import { ApiGatewayManagementApiClient } from '@aws-sdk/client-apigatewaymanagementapi';
10
+
11
+ /**
12
+ * Database context provided to procedures
13
+ */
14
+ interface DatabaseContext {
15
+ query<TTable extends AnyDynamoTable>(table: TTable): QueryBuilder<TTable>;
16
+ get<TTable extends AnyDynamoTable>(table: TTable, key: TableKeyInput<TTable>): Promise<TableItem<TTable> | null>;
17
+ put<TTable extends AnyDynamoTable>(table: TTable, item: TableItem<TTable>): Promise<void>;
18
+ delete<TTable extends AnyDynamoTable>(table: TTable, key: TableKeyInput<TTable>): Promise<void>;
19
+ update<TTable extends AnyDynamoTable>(table: TTable, key: TableKeyInput<TTable>, updates: Partial<TableItem<TTable>>): Promise<TableItem<TTable>>;
20
+ }
21
+ /**
22
+ * Extract the item type from a DynamoTable
23
+ * Works with both the DynamoTable class and AnyDynamoTable interface
24
+ */
25
+ type TableItem<T extends AnyDynamoTable> = T extends DynamoTable<infer TSchema, any, any, any> ? z.infer<TSchema> : T extends {
26
+ schema: infer TSchema extends z.ZodTypeAny;
27
+ } ? z.infer<TSchema> : never;
28
+ /**
29
+ * Extract key input type from a DynamoTable
30
+ * Works with both the DynamoTable class and AnyDynamoTable interface
31
+ */
32
+ 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 {
33
+ schema: infer TSchema extends z.ZodTypeAny;
34
+ pk: infer TPk;
35
+ sk: infer TSk;
36
+ } ? 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;
37
+ /**
38
+ * Query builder for type-safe DynamoDB queries
39
+ */
40
+ interface QueryBuilder<TTable extends AnyDynamoTable> {
41
+ filter(fn: (q: FilterBuilder<TTable>) => FilterCondition): QueryBuilder<TTable>;
42
+ useIndex(indexName: keyof TTable['indexes'] & string): QueryBuilder<TTable>;
43
+ take(limit: number): QueryBuilder<TTable>;
44
+ sortAscending(): QueryBuilder<TTable>;
45
+ sortDescending(): QueryBuilder<TTable>;
46
+ execute(): Promise<TableItem<TTable>[]>;
47
+ }
48
+ /**
49
+ * Filter builder for query conditions
50
+ */
51
+ interface FilterBuilder<TTable extends AnyDynamoTable> {
52
+ eq<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
53
+ ne<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
54
+ gt<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
55
+ gte<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
56
+ lt<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
57
+ lte<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, value: TableItem<TTable>[K]): FilterCondition;
58
+ between<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, TableItem<TTable>[K]>, lower: TableItem<TTable>[K], upper: TableItem<TTable>[K]): FilterCondition;
59
+ beginsWith<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, string>, prefix: string): FilterCondition;
60
+ contains<K extends keyof TableItem<TTable>>(field: FieldRef<K & string, string>, substring: string): FilterCondition;
61
+ and(...conditions: FilterCondition[]): FilterCondition;
62
+ or(...conditions: FilterCondition[]): FilterCondition;
63
+ not(condition: FilterCondition): FilterCondition;
64
+ }
65
+ /**
66
+ * Procedure types
67
+ */
68
+ type ProcedureType = 'query' | 'mutation';
69
+ /**
70
+ * Procedure definition
71
+ */
72
+ interface ProcedureDefinition<TContext, TInput extends z.ZodTypeAny = z.ZodUndefined, TOutput = unknown, TType extends ProcedureType = ProcedureType> {
73
+ type: TType;
74
+ inputSchema?: TInput;
75
+ resolver: (opts: {
76
+ ctx: TContext & {
77
+ db: DatabaseContext;
78
+ };
79
+ input: z.infer<TInput>;
80
+ }) => Promise<TOutput> | TOutput;
81
+ }
82
+ /**
83
+ * Any procedure definition - used for generic constraints
84
+ * Uses 'any' for input/output to allow covariant assignment
85
+ */
86
+ type AnyProcedureDefinition<TContext> = ProcedureDefinition<TContext, any, any, ProcedureType>;
87
+ /**
88
+ * Router definition
89
+ */
90
+ type RouterDefinition<TContext> = {
91
+ [key: string]: AnyProcedureDefinition<TContext> | RouterDefinition<TContext>;
92
+ };
93
+ /**
94
+ * Dependency information extracted from a query
95
+ */
96
+ interface QueryDependency {
97
+ tableName: string;
98
+ fieldName: string;
99
+ fieldValue: string;
100
+ }
101
+ /**
102
+ * Transform a router definition into a callable structure (for queries only)
103
+ */
104
+ type RouterCaller<TRouter> = {
105
+ [K in keyof TRouter]: TRouter[K] extends ProcedureDefinition<any, // eslint-disable-line @typescript-eslint/no-explicit-any -- conditional type inference requires `any` for contravariant TContext
106
+ infer TInput, infer TOutput, infer TType> ? TType extends 'query' ? TInput extends z.ZodTypeAny ? (input: z.infer<TInput>) => Promise<TOutput> : () => Promise<TOutput> : never : TRouter[K] extends Record<string, unknown> ? RouterCaller<TRouter[K]> : never;
107
+ };
108
+ /**
109
+ * Tracked query operation (for dependency extraction and stream processing)
110
+ */
111
+ interface TrackedQueryOperation {
112
+ tableName: string;
113
+ filters: FilterCondition[];
114
+ indexName?: string;
115
+ /** Field names selected by useIndex, used to preserve sparse membership. */
116
+ indexPkField?: string;
117
+ indexSkField?: string;
118
+ /** Sort field for ordering results */
119
+ sortField?: string;
120
+ /** Sort direction */
121
+ sortOrder?: 'asc' | 'desc';
122
+ /** Maximum number of results */
123
+ limit?: number;
124
+ }
125
+
126
+ /**
127
+ * Procedure builder for creating type-safe procedures
128
+ */
129
+ declare class ProcedureBuilder<TContext, TInput extends z.ZodType = z.ZodUndefined> {
130
+ private inputSchema?;
131
+ constructor(inputSchema?: TInput);
132
+ /**
133
+ * Define the input schema for the procedure
134
+ */
135
+ input<TNewInput extends z.ZodType>(schema: TNewInput): ProcedureBuilder<TContext, TNewInput>;
136
+ /**
137
+ * Define a query procedure (read-only operation)
138
+ */
139
+ query<TOutput>(resolver: (opts: {
140
+ ctx: TContext & {
141
+ db: DatabaseContext;
142
+ };
143
+ input: z.infer<TInput>;
144
+ }) => Promise<TOutput> | TOutput): ProcedureDefinition<TContext, TInput, TOutput, 'query'>;
145
+ /**
146
+ * Define a mutation procedure (write operation)
147
+ */
148
+ mutation<TOutput>(resolver: (opts: {
149
+ ctx: TContext & {
150
+ db: DatabaseContext;
151
+ };
152
+ input: z.infer<TInput>;
153
+ }) => Promise<TOutput> | TOutput): ProcedureDefinition<TContext, TInput, TOutput, 'mutation'>;
154
+ }
155
+
156
+ /**
157
+ * Router class for organizing procedures
158
+ */
159
+ declare class Router<TContext, TRouter extends RouterDefinition<TContext>> {
160
+ readonly definition: TRouter;
161
+ constructor(definition: TRouter);
162
+ /**
163
+ * Get a procedure by its path (e.g., "todos.list")
164
+ */
165
+ getProcedure(path: string): AnyProcedureDefinition<TContext> | null;
166
+ /**
167
+ * Execute a procedure by its path
168
+ */
169
+ execute(path: string, ctx: TContext & {
170
+ db: DatabaseContext;
171
+ }, input: unknown): Promise<unknown>;
172
+ }
173
+
174
+ /**
175
+ * ReactiveBuilder - The main builder returned by initReactive
176
+ */
177
+ interface ReactiveBuilder<TContext> {
178
+ /**
179
+ * Create a new procedure builder
180
+ */
181
+ procedure: ProcedureBuilder<TContext>;
182
+ /**
183
+ * Create a router from procedure definitions
184
+ */
185
+ router<TRouter extends RouterDefinition<TContext>>(definition: TRouter): Router<TContext, TRouter>;
186
+ }
187
+ /**
188
+ * Initialize the reactive system with a context type
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * const t = initReactive<{ userId: string }>();
193
+ *
194
+ * export const appRouter = t.router({
195
+ * todos: {
196
+ * list: t.procedure
197
+ * .input(z.object({ taskListId: z.string() }))
198
+ * .query(({ ctx, input }) => {
199
+ * return ctx.db
200
+ * .query(TodoTable)
201
+ * .filter((q) => q.eq(TodoTable.field.taskListId, input.taskListId))
202
+ * .take(50);
203
+ * }),
204
+ * }
205
+ * });
206
+ * ```
207
+ */
208
+ declare function initReactive<TContext = Record<string, unknown>>(): ReactiveBuilder<TContext>;
209
+ /**
210
+ * Type helper to infer the router type
211
+ */
212
+ type InferRouterType<T> = T extends Router<infer TContext, infer TRouter> ? {
213
+ context: TContext;
214
+ router: TRouter;
215
+ } : never;
216
+ /**
217
+ * Type helper to get procedure input type
218
+ */
219
+ type InferProcedureInput<T> = T extends {
220
+ inputSchema: infer TSchema;
221
+ } ? TSchema extends z.ZodType ? z.infer<TSchema> : undefined : undefined;
222
+ /**
223
+ * Type helper to get procedure output type
224
+ */
225
+ type InferProcedureOutput<T> = T extends {
226
+ resolver: (...args: any[]) => infer TOutput;
227
+ } ? Awaited<TOutput> : unknown;
228
+
229
+ /** An error whose status and message are safe to return to an API caller. */
230
+ declare class SafeRequestError extends Error {
231
+ readonly statusCode: number;
232
+ constructor(message: string, statusCode: number);
233
+ }
234
+ /** Generic public error for malformed procedure input; Zod details stay private. */
235
+ declare class InvalidInputError extends SafeRequestError {
236
+ constructor();
237
+ }
238
+ declare function isSafeRequestError(error: unknown): error is SafeRequestError;
239
+
240
+ /**
241
+ * DependencyTracker - Tracks query operations during procedure execution
242
+ */
243
+ declare class DependencyTracker {
244
+ private operations;
245
+ /**
246
+ * Track a query operation
247
+ */
248
+ track(operation: TrackedQueryOperation, result: unknown[]): void;
249
+ /**
250
+ * Get all tracked operations
251
+ */
252
+ getOperations(): TrackedQueryOperation[];
253
+ /**
254
+ * Extract all dependencies from tracked operations
255
+ */
256
+ extractAll(): QueryDependency[];
257
+ /**
258
+ * Get query metadata for the first tracked operation.
259
+ * Used for storing subscription state.
260
+ */
261
+ getQueryMetadata(): QueryMetadata | null;
262
+ getCapturedResult(): {
263
+ reference: unknown[];
264
+ snapshot: unknown[];
265
+ } | null;
266
+ }
267
+
268
+ /**
269
+ * Configuration for creating a database context
270
+ */
271
+ interface DbContextConfig {
272
+ client?: DynamoDBClient;
273
+ docClient?: DynamoDBDocumentClient;
274
+ region?: string;
275
+ endpoint?: string;
276
+ }
277
+ /**
278
+ * Creates a database context for procedure execution
279
+ */
280
+ declare function createDbContext(config: DbContextConfig, dependencyTracker?: DependencyTracker): DatabaseContext;
281
+
282
+ interface SubscribeRequest {
283
+ type: 'subscribe';
284
+ connectionId: string;
285
+ subscriptionId: string;
286
+ generation: number;
287
+ registrationId: string;
288
+ path: string;
289
+ input: unknown;
290
+ }
291
+ interface UnsubscribeRequest {
292
+ type: 'unsubscribe';
293
+ connectionId: string;
294
+ subscriptionId: string;
295
+ generation: number;
296
+ registrationId: string;
297
+ }
298
+ interface CallRequest {
299
+ type: 'call';
300
+ connectionId: string;
301
+ path: string;
302
+ input: unknown;
303
+ }
304
+ type ReactiveRequest = SubscribeRequest | UnsubscribeRequest | CallRequest;
305
+ interface SnapshotResponse {
306
+ type: 'snapshot';
307
+ subscriptionId: string;
308
+ generation: number;
309
+ version: number;
310
+ data: unknown[];
311
+ }
312
+ interface ResultResponse {
313
+ type: 'result';
314
+ data: unknown;
315
+ }
316
+ interface ErrorResponse {
317
+ type: 'error';
318
+ message: string;
319
+ code?: number;
320
+ subscriptionId?: string;
321
+ }
322
+ type ReactiveResponse = SnapshotResponse | ResultResponse | ErrorResponse;
323
+ interface RequestInfo {
324
+ connectionId: string;
325
+ headers?: Record<string, string>;
326
+ }
327
+ interface ConnectionAuthorization<TContext> {
328
+ context: TContext;
329
+ connection: ConnectionEntry;
330
+ requestInfo: RequestInfo;
331
+ }
332
+ interface ReactiveHandlerConfig<TContext, TRouter extends RouterDefinition<TContext> = RouterDefinition<TContext>> {
333
+ router: Router<TContext, TRouter>;
334
+ dbConfig?: DbContextConfig;
335
+ getContext: (requestInfo: RequestInfo) => Promise<TContext>;
336
+ authorizeConnection: (authorization: ConnectionAuthorization<TContext>) => boolean | Promise<boolean>;
337
+ ttlSeconds?: number;
338
+ tablePrefix: string;
339
+ }
340
+ declare function createReactiveHandler<TContext, TRouter extends RouterDefinition<TContext>>(config: ReactiveHandlerConfig<TContext, TRouter>): {
341
+ handleRequest: (request: ReactiveRequest, headers?: Record<string, string>) => Promise<ReactiveResponse>;
342
+ registerConnection: (connectionId: string, context?: Record<string, unknown>) => Promise<void>;
343
+ unregisterConnection: (connectionId: string) => Promise<void>;
344
+ query: <T = unknown>(path: string, input?: unknown, headers?: Record<string, string>) => Promise<T>;
345
+ createCaller: () => RouterCaller<TRouter>;
346
+ };
347
+
348
+ interface LambdaHandlersConfig {
349
+ dbConfig?: DbContextConfig;
350
+ apiClient?: ApiGatewayManagementApiClient;
351
+ connectionsTableName?: string;
352
+ dependenciesTableName?: string;
353
+ queriesTableName?: string;
354
+ apiGatewayEndpoint?: string;
355
+ }
356
+ declare function createLambdaHandlers(config?: LambdaHandlersConfig): {
357
+ connectHandler: (event: APIGatewayProxyEvent) => Promise<APIGatewayProxyResult>;
358
+ disconnectHandler: (event: APIGatewayProxyEvent) => Promise<APIGatewayProxyResult>;
359
+ messageHandler: (event: APIGatewayProxyEvent) => Promise<APIGatewayProxyResult>;
360
+ streamHandler: (event: DynamoDBStreamEvent) => Promise<aws_lambda.DynamoDBBatchResponse>;
361
+ };
362
+
363
+ export { AnyDynamoTable, FilterCondition, InvalidInputError, SafeRequestError, createDbContext, createLambdaHandlers, createReactiveHandler, initReactive, isSafeRequestError };
364
+ export type { AnyProcedureDefinition, CallRequest, DatabaseContext, DbContextConfig, ErrorResponse, FilterBuilder, InferProcedureInput, InferProcedureOutput, InferRouterType, LambdaHandlersConfig, ProcedureDefinition, ProcedureType, QueryBuilder, ReactiveBuilder, ReactiveHandlerConfig, ReactiveRequest, ReactiveResponse, RequestInfo, ResultResponse, RouterDefinition, SnapshotResponse, SubscribeRequest, TableItem, TableKeyInput, UnsubscribeRequest };