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
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { S as SupportedSchema, I as IndexDefinition, F as FieldRef, D as DynamoTableConfig } from './types-ISMJfyIv.js';
2
+ import { S as SupportedSchema, I as IndexDefinition, F as FieldRef, D as DynamoTableConfig } from './types-LMLk8JVC.js';
3
3
 
4
4
  /**
5
5
  * Creates field references for type-safe query building
@@ -56,42 +56,10 @@ declare class DynamoTable<TSchema extends SupportedSchema, TPk extends keyof z.i
56
56
  * Safely validate an item, returning a result object
57
57
  */
58
58
  safeParse(item: unknown): z.ZodSafeParseResult<z.infer<TSchema>>;
59
- /**
60
- * Get the partition key value from an item
61
- */
62
- getPk(item: z.infer<TSchema>): z.infer<TSchema>[TPk];
63
- /**
64
- * Get the sort key value from an item (if defined)
65
- */
66
- getSk(item: z.infer<TSchema>): TSk extends keyof z.infer<TSchema> ? z.infer<TSchema>[TSk] : undefined;
67
59
  /**
68
60
  * Get the list of field names in the schema
69
61
  */
70
62
  getFieldNames(): (keyof z.infer<TSchema>)[];
71
- /**
72
- * Check if a field exists in the schema
73
- */
74
- hasField(fieldName: string): fieldName is keyof z.infer<TSchema> & string;
75
63
  }
76
- /**
77
- * Helper type to extract the shape from a Zod schema
78
- */
79
- type InferSchema<T> = T extends DynamoTable<infer TSchema, any, any, any> ? z.infer<TSchema> : never;
80
- /**
81
- * Helper type to extract field names from a table
82
- */
83
- type TableFields<T> = T extends DynamoTable<infer TSchema, any, any, any> ? keyof z.infer<TSchema> : never;
84
- /**
85
- * Helper type to get the pk field name
86
- */
87
- type TablePk<T> = T extends DynamoTable<any, infer TPk, any, any> ? TPk : never;
88
- /**
89
- * Helper type to get the sk field name
90
- */
91
- type TableSk<T> = T extends DynamoTable<any, any, infer TSk, any> ? TSk : never;
92
- /**
93
- * Helper type to get indexes
94
- */
95
- type TableIndexes<T> = T extends DynamoTable<any, any, any, infer TIndexes> ? TIndexes : never;
96
64
 
97
- export { DynamoTable as D, type InferSchema as I, type TableFields as T, type TableIndexes as a, type TablePk as b, type TableSk as c };
65
+ export { DynamoTable as D };
@@ -13,10 +13,6 @@ interface IndexDefinition {
13
13
  * Accepts both ZodObject and ZodDiscriminatedUnion
14
14
  */
15
15
  type SupportedSchema = z.ZodObject<z.ZodRawShape> | z.ZodDiscriminatedUnion;
16
- /**
17
- * Extract the inferred type from a supported schema
18
- */
19
- type InferSupportedSchema<T extends SupportedSchema> = z.infer<T>;
20
16
  /**
21
17
  * Base interface for any DynamoTable - used for generic constraints
22
18
  * Defines the minimal shape that all DynamoTable instances satisfy
@@ -33,10 +29,7 @@ interface AnyDynamoTable {
33
29
  }>;
34
30
  validate(item: unknown): unknown;
35
31
  safeParse(item: unknown): z.ZodSafeParseResult<unknown>;
36
- getPk(item: unknown): unknown;
37
- getSk(item: unknown): unknown;
38
32
  getFieldNames(): string[];
39
- hasField(fieldName: string): boolean;
40
33
  }
41
34
  /**
42
35
  * Configuration for DynamoTable
@@ -56,17 +49,6 @@ interface FieldRef<TName extends string, TType> {
56
49
  fieldName: TName;
57
50
  _type: TType;
58
51
  }
59
- /**
60
- * Subscription message types for WebSocket communication
61
- */
62
- interface SubscriptionMessage {
63
- type: 'subscribe' | 'unsubscribe' | 'patch' | 'snapshot' | 'error';
64
- subscriptionId: string;
65
- path?: string;
66
- input?: unknown;
67
- data?: unknown;
68
- patches?: JsonPatch[];
69
- }
70
52
  /**
71
53
  * JSON Patch operation (RFC 6902)
72
54
  */
@@ -87,6 +69,8 @@ interface DependencyEntry {
87
69
  tableName: string;
88
70
  fieldName: string;
89
71
  fieldValue: string;
72
+ generation: number;
73
+ registrationId: string;
90
74
  ttl: number;
91
75
  }
92
76
  /**
@@ -94,7 +78,13 @@ interface DependencyEntry {
94
78
  */
95
79
  interface ConnectionEntry {
96
80
  connectionId: string;
81
+ status: 'open' | 'closed';
82
+ /** Context explicitly supplied by application-side registration. */
97
83
  context?: Record<string, unknown>;
84
+ /** API Gateway authorizer values captured by the WebSocket connect adapter. */
85
+ authorizerContext?: Record<string, unknown>;
86
+ /** API Gateway request identity captured for IAM-authorized connections. */
87
+ requestIdentity?: Record<string, unknown>;
98
88
  connectedAt: number;
99
89
  ttl: number;
100
90
  }
@@ -102,23 +92,42 @@ interface ConnectionEntry {
102
92
  * Filter condition for query subscriptions (serializable)
103
93
  * Used to evaluate whether a record matches the subscription's query
104
94
  */
105
- interface FilterCondition {
106
- type: 'comparison' | 'logical' | 'function';
107
- operator: string;
108
- field?: string;
109
- value?: unknown;
110
- value2?: unknown;
111
- conditions?: FilterCondition[];
112
- }
95
+ type FilterCondition = {
96
+ type: 'comparison';
97
+ operator: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';
98
+ field: string;
99
+ value: unknown;
100
+ } | {
101
+ type: 'function';
102
+ operator: 'between';
103
+ field: string;
104
+ value: unknown;
105
+ value2: unknown;
106
+ } | {
107
+ type: 'function';
108
+ operator: 'beginsWith' | 'contains';
109
+ field: string;
110
+ value: unknown;
111
+ } | {
112
+ type: 'logical';
113
+ operator: 'and' | 'or' | 'not';
114
+ conditions: FilterCondition[];
115
+ };
113
116
  /**
114
117
  * Query metadata for subscription state (serializable, no router code needed)
115
118
  * Contains all information needed to evaluate stream changes
116
119
  */
117
120
  interface QueryMetadata {
121
+ /** Stored plan format. Unknown versions must be rejected. */
122
+ planVersion: 1;
118
123
  /** Table name being queried */
119
124
  tableName: string;
120
125
  /** Index name if using a GSI */
121
126
  indexName?: string;
127
+ /** Partition key field of the selected sparse index. */
128
+ indexPkField?: string;
129
+ /** Sort key field of the selected sparse index. */
130
+ indexSkField?: string;
122
131
  /** Filter conditions to evaluate against records */
123
132
  filterConditions: FilterCondition[];
124
133
  /** Field to sort by */
@@ -128,6 +137,18 @@ interface QueryMetadata {
128
137
  /** Maximum number of results */
129
138
  limit?: number;
130
139
  }
140
+ interface PendingDeliveryVersion {
141
+ generation: number;
142
+ fromVersion: number;
143
+ toVersion: number;
144
+ messageId: string;
145
+ }
146
+ type PendingDelivery = (PendingDeliveryVersion & {
147
+ type: 'patch';
148
+ patches: JsonPatch[];
149
+ }) | (PendingDeliveryVersion & {
150
+ type: 'resync';
151
+ });
131
152
  /**
132
153
  * Query entry for storing subscription state
133
154
  * Stores all metadata needed to evaluate stream changes without router code
@@ -137,17 +158,22 @@ interface QueryEntry {
137
158
  sk: string;
138
159
  connectionId: string;
139
160
  subscriptionId: string;
161
+ status: 'registering' | 'active' | 'cancelled' | 'faulted';
162
+ generation: number;
163
+ registrationId: string;
140
164
  /** Query metadata for evaluating stream changes */
141
165
  queryMetadata: QueryMetadata;
142
- /** Last query result - can be array or single item depending on procedure */
143
- lastResult: unknown;
166
+ /** Subscription results are always arrays. */
167
+ lastResult: unknown[];
144
168
  /** Dependency keys for the inverted index */
145
169
  dependencies: string[];
146
170
  /** Optimistic locking version - incremented on each update to prevent race conditions */
147
- version?: number;
171
+ version: number;
172
+ /** Delivery is cleared only after its versioned message was sent. */
173
+ pendingDelivery?: PendingDelivery;
148
174
  createdAt: number;
149
175
  updatedAt: number;
150
176
  ttl: number;
151
177
  }
152
178
 
153
- export type { AnyDynamoTable as A, ConnectionEntry as C, DynamoTableConfig as D, FieldRef as F, IndexDefinition as I, JsonPatch as J, QueryMetadata as Q, SupportedSchema as S, FilterCondition as a, DependencyEntry as b, InferSupportedSchema as c, QueryEntry as d, SubscriptionMessage as e };
179
+ export type { AnyDynamoTable as A, ConnectionEntry as C, DynamoTableConfig as D, FieldRef as F, IndexDefinition as I, JsonPatch as J, PendingDelivery as P, QueryMetadata as Q, SupportedSchema as S, FilterCondition as a, DependencyEntry as b, QueryEntry as c };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynamodb-reactive",
3
- "version": "0.1.21",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "A Serverless, Reactive tRPC replacement for AWS DynamoDB",
6
6
  "keywords": [
@@ -17,69 +17,106 @@
17
17
  "author": "andreigec@gmail.com",
18
18
  "repository": {
19
19
  "type": "git",
20
- "url": ""
20
+ "url": "git+https://github.com/andreigec/dynamodb-reactive.git",
21
+ "directory": "packages/dynamodb-reactive"
21
22
  },
22
- "main": "./dist/index.js",
23
- "module": "./dist/index.js",
24
- "types": "./dist/index.d.ts",
23
+ "bugs": {
24
+ "url": "https://github.com/andreigec/dynamodb-reactive/issues"
25
+ },
26
+ "homepage": "https://github.com/andreigec/dynamodb-reactive#readme",
25
27
  "exports": {
26
28
  ".": {
27
- "types": "./dist/index.d.ts",
28
- "import": "./dist/index.js",
29
- "default": "./dist/index.js"
29
+ "import": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ },
33
+ "require": {
34
+ "types": "./dist/index.d.cts",
35
+ "default": "./dist/index.cjs"
36
+ }
30
37
  },
31
38
  "./client": {
32
- "types": "./dist/client.d.ts",
33
- "import": "./dist/client.js",
34
- "default": "./dist/client.js"
39
+ "import": {
40
+ "types": "./dist/client.d.ts",
41
+ "default": "./dist/client.js"
42
+ },
43
+ "require": {
44
+ "types": "./dist/client.d.cts",
45
+ "default": "./dist/client.cjs"
46
+ }
35
47
  },
36
48
  "./react": {
37
- "types": "./dist/react.d.ts",
38
- "import": "./dist/react.js",
39
- "default": "./dist/react.js"
49
+ "import": {
50
+ "types": "./dist/react.d.ts",
51
+ "default": "./dist/react.js"
52
+ },
53
+ "require": {
54
+ "types": "./dist/react.d.cts",
55
+ "default": "./dist/react.cjs"
56
+ }
40
57
  },
41
58
  "./server": {
42
- "types": "./dist/server.d.ts",
43
- "import": "./dist/server.js",
44
- "default": "./dist/server.js"
59
+ "import": {
60
+ "types": "./dist/server.d.ts",
61
+ "default": "./dist/server.js"
62
+ },
63
+ "require": {
64
+ "types": "./dist/server.d.cts",
65
+ "default": "./dist/server.cjs"
66
+ }
45
67
  },
46
68
  "./core": {
47
- "types": "./dist/core.d.ts",
48
- "import": "./dist/core.js",
49
- "default": "./dist/core.js"
69
+ "import": {
70
+ "types": "./dist/core.d.ts",
71
+ "default": "./dist/core.js"
72
+ },
73
+ "require": {
74
+ "types": "./dist/core.d.cts",
75
+ "default": "./dist/core.cjs"
76
+ }
50
77
  },
51
78
  "./infra": {
52
- "types": "./dist/infra.d.ts",
53
- "import": "./dist/infra.js",
54
- "default": "./dist/infra.js"
79
+ "import": {
80
+ "types": "./dist/infra.d.ts",
81
+ "default": "./dist/infra.js"
82
+ },
83
+ "require": {
84
+ "types": "./dist/infra.d.cts",
85
+ "default": "./dist/infra.cjs"
86
+ }
55
87
  }
56
88
  },
57
89
  "files": [
58
90
  "dist",
59
91
  "!**/*.spec.*",
60
92
  "!**/*.test.*",
61
- "README.md"
93
+ "README.md",
94
+ "LICENSE"
62
95
  ],
63
96
  "dependencies": {
64
- "@aws-sdk/client-apigatewaymanagementapi": "^3.983.0",
65
- "@aws-sdk/client-dynamodb": "^3.983.0",
66
- "@aws-sdk/lib-dynamodb": "^3.983.0",
67
- "@aws-sdk/util-dynamodb": "^3.983.0",
68
- "ag-common": "^0.0.871",
97
+ "@aws-sdk/client-apigatewaymanagementapi": "^3.1121.0",
98
+ "@aws-sdk/client-dynamodb": "^3.1121.0",
99
+ "@aws-sdk/lib-dynamodb": "^3.1121.0",
100
+ "@aws-sdk/util-dynamodb": "^3.996.9",
101
+ "@types/aws-lambda": "^8.10.162",
69
102
  "fast-json-patch": "^3.1.1"
70
103
  },
71
104
  "devDependencies": {
72
- "@types/react": "^19.2.11",
73
- "eslint": "^9.39.2",
74
- "rimraf": "^6.1.2",
105
+ "@typescript/typescript6": "^6.0.2",
106
+ "@types/react": "^19.2.18",
107
+ "eslint": "^10.9.1",
108
+ "rimraf": "^6.1.3",
109
+ "rollup": "^4.55.1",
110
+ "rollup-plugin-dts": "^6.5.1",
75
111
  "tsup": "^8.5.1",
76
- "typescript": "^5.9.3"
112
+ "typescript": "^7.0.2"
77
113
  },
78
114
  "peerDependencies": {
79
- "aws-cdk-lib": "^2.237.1",
80
- "constructs": "^10.4.5",
81
- "react": "^19.2.4",
82
- "zod": "^4.3.6"
115
+ "aws-cdk-lib": "^2.267.0",
116
+ "constructs": "^10.8.1",
117
+ "esbuild": ">=0.21.0",
118
+ "react": "^18.2.0 || ^19.0.0",
119
+ "zod": "^4.5.4"
83
120
  },
84
121
  "peerDependenciesMeta": {
85
122
  "react": {
@@ -90,19 +127,20 @@
90
127
  },
91
128
  "constructs": {
92
129
  "optional": true
130
+ },
131
+ "esbuild": {
132
+ "optional": true
93
133
  }
94
134
  },
95
135
  "publishConfig": {
96
136
  "access": "public"
97
137
  },
98
- "engines": {
99
- "node": ">=18.0.0"
100
- },
101
138
  "sideEffects": false,
102
139
  "scripts": {
103
- "build": "tsup",
140
+ "build": "tsup && rollup --config rollup.config.mjs",
104
141
  "dev": "tsup --watch src ../core/src ../client/src ../server/src ../infra/src",
105
142
  "clean": "rimraf dist",
143
+ "test": "pnpm --dir ../.. test",
106
144
  "typecheck": "tsc --noEmit",
107
145
  "format": "eslint src --fix && tsc --noEmit"
108
146
  }