dynamodb-reactive 0.1.5 → 0.1.7
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/{chunk-HZ6JHAJJ.js → chunk-L4NOAOXX.js} +25 -6
- package/dist/chunk-L4NOAOXX.js.map +1 -0
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/index.d.ts +20 -6
- package/dist/index.js +1 -1
- package/dist/infra.d.ts +15 -2
- package/dist/infra.js +17 -5
- package/dist/infra.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1 -1
- package/dist/{table-CfIWxbuJ.d.ts → table-DjeyVXYp.d.ts} +21 -9
- package/dist/{types-DeshTSf5.d.ts → types-2EfCnE0c.d.ts} +12 -2
- package/package.json +1 -1
- package/dist/chunk-HZ6JHAJJ.js.map +0 -1
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
// ../core/src/table.ts
|
|
4
|
+
function getSchemaFields(schema) {
|
|
5
|
+
const fields = /* @__PURE__ */ new Set();
|
|
6
|
+
if ("options" in schema && Array.isArray(schema.options)) {
|
|
7
|
+
for (const option of schema.options) {
|
|
8
|
+
if ("shape" in option && typeof option.shape === "object") {
|
|
9
|
+
for (const key of Object.keys(option.shape)) {
|
|
10
|
+
fields.add(key);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
} else if ("shape" in schema && typeof schema.shape === "object") {
|
|
15
|
+
for (const key of Object.keys(schema.shape)) {
|
|
16
|
+
fields.add(key);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return fields;
|
|
20
|
+
}
|
|
4
21
|
var DynamoTable = class {
|
|
5
22
|
tableName;
|
|
6
23
|
schema;
|
|
@@ -17,9 +34,9 @@ var DynamoTable = class {
|
|
|
17
34
|
this.field = this.createFieldRefs();
|
|
18
35
|
}
|
|
19
36
|
createFieldRefs() {
|
|
20
|
-
const
|
|
37
|
+
const fields = getSchemaFields(this.schema);
|
|
21
38
|
const refs = {};
|
|
22
|
-
for (const key of
|
|
39
|
+
for (const key of fields) {
|
|
23
40
|
refs[key] = {
|
|
24
41
|
fieldName: key,
|
|
25
42
|
_type: void 0
|
|
@@ -58,13 +75,15 @@ var DynamoTable = class {
|
|
|
58
75
|
* Get the list of field names in the schema
|
|
59
76
|
*/
|
|
60
77
|
getFieldNames() {
|
|
61
|
-
return
|
|
78
|
+
return Array.from(
|
|
79
|
+
getSchemaFields(this.schema)
|
|
80
|
+
);
|
|
62
81
|
}
|
|
63
82
|
/**
|
|
64
83
|
* Check if a field exists in the schema
|
|
65
84
|
*/
|
|
66
85
|
hasField(fieldName) {
|
|
67
|
-
return
|
|
86
|
+
return getSchemaFields(this.schema).has(fieldName);
|
|
68
87
|
}
|
|
69
88
|
};
|
|
70
89
|
function defineSchema(config) {
|
|
@@ -127,5 +146,5 @@ var SystemTableNames = {
|
|
|
127
146
|
};
|
|
128
147
|
|
|
129
148
|
export { DynamoTable, SystemSchemas, SystemTableNames, defineSchema };
|
|
130
|
-
//# sourceMappingURL=chunk-
|
|
131
|
-
//# sourceMappingURL=chunk-
|
|
149
|
+
//# sourceMappingURL=chunk-L4NOAOXX.js.map
|
|
150
|
+
//# sourceMappingURL=chunk-L4NOAOXX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../core/src/table.ts","../../core/src/schema.ts"],"names":[],"mappings":"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","file":"chunk-L4NOAOXX.js","sourcesContent":["import type { z } from 'zod';\n\nimport type {\n DynamoTableConfig,\n FieldRef,\n IndexDefinition,\n SupportedSchema,\n} from './types.js';\n\n/**\n * Extract all field names from a schema (handles both ZodObject and ZodDiscriminatedUnion)\n */\nfunction getSchemaFields(schema: SupportedSchema): Set<string> {\n const fields = new Set<string>();\n\n // Check if it's a discriminated union by looking for 'options' property\n if ('options' in schema && Array.isArray(schema.options)) {\n // It's a discriminated union - collect fields from all options\n for (const option of schema.options) {\n if ('shape' in option && typeof option.shape === 'object') {\n for (const key of Object.keys(option.shape)) {\n fields.add(key);\n }\n }\n }\n } else if ('shape' in schema && typeof schema.shape === 'object') {\n // It's a regular ZodObject\n for (const key of Object.keys(schema.shape)) {\n fields.add(key);\n }\n }\n\n return fields;\n}\n\n/**\n * Creates field references for type-safe query building\n */\ntype FieldRefs<TSchema extends SupportedSchema> = {\n [K in keyof z.infer<TSchema>]: FieldRef<K & string, z.infer<TSchema>[K]>;\n};\n\n/**\n * DynamoTable - Defines a DynamoDB table with type-safe schema\n *\n * Supports both ZodObject and ZodDiscriminatedUnion schemas for single-table design patterns.\n *\n * @example\n * ```ts\n * // Simple schema\n * const TodoTable = new DynamoTable({\n * tableName: 'prod-todo-table',\n * schema: z.object({\n * PK: z.string(),\n * SK: z.string(),\n * text: z.string(),\n * isDone: z.boolean(),\n * }),\n * pk: 'PK',\n * sk: 'SK',\n * });\n *\n * // Discriminated union for single-table design\n * const MultiEntityTable = new DynamoTable({\n * tableName: 'prod-entities',\n * schema: z.discriminatedUnion('entityType', [\n * z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('USER'), name: z.string() }),\n * z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('ITEM'), title: z.string() }),\n * ]),\n * pk: 'PK',\n * sk: 'SK',\n * });\n * ```\n */\nexport class DynamoTable<\n TSchema extends SupportedSchema,\n TPk extends keyof z.infer<TSchema>,\n TSk extends keyof z.infer<TSchema> | undefined = undefined,\n TIndexes extends Record<string, IndexDefinition> = Record<\n string,\n IndexDefinition\n >,\n> {\n public readonly tableName: string;\n public readonly schema: TSchema;\n public readonly pk: TPk;\n public readonly sk: TSk;\n public readonly indexes: TIndexes;\n public readonly field: FieldRefs<TSchema>;\n\n constructor(config: DynamoTableConfig<TSchema, TPk, TSk, TIndexes>) {\n this.tableName = config.tableName;\n this.schema = config.schema;\n this.pk = config.pk;\n this.sk = config.sk as TSk;\n this.indexes = (config.indexes ?? {}) as TIndexes;\n\n // Create field references for query building\n this.field = this.createFieldRefs();\n }\n\n private createFieldRefs(): FieldRefs<TSchema> {\n const fields = getSchemaFields(this.schema);\n const refs: Record<string, FieldRef<string, unknown>> = {};\n\n for (const key of fields) {\n refs[key] = {\n fieldName: key,\n _type: undefined as unknown,\n };\n }\n\n return refs as FieldRefs<TSchema>;\n }\n\n /**\n * Validate an item against the schema\n */\n validate(item: unknown): z.infer<TSchema> {\n return this.schema.parse(item);\n }\n\n /**\n * Safely validate an item, returning a result object\n */\n safeParse(item: unknown): z.SafeParseReturnType<unknown, z.infer<TSchema>> {\n return this.schema.safeParse(item);\n }\n\n /**\n * Get the partition key value from an item\n */\n getPk(item: z.infer<TSchema>): z.infer<TSchema>[TPk] {\n return item[this.pk];\n }\n\n /**\n * Get the sort key value from an item (if defined)\n */\n getSk(\n item: z.infer<TSchema>,\n ): TSk extends keyof z.infer<TSchema> ? z.infer<TSchema>[TSk] : undefined {\n if (this.sk === undefined) {\n return undefined as TSk extends keyof z.infer<TSchema>\n ? z.infer<TSchema>[TSk]\n : undefined;\n }\n return item[\n this.sk as keyof z.infer<TSchema>\n ] as TSk extends keyof z.infer<TSchema> ? z.infer<TSchema>[TSk] : undefined;\n }\n\n /**\n * Get the list of field names in the schema\n */\n getFieldNames(): (keyof z.infer<TSchema>)[] {\n return Array.from(\n getSchemaFields(this.schema),\n ) as (keyof z.infer<TSchema>)[];\n }\n\n /**\n * Check if a field exists in the schema\n */\n hasField(fieldName: string): fieldName is keyof z.infer<TSchema> & string {\n return getSchemaFields(this.schema).has(fieldName);\n }\n}\n\n/**\n * Helper type to extract the shape from a Zod schema\n */\nexport type InferSchema<T> =\n T extends DynamoTable<infer TSchema, any, any, any>\n ? z.infer<TSchema>\n : never;\n\n/**\n * Helper type to extract field names from a table\n */\nexport type TableFields<T> =\n T extends DynamoTable<infer TSchema, any, any, any>\n ? keyof z.infer<TSchema>\n : never;\n\n/**\n * Helper type to get the pk field name\n */\nexport type TablePk<T> =\n T extends DynamoTable<any, infer TPk, any, any> ? TPk : never;\n\n/**\n * Helper type to get the sk field name\n */\nexport type TableSk<T> =\n T extends DynamoTable<any, any, infer TSk, any> ? TSk : never;\n\n/**\n * Helper type to get indexes\n */\nexport type TableIndexes<T> =\n T extends DynamoTable<any, any, any, infer TIndexes> ? TIndexes : never;\n","import { z } from 'zod';\n\nimport { DynamoTable } from './table.js';\nimport type { IndexDefinition, SupportedSchema } from './types.js';\n\n/**\n * Helper function to define a schema with type inference\n * This provides a cleaner API for defining tables\n *\n * Supports both ZodObject and ZodDiscriminatedUnion schemas.\n *\n * @example\n * ```ts\n * // Simple schema\n * const TodoTable = defineSchema({\n * tableName: 'prod-todo-table',\n * schema: z.object({\n * id: z.string(),\n * taskListId: z.string(),\n * text: z.string(),\n * isDone: z.boolean(),\n * }),\n * pk: 'id',\n * indexes: {\n * byTaskId: { name: 'gsi_by_task_id', pk: 'taskListId' }\n * }\n * });\n *\n * // Discriminated union for single-table design\n * const MultiEntityTable = defineSchema({\n * tableName: 'prod-entities',\n * schema: z.discriminatedUnion('entityType', [\n * z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('USER'), name: z.string() }),\n * z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('ITEM'), title: z.string() }),\n * ]),\n * pk: 'PK',\n * sk: 'SK',\n * });\n * ```\n */\nexport function defineSchema<\n TSchema extends SupportedSchema,\n TPk extends keyof z.infer<TSchema> & string,\n TSk extends (keyof z.infer<TSchema> & string) | undefined = undefined,\n TIndexes extends Record<string, IndexDefinition> = Record<\n string,\n IndexDefinition\n >,\n>(config: {\n tableName: string;\n schema: TSchema;\n pk: TPk;\n sk?: TSk;\n indexes?: TIndexes;\n}): DynamoTable<TSchema, TPk, TSk, TIndexes> {\n return new DynamoTable(config);\n}\n\n/**\n * System table schemas for the reactive engine\n */\nexport const SystemSchemas = {\n /**\n * ReactiveConnections - Tracks active WebSocket connections\n */\n connections: z.object({\n connectionId: z.string(),\n context: z.record(z.unknown()).optional(),\n connectedAt: z.number(),\n ttl: z.number(),\n }),\n\n /**\n * ReactiveDependencies - The inverted index for O(1) lookups\n */\n dependencies: z.object({\n pk: z.string(), // Format: \"TableName#FieldName#FieldValue\"\n sk: z.string(), // ConnectionID#SubscriptionID\n connectionId: z.string(),\n subscriptionId: z.string(),\n tableName: z.string(),\n fieldName: z.string(),\n fieldValue: z.string(),\n ttl: z.number(),\n }),\n\n /**\n * ReactiveConnectionQueries - Stores subscription state for diffing\n */\n queries: z.object({\n pk: z.string(), // ConnectionID\n sk: z.string(), // SubscriptionID\n connectionId: z.string(),\n subscriptionId: z.string(),\n queryMetadata: z.object({\n tableName: z.string(),\n indexName: z.string().optional(),\n filterConditions: z.array(z.unknown()),\n sortField: z.string().optional(),\n sortOrder: z.enum(['asc', 'desc']).optional(),\n limit: z.number().optional(),\n }),\n lastResult: z.array(z.unknown()),\n dependencies: z.array(z.string()),\n createdAt: z.number(),\n updatedAt: z.number(),\n ttl: z.number(),\n }),\n};\n\n/**\n * System table names\n */\nexport const SystemTableNames = {\n connections: 'ReactiveConnections',\n dependencies: 'ReactiveDependencies',\n queries: 'ReactiveConnectionQueries',\n} as const;\n"]}
|
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { SystemSchemas, SystemTableNames, defineSchema } from './index.js';
|
|
2
|
-
export { D as DynamoTable, I as InferSchema, T as TableFields, a as TableIndexes, b as TablePk, c as TableSk } from './table-
|
|
3
|
-
export { A as AnyDynamoTable, C as ConnectionEntry, b as DependencyEntry, D as DynamoTableConfig, F as FieldRef, a as FilterCondition, I as IndexDefinition, J as JsonPatch,
|
|
2
|
+
export { D as DynamoTable, I as InferSchema, T as TableFields, a as TableIndexes, b as TablePk, c as TableSk } from './table-DjeyVXYp.js';
|
|
3
|
+
export { A as AnyDynamoTable, C as ConnectionEntry, b as DependencyEntry, D as DynamoTableConfig, F as FieldRef, a as FilterCondition, I as IndexDefinition, c as InferSupportedSchema, J as JsonPatch, d as QueryEntry, Q as QueryMetadata, e as SubscriptionMessage, S as SupportedSchema } from './types-2EfCnE0c.js';
|
|
4
4
|
import 'zod';
|
package/dist/core.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { D as DynamoTable } from './table-
|
|
2
|
-
export { I as InferSchema, T as TableFields, a as TableIndexes, b as TablePk, c as TableSk } from './table-
|
|
3
|
-
import { I as IndexDefinition } from './types-
|
|
4
|
-
export { A as AnyDynamoTable, C as ConnectionEntry, b as DependencyEntry, D as DynamoTableConfig, F as FieldRef, a as FilterCondition, J as JsonPatch,
|
|
1
|
+
import { D as DynamoTable } from './table-DjeyVXYp.js';
|
|
2
|
+
export { I as InferSchema, T as TableFields, a as TableIndexes, b as TablePk, c as TableSk } from './table-DjeyVXYp.js';
|
|
3
|
+
import { S as SupportedSchema, I as IndexDefinition } from './types-2EfCnE0c.js';
|
|
4
|
+
export { A as AnyDynamoTable, C as ConnectionEntry, b as DependencyEntry, D as DynamoTableConfig, F as FieldRef, a as FilterCondition, c as InferSupportedSchema, J as JsonPatch, d as QueryEntry, Q as QueryMetadata, e as SubscriptionMessage } from './types-2EfCnE0c.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Helper function to define a schema with type inference
|
|
9
9
|
* This provides a cleaner API for defining tables
|
|
10
10
|
*
|
|
11
|
+
* Supports both ZodObject and ZodDiscriminatedUnion schemas.
|
|
12
|
+
*
|
|
11
13
|
* @example
|
|
12
14
|
* ```ts
|
|
15
|
+
* // Simple schema
|
|
13
16
|
* const TodoTable = defineSchema({
|
|
14
17
|
* tableName: 'prod-todo-table',
|
|
15
18
|
* schema: z.object({
|
|
@@ -23,9 +26,20 @@ import { z } from 'zod';
|
|
|
23
26
|
* byTaskId: { name: 'gsi_by_task_id', pk: 'taskListId' }
|
|
24
27
|
* }
|
|
25
28
|
* });
|
|
29
|
+
*
|
|
30
|
+
* // Discriminated union for single-table design
|
|
31
|
+
* const MultiEntityTable = defineSchema({
|
|
32
|
+
* tableName: 'prod-entities',
|
|
33
|
+
* schema: z.discriminatedUnion('entityType', [
|
|
34
|
+
* z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('USER'), name: z.string() }),
|
|
35
|
+
* z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('ITEM'), title: z.string() }),
|
|
36
|
+
* ]),
|
|
37
|
+
* pk: 'PK',
|
|
38
|
+
* sk: 'SK',
|
|
39
|
+
* });
|
|
26
40
|
* ```
|
|
27
41
|
*/
|
|
28
|
-
declare function defineSchema<TSchema extends
|
|
42
|
+
declare function defineSchema<TSchema extends SupportedSchema, TPk extends keyof z.infer<TSchema> & string, TSk extends (keyof z.infer<TSchema> & string) | undefined = undefined, TIndexes extends Record<string, IndexDefinition> = Record<string, IndexDefinition>>(config: {
|
|
29
43
|
tableName: string;
|
|
30
44
|
schema: TSchema;
|
|
31
45
|
pk: TPk;
|
|
@@ -168,4 +182,4 @@ declare const SystemTableNames: {
|
|
|
168
182
|
readonly queries: "ReactiveConnectionQueries";
|
|
169
183
|
};
|
|
170
184
|
|
|
171
|
-
export { DynamoTable, IndexDefinition, SystemSchemas, SystemTableNames, defineSchema };
|
|
185
|
+
export { DynamoTable, IndexDefinition, SupportedSchema, SystemSchemas, SystemTableNames, defineSchema };
|
package/dist/index.js
CHANGED
package/dist/infra.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AnyDynamoTable } from './types-
|
|
1
|
+
import { A as AnyDynamoTable } from './types-2EfCnE0c.js';
|
|
2
2
|
import * as cdk from 'aws-cdk-lib';
|
|
3
3
|
import * as apigatewayv2 from 'aws-cdk-lib/aws-apigatewayv2';
|
|
4
4
|
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
@@ -7,6 +7,14 @@ import * as logs from 'aws-cdk-lib/aws-logs';
|
|
|
7
7
|
import { Construct } from 'constructs';
|
|
8
8
|
import 'zod';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Provisioning mode for DynamoDB tables
|
|
12
|
+
* - "ON_DEMAND": Pay-per-request billing (default)
|
|
13
|
+
* - { readWrite: number }: Provisioned capacity with specified RCU/WCU
|
|
14
|
+
*/
|
|
15
|
+
type ProvisioningMode = 'ON_DEMAND' | {
|
|
16
|
+
readWrite: number;
|
|
17
|
+
};
|
|
10
18
|
/**
|
|
11
19
|
* Props for ReactiveSystemTables
|
|
12
20
|
*/
|
|
@@ -26,6 +34,11 @@ interface ReactiveSystemTablesProps {
|
|
|
26
34
|
* @default false
|
|
27
35
|
*/
|
|
28
36
|
pointInTimeRecovery?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Provisioning mode for tables
|
|
39
|
+
* @default "ON_DEMAND"
|
|
40
|
+
*/
|
|
41
|
+
provisioningMode?: ProvisioningMode;
|
|
29
42
|
}
|
|
30
43
|
/**
|
|
31
44
|
* Creates the three system tables for the reactive engine
|
|
@@ -186,4 +199,4 @@ declare function createStreamFilter(options: {
|
|
|
186
199
|
*/
|
|
187
200
|
declare function generateEntryPointCode(): string;
|
|
188
201
|
|
|
189
|
-
export { DynamoDBStreamSource, type DynamoDBStreamSourceProps, ReactiveEngine, type ReactiveEngineProps, ReactiveSystemTables, type ReactiveSystemTablesProps, createStreamFilter, generateEntryPointCode };
|
|
202
|
+
export { DynamoDBStreamSource, type DynamoDBStreamSourceProps, type ProvisioningMode, ReactiveEngine, type ReactiveEngineProps, ReactiveSystemTables, type ReactiveSystemTablesProps, createStreamFilter, generateEntryPointCode };
|
package/dist/infra.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SystemTableNames } from './chunk-
|
|
1
|
+
import { SystemTableNames } from './chunk-L4NOAOXX.js';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import * as cdk2 from 'aws-cdk-lib';
|
|
@@ -43,13 +43,20 @@ var ReactiveSystemTables = class extends Construct {
|
|
|
43
43
|
const prefix = props.tablePrefix ? `${props.tablePrefix}-` : "";
|
|
44
44
|
const removalPolicy = props.removalPolicy ?? cdk2.RemovalPolicy.RETAIN;
|
|
45
45
|
const pointInTimeRecovery = props.pointInTimeRecovery ?? false;
|
|
46
|
+
const provisioningMode = props.provisioningMode ?? "ON_DEMAND";
|
|
47
|
+
const isOnDemand = provisioningMode === "ON_DEMAND";
|
|
48
|
+
const capacityProps = isOnDemand ? { billingMode: dynamodb.BillingMode.PAY_PER_REQUEST } : {
|
|
49
|
+
billingMode: dynamodb.BillingMode.PROVISIONED,
|
|
50
|
+
readCapacity: provisioningMode.readWrite,
|
|
51
|
+
writeCapacity: provisioningMode.readWrite
|
|
52
|
+
};
|
|
46
53
|
this.connectionsTable = new dynamodb.Table(this, "ConnectionsTable", {
|
|
47
54
|
tableName: `${prefix}${SystemTableNames.connections}`,
|
|
48
55
|
partitionKey: {
|
|
49
56
|
name: "connectionId",
|
|
50
57
|
type: dynamodb.AttributeType.STRING
|
|
51
58
|
},
|
|
52
|
-
|
|
59
|
+
...capacityProps,
|
|
53
60
|
removalPolicy,
|
|
54
61
|
pointInTimeRecovery,
|
|
55
62
|
timeToLiveAttribute: "ttl"
|
|
@@ -66,18 +73,23 @@ var ReactiveSystemTables = class extends Construct {
|
|
|
66
73
|
// Format: "ConnectionID#SubscriptionID"
|
|
67
74
|
type: dynamodb.AttributeType.STRING
|
|
68
75
|
},
|
|
69
|
-
|
|
76
|
+
...capacityProps,
|
|
70
77
|
removalPolicy,
|
|
71
78
|
pointInTimeRecovery,
|
|
72
79
|
timeToLiveAttribute: "ttl"
|
|
73
80
|
});
|
|
81
|
+
const gsiProps = isOnDemand ? {} : {
|
|
82
|
+
readCapacity: provisioningMode.readWrite,
|
|
83
|
+
writeCapacity: provisioningMode.readWrite
|
|
84
|
+
};
|
|
74
85
|
this.dependenciesTable.addGlobalSecondaryIndex({
|
|
75
86
|
indexName: "byConnectionId",
|
|
76
87
|
partitionKey: {
|
|
77
88
|
name: "connectionId",
|
|
78
89
|
type: dynamodb.AttributeType.STRING
|
|
79
90
|
},
|
|
80
|
-
projectionType: dynamodb.ProjectionType.KEYS_ONLY
|
|
91
|
+
projectionType: dynamodb.ProjectionType.KEYS_ONLY,
|
|
92
|
+
...gsiProps
|
|
81
93
|
});
|
|
82
94
|
this.queriesTable = new dynamodb.Table(this, "QueriesTable", {
|
|
83
95
|
tableName: `${prefix}${SystemTableNames.queries}`,
|
|
@@ -91,7 +103,7 @@ var ReactiveSystemTables = class extends Construct {
|
|
|
91
103
|
// SubscriptionID
|
|
92
104
|
type: dynamodb.AttributeType.STRING
|
|
93
105
|
},
|
|
94
|
-
|
|
106
|
+
...capacityProps,
|
|
95
107
|
removalPolicy,
|
|
96
108
|
pointInTimeRecovery,
|
|
97
109
|
timeToLiveAttribute: "ttl"
|
package/dist/infra.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../infra/src/handlers/lambda-handlers.ts","../../infra/src/tables.ts","../../infra/src/engine.ts","../../infra/src/stream-source.ts"],"names":["cdk","Construct","cdk3","lambda2"],"mappings":"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","file":"infra.js","sourcesContent":["/**\n * Entry point code generator for the reactive Lambda handlers.\n *\n * No user code is imported - the handlers use only environment variables\n * and stored query metadata for all operations.\n */\n\n/**\n * Generate the entry point code for Lambda functions.\n * This is called by the CDK construct to create the bundled entry file.\n */\nexport function generateEntryPointCode(): string {\n return `// Auto-generated entry point for reactive Lambda handlers\n// No user code required - all configuration comes from environment variables\nimport { createLambdaHandlers } from 'dynamodb-reactive/server';\n\nconst handlers = createLambdaHandlers();\n\nexport const connectHandler = handlers.connectHandler;\nexport const disconnectHandler = handlers.disconnectHandler;\nexport const messageHandler = handlers.messageHandler;\nexport const streamHandler = handlers.streamHandler;\n`;\n}\n","import { SystemTableNames } from '@dynamodb-reactive/core';\nimport * as cdk from 'aws-cdk-lib';\nimport * as dynamodb from 'aws-cdk-lib/aws-dynamodb';\nimport { Construct } from 'constructs';\n\n/**\n * Props for ReactiveSystemTables\n */\nexport interface ReactiveSystemTablesProps {\n /**\n * Prefix for table names\n * @default - no prefix\n */\n tablePrefix?: string;\n\n /**\n * Removal policy for tables\n * @default - cdk.RemovalPolicy.RETAIN\n */\n removalPolicy?: cdk.RemovalPolicy;\n\n /**\n * Enable point-in-time recovery\n * @default false\n */\n pointInTimeRecovery?: boolean;\n}\n\n/**\n * Creates the three system tables for the reactive engine\n */\nexport class ReactiveSystemTables extends Construct {\n /**\n * ReactiveConnections table - tracks WebSocket connections\n */\n public readonly connectionsTable: dynamodb.Table;\n\n /**\n * ReactiveDependencies table - the inverted index\n */\n public readonly dependenciesTable: dynamodb.Table;\n\n /**\n * ReactiveConnectionQueries table - stores subscription state\n */\n public readonly queriesTable: dynamodb.Table;\n\n constructor(\n scope: Construct,\n id: string,\n props: ReactiveSystemTablesProps = {},\n ) {\n super(scope, id);\n\n const prefix = props.tablePrefix ? `${props.tablePrefix}-` : '';\n const removalPolicy = props.removalPolicy ?? cdk.RemovalPolicy.RETAIN;\n const pointInTimeRecovery = props.pointInTimeRecovery ?? false;\n\n // ReactiveConnections Table\n // Tracks active WebSocket connections and user context\n this.connectionsTable = new dynamodb.Table(this, 'ConnectionsTable', {\n tableName: `${prefix}${SystemTableNames.connections}`,\n partitionKey: {\n name: 'connectionId',\n type: dynamodb.AttributeType.STRING,\n },\n billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,\n removalPolicy,\n pointInTimeRecovery,\n timeToLiveAttribute: 'ttl',\n });\n\n // ReactiveDependencies Table (The Inverted Index)\n // Maps Field#Value -> ConnectionID for O(1) lookups\n this.dependenciesTable = new dynamodb.Table(this, 'DependenciesTable', {\n tableName: `${prefix}${SystemTableNames.dependencies}`,\n partitionKey: {\n name: 'pk', // Format: \"TableName#FieldName#FieldValue\"\n type: dynamodb.AttributeType.STRING,\n },\n sortKey: {\n name: 'sk', // Format: \"ConnectionID#SubscriptionID\"\n type: dynamodb.AttributeType.STRING,\n },\n billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,\n removalPolicy,\n pointInTimeRecovery,\n timeToLiveAttribute: 'ttl',\n });\n\n // Add GSI for querying by connectionId (for cleanup)\n this.dependenciesTable.addGlobalSecondaryIndex({\n indexName: 'byConnectionId',\n partitionKey: {\n name: 'connectionId',\n type: dynamodb.AttributeType.STRING,\n },\n projectionType: dynamodb.ProjectionType.KEYS_ONLY,\n });\n\n // ReactiveConnectionQueries Table\n // Stores subscription state for diffing\n this.queriesTable = new dynamodb.Table(this, 'QueriesTable', {\n tableName: `${prefix}${SystemTableNames.queries}`,\n partitionKey: {\n name: 'pk', // ConnectionID\n type: dynamodb.AttributeType.STRING,\n },\n sortKey: {\n name: 'sk', // SubscriptionID\n type: dynamodb.AttributeType.STRING,\n },\n billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,\n removalPolicy,\n pointInTimeRecovery,\n timeToLiveAttribute: 'ttl',\n });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { AnyDynamoTable } from '@dynamodb-reactive/core';\nimport * as cdk from 'aws-cdk-lib';\nimport * as apigatewayv2 from 'aws-cdk-lib/aws-apigatewayv2';\nimport * as apigatewayv2Integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';\nimport type * as dynamodb from 'aws-cdk-lib/aws-dynamodb';\nimport * as iam from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport * as nodejs from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as logs from 'aws-cdk-lib/aws-logs';\nimport { Construct } from 'constructs';\n\nimport { generateEntryPointCode } from './handlers/lambda-handlers.js';\nimport {\n ReactiveSystemTables,\n type ReactiveSystemTablesProps,\n} from './tables.js';\n\n/**\n * Props for ReactiveEngine construct\n */\nexport interface ReactiveEngineProps {\n /**\n * User-defined DynamoDB tables to enable reactive updates on\n */\n tables: AnyDynamoTable[];\n\n /**\n * Prefix for all resource names\n * @default - no prefix\n */\n resourcePrefix?: string;\n\n /**\n * System tables configuration\n */\n systemTablesProps?: ReactiveSystemTablesProps;\n\n /**\n * Lambda function memory size in MB\n * @default 256\n */\n memorySize?: number;\n\n /**\n * Lambda function timeout\n * @default Duration.seconds(30)\n */\n timeout?: cdk.Duration;\n\n /**\n * Log retention period\n * @default logs.RetentionDays.ONE_WEEK\n */\n logRetention?: logs.RetentionDays;\n\n /**\n * Environment variables for Lambda functions\n */\n environment?: Record<string, string>;\n\n /**\n * Enable tracing with X-Ray\n * @default false\n */\n tracing?: boolean;\n}\n\n/**\n * ReactiveEngine - Main CDK construct for the reactive DynamoDB system\n */\nexport class ReactiveEngine extends Construct {\n public readonly systemTables: ReactiveSystemTables;\n public readonly webSocketApi: apigatewayv2.WebSocketApi;\n public readonly webSocketStage: apigatewayv2.WebSocketStage;\n public readonly connectHandler: lambda.Function;\n public readonly disconnectHandler: lambda.Function;\n public readonly messageHandler: lambda.Function;\n public readonly streamHandler: lambda.Function;\n public readonly webSocketUrl: string;\n public readonly callbackUrl: string;\n\n constructor(scope: Construct, id: string, props: ReactiveEngineProps) {\n super(scope, id);\n\n const prefix = props.resourcePrefix ?? '';\n const memorySize = props.memorySize ?? 256;\n const timeout = props.timeout ?? cdk.Duration.seconds(30);\n const logRetention = props.logRetention ?? logs.RetentionDays.ONE_WEEK;\n\n // Create system tables\n this.systemTables = new ReactiveSystemTables(this, 'SystemTables', {\n tablePrefix: prefix,\n ...props.systemTablesProps,\n });\n\n // Create WebSocket API\n this.webSocketApi = new apigatewayv2.WebSocketApi(this, 'WebSocketApi', {\n apiName: `${prefix}ReactiveWebSocket`,\n });\n\n this.webSocketStage = new apigatewayv2.WebSocketStage(\n this,\n 'WebSocketStage',\n {\n webSocketApi: this.webSocketApi,\n stageName: 'prod',\n autoDeploy: true,\n },\n );\n\n this.webSocketUrl = this.webSocketStage.url;\n this.callbackUrl = this.webSocketStage.callbackUrl;\n\n // Generate the entry point file (no user code required)\n // Write to cdk.out directory to avoid path resolution issues with temp directories\n const entryPointCode = generateEntryPointCode();\n const cdkOutDir = path.join(process.cwd(), 'cdk.out', '.generated');\n fs.mkdirSync(cdkOutDir, { recursive: true });\n const entryPointPath = path.join(\n cdkOutDir,\n `reactive-entry-${id}-${Date.now()}.ts`,\n );\n fs.writeFileSync(entryPointPath, entryPointCode);\n\n // Common environment variables\n const environment: Record<string, string> = {\n CONNECTIONS_TABLE: this.systemTables.connectionsTable.tableName,\n DEPENDENCIES_TABLE: this.systemTables.dependenciesTable.tableName,\n QUERIES_TABLE: this.systemTables.queriesTable.tableName,\n WEBSOCKET_ENDPOINT: this.callbackUrl,\n ...props.environment,\n };\n\n // Create handlers using NodejsFunction with the generated entry point\n this.connectHandler = new nodejs.NodejsFunction(this, 'ConnectHandler', {\n functionName: `${prefix}ReactiveConnect`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'connectHandler',\n entry: entryPointPath,\n environment,\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,\n });\n\n this.disconnectHandler = new nodejs.NodejsFunction(\n this,\n 'DisconnectHandler',\n {\n functionName: `${prefix}ReactiveDisconnect`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'disconnectHandler',\n entry: entryPointPath,\n environment,\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing\n ? lambda.Tracing.ACTIVE\n : lambda.Tracing.DISABLED,\n },\n );\n\n this.messageHandler = new nodejs.NodejsFunction(this, 'MessageHandler', {\n functionName: `${prefix}ReactiveMessage`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'messageHandler',\n entry: entryPointPath,\n environment,\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,\n });\n\n this.streamHandler = new nodejs.NodejsFunction(this, 'StreamHandler', {\n functionName: `${prefix}ReactiveStream`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'streamHandler',\n entry: entryPointPath,\n environment: {\n ...environment,\n USER_TABLES: props.tables.map((t) => t.tableName).join(','),\n },\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,\n });\n\n // Grant permissions for system tables\n this.systemTables.connectionsTable.grantReadWriteData(this.connectHandler);\n this.systemTables.connectionsTable.grantReadWriteData(\n this.disconnectHandler,\n );\n this.systemTables.connectionsTable.grantReadWriteData(this.messageHandler);\n this.systemTables.connectionsTable.grantReadWriteData(this.streamHandler);\n\n this.systemTables.dependenciesTable.grantReadWriteData(this.messageHandler);\n this.systemTables.dependenciesTable.grantReadWriteData(this.streamHandler);\n\n this.systemTables.queriesTable.grantReadWriteData(this.messageHandler);\n this.systemTables.queriesTable.grantReadWriteData(this.streamHandler);\n\n // Grant WebSocket management permissions\n const managementPolicy = new iam.PolicyStatement({\n actions: ['execute-api:ManageConnections'],\n resources: [\n `arn:aws:execute-api:${cdk.Stack.of(this).region}:${cdk.Stack.of(this).account}:${this.webSocketApi.apiId}/${this.webSocketStage.stageName}/POST/@connections/*`,\n ],\n });\n\n this.messageHandler.addToRolePolicy(managementPolicy);\n this.streamHandler.addToRolePolicy(managementPolicy);\n\n // Set up WebSocket routes\n this.webSocketApi.addRoute('$connect', {\n integration: new apigatewayv2Integrations.WebSocketLambdaIntegration(\n 'ConnectIntegration',\n this.connectHandler,\n ),\n });\n\n this.webSocketApi.addRoute('$disconnect', {\n integration: new apigatewayv2Integrations.WebSocketLambdaIntegration(\n 'DisconnectIntegration',\n this.disconnectHandler,\n ),\n });\n\n this.webSocketApi.addRoute('$default', {\n integration: new apigatewayv2Integrations.WebSocketLambdaIntegration(\n 'DefaultIntegration',\n this.messageHandler,\n ),\n });\n\n // Set up DynamoDB stream processing for user tables\n for (const table of props.tables) {\n this.setupStreamProcessing(table);\n }\n\n // Output the WebSocket URL\n new cdk.CfnOutput(this, 'WebSocketUrl', {\n value: this.webSocketUrl,\n description: 'WebSocket URL for reactive connections',\n });\n }\n\n private setupStreamProcessing(table: AnyDynamoTable): void {\n const tableArn = `arn:aws:dynamodb:${cdk.Stack.of(this).region}:${cdk.Stack.of(this).account}:table/${table.tableName}`;\n const streamArn = `${tableArn}/stream/*`;\n\n // Stream handler needs stream access\n this.streamHandler.addToRolePolicy(\n new iam.PolicyStatement({\n actions: [\n 'dynamodb:GetRecords',\n 'dynamodb:GetShardIterator',\n 'dynamodb:DescribeStream',\n 'dynamodb:ListStreams',\n ],\n resources: [streamArn],\n }),\n );\n\n // Both handlers need read access to user tables (including PartiQL for queries)\n const tableReadPolicy = new iam.PolicyStatement({\n actions: [\n 'dynamodb:Query',\n 'dynamodb:Scan',\n 'dynamodb:GetItem',\n 'dynamodb:BatchGetItem',\n 'dynamodb:PartiQLSelect',\n ],\n resources: [tableArn, `${tableArn}/index/*`],\n });\n\n this.streamHandler.addToRolePolicy(tableReadPolicy);\n this.messageHandler.addToRolePolicy(tableReadPolicy);\n\n // Message handler also needs write access for mutations\n this.messageHandler.addToRolePolicy(\n new iam.PolicyStatement({\n actions: [\n 'dynamodb:PutItem',\n 'dynamodb:UpdateItem',\n 'dynamodb:DeleteItem',\n 'dynamodb:BatchWriteItem',\n 'dynamodb:PartiQLInsert',\n 'dynamodb:PartiQLUpdate',\n 'dynamodb:PartiQLDelete',\n ],\n resources: [tableArn, `${tableArn}/index/*`],\n }),\n );\n }\n\n public addTable(table: dynamodb.ITable): void {\n if (!table.tableStreamArn) {\n throw new Error(`Table ${table.tableName} does not have streams enabled`);\n }\n\n table.grantStreamRead(this.streamHandler);\n table.grantReadData(this.streamHandler);\n\n new lambda.EventSourceMapping(this, `Stream-${table.tableName}`, {\n target: this.streamHandler,\n eventSourceArn: table.tableStreamArn,\n startingPosition: lambda.StartingPosition.TRIM_HORIZON,\n batchSize: 100,\n maxBatchingWindow: cdk.Duration.seconds(5),\n });\n }\n}\n","import * as cdk from 'aws-cdk-lib';\nimport type * as dynamodb from 'aws-cdk-lib/aws-dynamodb';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport { Construct } from 'constructs';\n\n/**\n * Props for DynamoDBStreamSource\n */\nexport interface DynamoDBStreamSourceProps {\n /**\n * The DynamoDB table to create a stream source for\n */\n table: dynamodb.ITable;\n\n /**\n * The Lambda function to receive stream events\n */\n target: lambda.IFunction;\n\n /**\n * Batch size for stream processing\n * @default 100\n */\n batchSize?: number;\n\n /**\n * Maximum batching window\n * @default Duration.seconds(5)\n */\n maxBatchingWindow?: cdk.Duration;\n\n /**\n * Starting position for reading the stream\n * @default TRIM_HORIZON\n */\n startingPosition?: lambda.StartingPosition;\n\n /**\n * Enable parallel processing with multiple batches\n * @default 1\n */\n parallelizationFactor?: number;\n\n /**\n * Maximum record age to process\n * @default Duration.days(1)\n */\n maxRecordAge?: cdk.Duration;\n\n /**\n * Number of retries on failure\n * @default 3\n */\n retryAttempts?: number;\n\n /**\n * Filter patterns for the event source\n */\n filters?: lambda.FilterCriteria[];\n}\n\n/**\n * Helper construct for setting up DynamoDB stream event sources\n */\nexport class DynamoDBStreamSource extends Construct {\n public readonly eventSourceMapping: lambda.EventSourceMapping;\n\n constructor(scope: Construct, id: string, props: DynamoDBStreamSourceProps) {\n super(scope, id);\n\n const {\n table,\n target,\n batchSize = 100,\n maxBatchingWindow = cdk.Duration.seconds(5),\n startingPosition = lambda.StartingPosition.TRIM_HORIZON,\n parallelizationFactor = 1,\n maxRecordAge = cdk.Duration.days(1),\n retryAttempts = 3,\n filters,\n } = props;\n\n if (!table.tableStreamArn) {\n throw new Error(\n `Table ${table.tableName} does not have DynamoDB Streams enabled. ` +\n 'Enable streams with streamSpecification when creating the table.',\n );\n }\n\n // Grant stream read permissions\n table.grantStreamRead(target);\n\n // Create the event source mapping\n this.eventSourceMapping = new lambda.EventSourceMapping(\n this,\n 'EventSource',\n {\n target,\n eventSourceArn: table.tableStreamArn,\n startingPosition,\n batchSize,\n maxBatchingWindow,\n parallelizationFactor,\n maxRecordAge,\n retryAttempts,\n bisectBatchOnError: true,\n reportBatchItemFailures: true,\n filters,\n },\n );\n }\n}\n\n/**\n * Create a filter criteria for DynamoDB streams\n */\nexport function createStreamFilter(options: {\n /**\n * Filter by event name (INSERT, MODIFY, REMOVE)\n */\n eventName?: ('INSERT' | 'MODIFY' | 'REMOVE')[];\n\n /**\n * Custom filter patterns\n */\n patterns?: Record<string, unknown>[];\n}): lambda.FilterCriteria[] {\n const filters: Record<string, unknown>[] = [];\n\n if (options.eventName) {\n filters.push({\n eventName: options.eventName,\n });\n }\n\n if (options.patterns) {\n filters.push(...options.patterns);\n }\n\n if (filters.length === 0) {\n return [];\n }\n\n return [lambda.FilterCriteria.filter({ filters })];\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../infra/src/handlers/lambda-handlers.ts","../../infra/src/tables.ts","../../infra/src/engine.ts","../../infra/src/stream-source.ts"],"names":["cdk","Construct","cdk3","lambda2"],"mappings":"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","file":"infra.js","sourcesContent":["/**\n * Entry point code generator for the reactive Lambda handlers.\n *\n * No user code is imported - the handlers use only environment variables\n * and stored query metadata for all operations.\n */\n\n/**\n * Generate the entry point code for Lambda functions.\n * This is called by the CDK construct to create the bundled entry file.\n */\nexport function generateEntryPointCode(): string {\n return `// Auto-generated entry point for reactive Lambda handlers\n// No user code required - all configuration comes from environment variables\nimport { createLambdaHandlers } from 'dynamodb-reactive/server';\n\nconst handlers = createLambdaHandlers();\n\nexport const connectHandler = handlers.connectHandler;\nexport const disconnectHandler = handlers.disconnectHandler;\nexport const messageHandler = handlers.messageHandler;\nexport const streamHandler = handlers.streamHandler;\n`;\n}\n","import { SystemTableNames } from '@dynamodb-reactive/core';\nimport * as cdk from 'aws-cdk-lib';\nimport * as dynamodb from 'aws-cdk-lib/aws-dynamodb';\nimport { Construct } from 'constructs';\n\n/**\n * Provisioning mode for DynamoDB tables\n * - \"ON_DEMAND\": Pay-per-request billing (default)\n * - { readWrite: number }: Provisioned capacity with specified RCU/WCU\n */\nexport type ProvisioningMode = 'ON_DEMAND' | { readWrite: number };\n\n/**\n * Props for ReactiveSystemTables\n */\nexport interface ReactiveSystemTablesProps {\n /**\n * Prefix for table names\n * @default - no prefix\n */\n tablePrefix?: string;\n\n /**\n * Removal policy for tables\n * @default - cdk.RemovalPolicy.RETAIN\n */\n removalPolicy?: cdk.RemovalPolicy;\n\n /**\n * Enable point-in-time recovery\n * @default false\n */\n pointInTimeRecovery?: boolean;\n\n /**\n * Provisioning mode for tables\n * @default \"ON_DEMAND\"\n */\n provisioningMode?: ProvisioningMode;\n}\n\n/**\n * Creates the three system tables for the reactive engine\n */\nexport class ReactiveSystemTables extends Construct {\n /**\n * ReactiveConnections table - tracks WebSocket connections\n */\n public readonly connectionsTable: dynamodb.Table;\n\n /**\n * ReactiveDependencies table - the inverted index\n */\n public readonly dependenciesTable: dynamodb.Table;\n\n /**\n * ReactiveConnectionQueries table - stores subscription state\n */\n public readonly queriesTable: dynamodb.Table;\n\n constructor(\n scope: Construct,\n id: string,\n props: ReactiveSystemTablesProps = {},\n ) {\n super(scope, id);\n\n const prefix = props.tablePrefix ? `${props.tablePrefix}-` : '';\n const removalPolicy = props.removalPolicy ?? cdk.RemovalPolicy.RETAIN;\n const pointInTimeRecovery = props.pointInTimeRecovery ?? false;\n const provisioningMode = props.provisioningMode ?? 'ON_DEMAND';\n\n // Determine billing/capacity settings\n const isOnDemand = provisioningMode === 'ON_DEMAND';\n const capacityProps = isOnDemand\n ? { billingMode: dynamodb.BillingMode.PAY_PER_REQUEST }\n : {\n billingMode: dynamodb.BillingMode.PROVISIONED,\n readCapacity: provisioningMode.readWrite,\n writeCapacity: provisioningMode.readWrite,\n };\n\n // ReactiveConnections Table\n // Tracks active WebSocket connections and user context\n this.connectionsTable = new dynamodb.Table(this, 'ConnectionsTable', {\n tableName: `${prefix}${SystemTableNames.connections}`,\n partitionKey: {\n name: 'connectionId',\n type: dynamodb.AttributeType.STRING,\n },\n ...capacityProps,\n removalPolicy,\n pointInTimeRecovery,\n timeToLiveAttribute: 'ttl',\n });\n\n // ReactiveDependencies Table (The Inverted Index)\n // Maps Field#Value -> ConnectionID for O(1) lookups\n this.dependenciesTable = new dynamodb.Table(this, 'DependenciesTable', {\n tableName: `${prefix}${SystemTableNames.dependencies}`,\n partitionKey: {\n name: 'pk', // Format: \"TableName#FieldName#FieldValue\"\n type: dynamodb.AttributeType.STRING,\n },\n sortKey: {\n name: 'sk', // Format: \"ConnectionID#SubscriptionID\"\n type: dynamodb.AttributeType.STRING,\n },\n ...capacityProps,\n removalPolicy,\n pointInTimeRecovery,\n timeToLiveAttribute: 'ttl',\n });\n\n // Add GSI for querying by connectionId (for cleanup)\n // For provisioned mode, GSI needs its own capacity\n const gsiProps = isOnDemand\n ? {}\n : {\n readCapacity: provisioningMode.readWrite,\n writeCapacity: provisioningMode.readWrite,\n };\n\n this.dependenciesTable.addGlobalSecondaryIndex({\n indexName: 'byConnectionId',\n partitionKey: {\n name: 'connectionId',\n type: dynamodb.AttributeType.STRING,\n },\n projectionType: dynamodb.ProjectionType.KEYS_ONLY,\n ...gsiProps,\n });\n\n // ReactiveConnectionQueries Table\n // Stores subscription state for diffing\n this.queriesTable = new dynamodb.Table(this, 'QueriesTable', {\n tableName: `${prefix}${SystemTableNames.queries}`,\n partitionKey: {\n name: 'pk', // ConnectionID\n type: dynamodb.AttributeType.STRING,\n },\n sortKey: {\n name: 'sk', // SubscriptionID\n type: dynamodb.AttributeType.STRING,\n },\n ...capacityProps,\n removalPolicy,\n pointInTimeRecovery,\n timeToLiveAttribute: 'ttl',\n });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { AnyDynamoTable } from '@dynamodb-reactive/core';\nimport * as cdk from 'aws-cdk-lib';\nimport * as apigatewayv2 from 'aws-cdk-lib/aws-apigatewayv2';\nimport * as apigatewayv2Integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';\nimport type * as dynamodb from 'aws-cdk-lib/aws-dynamodb';\nimport * as iam from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport * as nodejs from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as logs from 'aws-cdk-lib/aws-logs';\nimport { Construct } from 'constructs';\n\nimport { generateEntryPointCode } from './handlers/lambda-handlers.js';\nimport {\n ReactiveSystemTables,\n type ReactiveSystemTablesProps,\n} from './tables.js';\n\n/**\n * Props for ReactiveEngine construct\n */\nexport interface ReactiveEngineProps {\n /**\n * User-defined DynamoDB tables to enable reactive updates on\n */\n tables: AnyDynamoTable[];\n\n /**\n * Prefix for all resource names\n * @default - no prefix\n */\n resourcePrefix?: string;\n\n /**\n * System tables configuration\n */\n systemTablesProps?: ReactiveSystemTablesProps;\n\n /**\n * Lambda function memory size in MB\n * @default 256\n */\n memorySize?: number;\n\n /**\n * Lambda function timeout\n * @default Duration.seconds(30)\n */\n timeout?: cdk.Duration;\n\n /**\n * Log retention period\n * @default logs.RetentionDays.ONE_WEEK\n */\n logRetention?: logs.RetentionDays;\n\n /**\n * Environment variables for Lambda functions\n */\n environment?: Record<string, string>;\n\n /**\n * Enable tracing with X-Ray\n * @default false\n */\n tracing?: boolean;\n}\n\n/**\n * ReactiveEngine - Main CDK construct for the reactive DynamoDB system\n */\nexport class ReactiveEngine extends Construct {\n public readonly systemTables: ReactiveSystemTables;\n public readonly webSocketApi: apigatewayv2.WebSocketApi;\n public readonly webSocketStage: apigatewayv2.WebSocketStage;\n public readonly connectHandler: lambda.Function;\n public readonly disconnectHandler: lambda.Function;\n public readonly messageHandler: lambda.Function;\n public readonly streamHandler: lambda.Function;\n public readonly webSocketUrl: string;\n public readonly callbackUrl: string;\n\n constructor(scope: Construct, id: string, props: ReactiveEngineProps) {\n super(scope, id);\n\n const prefix = props.resourcePrefix ?? '';\n const memorySize = props.memorySize ?? 256;\n const timeout = props.timeout ?? cdk.Duration.seconds(30);\n const logRetention = props.logRetention ?? logs.RetentionDays.ONE_WEEK;\n\n // Create system tables\n this.systemTables = new ReactiveSystemTables(this, 'SystemTables', {\n tablePrefix: prefix,\n ...props.systemTablesProps,\n });\n\n // Create WebSocket API\n this.webSocketApi = new apigatewayv2.WebSocketApi(this, 'WebSocketApi', {\n apiName: `${prefix}ReactiveWebSocket`,\n });\n\n this.webSocketStage = new apigatewayv2.WebSocketStage(\n this,\n 'WebSocketStage',\n {\n webSocketApi: this.webSocketApi,\n stageName: 'prod',\n autoDeploy: true,\n },\n );\n\n this.webSocketUrl = this.webSocketStage.url;\n this.callbackUrl = this.webSocketStage.callbackUrl;\n\n // Generate the entry point file (no user code required)\n // Write to cdk.out directory to avoid path resolution issues with temp directories\n const entryPointCode = generateEntryPointCode();\n const cdkOutDir = path.join(process.cwd(), 'cdk.out', '.generated');\n fs.mkdirSync(cdkOutDir, { recursive: true });\n const entryPointPath = path.join(\n cdkOutDir,\n `reactive-entry-${id}-${Date.now()}.ts`,\n );\n fs.writeFileSync(entryPointPath, entryPointCode);\n\n // Common environment variables\n const environment: Record<string, string> = {\n CONNECTIONS_TABLE: this.systemTables.connectionsTable.tableName,\n DEPENDENCIES_TABLE: this.systemTables.dependenciesTable.tableName,\n QUERIES_TABLE: this.systemTables.queriesTable.tableName,\n WEBSOCKET_ENDPOINT: this.callbackUrl,\n ...props.environment,\n };\n\n // Create handlers using NodejsFunction with the generated entry point\n this.connectHandler = new nodejs.NodejsFunction(this, 'ConnectHandler', {\n functionName: `${prefix}ReactiveConnect`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'connectHandler',\n entry: entryPointPath,\n environment,\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,\n });\n\n this.disconnectHandler = new nodejs.NodejsFunction(\n this,\n 'DisconnectHandler',\n {\n functionName: `${prefix}ReactiveDisconnect`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'disconnectHandler',\n entry: entryPointPath,\n environment,\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing\n ? lambda.Tracing.ACTIVE\n : lambda.Tracing.DISABLED,\n },\n );\n\n this.messageHandler = new nodejs.NodejsFunction(this, 'MessageHandler', {\n functionName: `${prefix}ReactiveMessage`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'messageHandler',\n entry: entryPointPath,\n environment,\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,\n });\n\n this.streamHandler = new nodejs.NodejsFunction(this, 'StreamHandler', {\n functionName: `${prefix}ReactiveStream`,\n runtime: lambda.Runtime.NODEJS_LATEST,\n handler: 'streamHandler',\n entry: entryPointPath,\n environment: {\n ...environment,\n USER_TABLES: props.tables.map((t) => t.tableName).join(','),\n },\n memorySize,\n timeout,\n logRetention,\n tracing: props.tracing ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,\n });\n\n // Grant permissions for system tables\n this.systemTables.connectionsTable.grantReadWriteData(this.connectHandler);\n this.systemTables.connectionsTable.grantReadWriteData(\n this.disconnectHandler,\n );\n this.systemTables.connectionsTable.grantReadWriteData(this.messageHandler);\n this.systemTables.connectionsTable.grantReadWriteData(this.streamHandler);\n\n this.systemTables.dependenciesTable.grantReadWriteData(this.messageHandler);\n this.systemTables.dependenciesTable.grantReadWriteData(this.streamHandler);\n\n this.systemTables.queriesTable.grantReadWriteData(this.messageHandler);\n this.systemTables.queriesTable.grantReadWriteData(this.streamHandler);\n\n // Grant WebSocket management permissions\n const managementPolicy = new iam.PolicyStatement({\n actions: ['execute-api:ManageConnections'],\n resources: [\n `arn:aws:execute-api:${cdk.Stack.of(this).region}:${cdk.Stack.of(this).account}:${this.webSocketApi.apiId}/${this.webSocketStage.stageName}/POST/@connections/*`,\n ],\n });\n\n this.messageHandler.addToRolePolicy(managementPolicy);\n this.streamHandler.addToRolePolicy(managementPolicy);\n\n // Set up WebSocket routes\n this.webSocketApi.addRoute('$connect', {\n integration: new apigatewayv2Integrations.WebSocketLambdaIntegration(\n 'ConnectIntegration',\n this.connectHandler,\n ),\n });\n\n this.webSocketApi.addRoute('$disconnect', {\n integration: new apigatewayv2Integrations.WebSocketLambdaIntegration(\n 'DisconnectIntegration',\n this.disconnectHandler,\n ),\n });\n\n this.webSocketApi.addRoute('$default', {\n integration: new apigatewayv2Integrations.WebSocketLambdaIntegration(\n 'DefaultIntegration',\n this.messageHandler,\n ),\n });\n\n // Set up DynamoDB stream processing for user tables\n for (const table of props.tables) {\n this.setupStreamProcessing(table);\n }\n\n // Output the WebSocket URL\n new cdk.CfnOutput(this, 'WebSocketUrl', {\n value: this.webSocketUrl,\n description: 'WebSocket URL for reactive connections',\n });\n }\n\n private setupStreamProcessing(table: AnyDynamoTable): void {\n const tableArn = `arn:aws:dynamodb:${cdk.Stack.of(this).region}:${cdk.Stack.of(this).account}:table/${table.tableName}`;\n const streamArn = `${tableArn}/stream/*`;\n\n // Stream handler needs stream access\n this.streamHandler.addToRolePolicy(\n new iam.PolicyStatement({\n actions: [\n 'dynamodb:GetRecords',\n 'dynamodb:GetShardIterator',\n 'dynamodb:DescribeStream',\n 'dynamodb:ListStreams',\n ],\n resources: [streamArn],\n }),\n );\n\n // Both handlers need read access to user tables (including PartiQL for queries)\n const tableReadPolicy = new iam.PolicyStatement({\n actions: [\n 'dynamodb:Query',\n 'dynamodb:Scan',\n 'dynamodb:GetItem',\n 'dynamodb:BatchGetItem',\n 'dynamodb:PartiQLSelect',\n ],\n resources: [tableArn, `${tableArn}/index/*`],\n });\n\n this.streamHandler.addToRolePolicy(tableReadPolicy);\n this.messageHandler.addToRolePolicy(tableReadPolicy);\n\n // Message handler also needs write access for mutations\n this.messageHandler.addToRolePolicy(\n new iam.PolicyStatement({\n actions: [\n 'dynamodb:PutItem',\n 'dynamodb:UpdateItem',\n 'dynamodb:DeleteItem',\n 'dynamodb:BatchWriteItem',\n 'dynamodb:PartiQLInsert',\n 'dynamodb:PartiQLUpdate',\n 'dynamodb:PartiQLDelete',\n ],\n resources: [tableArn, `${tableArn}/index/*`],\n }),\n );\n }\n\n public addTable(table: dynamodb.ITable): void {\n if (!table.tableStreamArn) {\n throw new Error(`Table ${table.tableName} does not have streams enabled`);\n }\n\n table.grantStreamRead(this.streamHandler);\n table.grantReadData(this.streamHandler);\n\n new lambda.EventSourceMapping(this, `Stream-${table.tableName}`, {\n target: this.streamHandler,\n eventSourceArn: table.tableStreamArn,\n startingPosition: lambda.StartingPosition.TRIM_HORIZON,\n batchSize: 100,\n maxBatchingWindow: cdk.Duration.seconds(5),\n });\n }\n}\n","import * as cdk from 'aws-cdk-lib';\nimport type * as dynamodb from 'aws-cdk-lib/aws-dynamodb';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport { Construct } from 'constructs';\n\n/**\n * Props for DynamoDBStreamSource\n */\nexport interface DynamoDBStreamSourceProps {\n /**\n * The DynamoDB table to create a stream source for\n */\n table: dynamodb.ITable;\n\n /**\n * The Lambda function to receive stream events\n */\n target: lambda.IFunction;\n\n /**\n * Batch size for stream processing\n * @default 100\n */\n batchSize?: number;\n\n /**\n * Maximum batching window\n * @default Duration.seconds(5)\n */\n maxBatchingWindow?: cdk.Duration;\n\n /**\n * Starting position for reading the stream\n * @default TRIM_HORIZON\n */\n startingPosition?: lambda.StartingPosition;\n\n /**\n * Enable parallel processing with multiple batches\n * @default 1\n */\n parallelizationFactor?: number;\n\n /**\n * Maximum record age to process\n * @default Duration.days(1)\n */\n maxRecordAge?: cdk.Duration;\n\n /**\n * Number of retries on failure\n * @default 3\n */\n retryAttempts?: number;\n\n /**\n * Filter patterns for the event source\n */\n filters?: lambda.FilterCriteria[];\n}\n\n/**\n * Helper construct for setting up DynamoDB stream event sources\n */\nexport class DynamoDBStreamSource extends Construct {\n public readonly eventSourceMapping: lambda.EventSourceMapping;\n\n constructor(scope: Construct, id: string, props: DynamoDBStreamSourceProps) {\n super(scope, id);\n\n const {\n table,\n target,\n batchSize = 100,\n maxBatchingWindow = cdk.Duration.seconds(5),\n startingPosition = lambda.StartingPosition.TRIM_HORIZON,\n parallelizationFactor = 1,\n maxRecordAge = cdk.Duration.days(1),\n retryAttempts = 3,\n filters,\n } = props;\n\n if (!table.tableStreamArn) {\n throw new Error(\n `Table ${table.tableName} does not have DynamoDB Streams enabled. ` +\n 'Enable streams with streamSpecification when creating the table.',\n );\n }\n\n // Grant stream read permissions\n table.grantStreamRead(target);\n\n // Create the event source mapping\n this.eventSourceMapping = new lambda.EventSourceMapping(\n this,\n 'EventSource',\n {\n target,\n eventSourceArn: table.tableStreamArn,\n startingPosition,\n batchSize,\n maxBatchingWindow,\n parallelizationFactor,\n maxRecordAge,\n retryAttempts,\n bisectBatchOnError: true,\n reportBatchItemFailures: true,\n filters,\n },\n );\n }\n}\n\n/**\n * Create a filter criteria for DynamoDB streams\n */\nexport function createStreamFilter(options: {\n /**\n * Filter by event name (INSERT, MODIFY, REMOVE)\n */\n eventName?: ('INSERT' | 'MODIFY' | 'REMOVE')[];\n\n /**\n * Custom filter patterns\n */\n patterns?: Record<string, unknown>[];\n}): lambda.FilterCriteria[] {\n const filters: Record<string, unknown>[] = [];\n\n if (options.eventName) {\n filters.push({\n eventName: options.eventName,\n });\n }\n\n if (options.patterns) {\n filters.push(...options.patterns);\n }\n\n if (filters.length === 0) {\n return [];\n }\n\n return [lambda.FilterCriteria.filter({ filters })];\n}\n"]}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { D as DynamoTable } from './table-
|
|
3
|
-
import { A as AnyDynamoTable, F as FieldRef, a as FilterCondition, Q as QueryMetadata, J as JsonPatch } from './types-
|
|
2
|
+
import { D as DynamoTable } from './table-DjeyVXYp.js';
|
|
3
|
+
import { A as AnyDynamoTable, F as FieldRef, a as FilterCondition, Q as QueryMetadata, J as JsonPatch } from './types-2EfCnE0c.js';
|
|
4
4
|
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
5
5
|
import { DynamoDBStreamEvent, APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
|
6
6
|
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SystemTableNames } from './chunk-
|
|
1
|
+
import { SystemTableNames } from './chunk-L4NOAOXX.js';
|
|
2
2
|
import { DynamoDBClient, ExecuteStatementCommand } from '@aws-sdk/client-dynamodb';
|
|
3
3
|
import { UpdateCommand, DeleteCommand, PutCommand, GetCommand, DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb';
|
|
4
4
|
import { unmarshall } from '@aws-sdk/util-dynamodb';
|
|
@@ -1,33 +1,45 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { I as IndexDefinition, F as FieldRef, D as DynamoTableConfig } from './types-
|
|
2
|
+
import { S as SupportedSchema, I as IndexDefinition, F as FieldRef, D as DynamoTableConfig } from './types-2EfCnE0c.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Creates field references for type-safe query building
|
|
6
6
|
*/
|
|
7
|
-
type FieldRefs<TSchema extends
|
|
7
|
+
type FieldRefs<TSchema extends SupportedSchema> = {
|
|
8
8
|
[K in keyof z.infer<TSchema>]: FieldRef<K & string, z.infer<TSchema>[K]>;
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* DynamoTable - Defines a DynamoDB table with type-safe schema
|
|
12
12
|
*
|
|
13
|
+
* Supports both ZodObject and ZodDiscriminatedUnion schemas for single-table design patterns.
|
|
14
|
+
*
|
|
13
15
|
* @example
|
|
14
16
|
* ```ts
|
|
17
|
+
* // Simple schema
|
|
15
18
|
* const TodoTable = new DynamoTable({
|
|
16
19
|
* tableName: 'prod-todo-table',
|
|
17
20
|
* schema: z.object({
|
|
18
|
-
*
|
|
19
|
-
*
|
|
21
|
+
* PK: z.string(),
|
|
22
|
+
* SK: z.string(),
|
|
20
23
|
* text: z.string(),
|
|
21
24
|
* isDone: z.boolean(),
|
|
22
25
|
* }),
|
|
23
|
-
* pk: '
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
26
|
+
* pk: 'PK',
|
|
27
|
+
* sk: 'SK',
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Discriminated union for single-table design
|
|
31
|
+
* const MultiEntityTable = new DynamoTable({
|
|
32
|
+
* tableName: 'prod-entities',
|
|
33
|
+
* schema: z.discriminatedUnion('entityType', [
|
|
34
|
+
* z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('USER'), name: z.string() }),
|
|
35
|
+
* z.object({ PK: z.string(), SK: z.string(), entityType: z.literal('ITEM'), title: z.string() }),
|
|
36
|
+
* ]),
|
|
37
|
+
* pk: 'PK',
|
|
38
|
+
* sk: 'SK',
|
|
27
39
|
* });
|
|
28
40
|
* ```
|
|
29
41
|
*/
|
|
30
|
-
declare class DynamoTable<TSchema extends
|
|
42
|
+
declare class DynamoTable<TSchema extends SupportedSchema, TPk extends keyof z.infer<TSchema>, TSk extends keyof z.infer<TSchema> | undefined = undefined, TIndexes extends Record<string, IndexDefinition> = Record<string, IndexDefinition>> {
|
|
31
43
|
readonly tableName: string;
|
|
32
44
|
readonly schema: TSchema;
|
|
33
45
|
readonly pk: TPk;
|
|
@@ -8,6 +8,15 @@ interface IndexDefinition {
|
|
|
8
8
|
pk: string;
|
|
9
9
|
sk?: string;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Supported schema types for DynamoTable
|
|
13
|
+
* Accepts both ZodObject and ZodDiscriminatedUnion
|
|
14
|
+
*/
|
|
15
|
+
type SupportedSchema = z.ZodObject<z.ZodRawShape> | z.ZodDiscriminatedUnion<string, z.ZodDiscriminatedUnionOption<string>[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Extract the inferred type from a supported schema
|
|
18
|
+
*/
|
|
19
|
+
type InferSupportedSchema<T extends SupportedSchema> = z.infer<T>;
|
|
11
20
|
/**
|
|
12
21
|
* Base interface for any DynamoTable - used for generic constraints
|
|
13
22
|
* Defines the minimal shape that all DynamoTable instances satisfy
|
|
@@ -31,8 +40,9 @@ interface AnyDynamoTable {
|
|
|
31
40
|
}
|
|
32
41
|
/**
|
|
33
42
|
* Configuration for DynamoTable
|
|
43
|
+
* Supports both ZodObject and ZodDiscriminatedUnion schemas
|
|
34
44
|
*/
|
|
35
|
-
interface DynamoTableConfig<TSchema extends
|
|
45
|
+
interface DynamoTableConfig<TSchema extends SupportedSchema, TPk extends keyof z.infer<TSchema>, TSk extends keyof z.infer<TSchema> | undefined = undefined, TIndexes extends Record<string, IndexDefinition> = Record<string, IndexDefinition>> {
|
|
36
46
|
tableName: string;
|
|
37
47
|
schema: TSchema;
|
|
38
48
|
pk: TPk;
|
|
@@ -138,4 +148,4 @@ interface QueryEntry {
|
|
|
138
148
|
ttl: number;
|
|
139
149
|
}
|
|
140
150
|
|
|
141
|
-
export type { AnyDynamoTable as A, ConnectionEntry as C, DynamoTableConfig as D, FieldRef as F, IndexDefinition as I, JsonPatch as J, QueryMetadata as Q,
|
|
151
|
+
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 };
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../core/src/table.ts","../../core/src/schema.ts"],"names":[],"mappings":"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","file":"chunk-HZ6JHAJJ.js","sourcesContent":["import type { z } from 'zod';\n\nimport type { DynamoTableConfig, FieldRef, IndexDefinition } from './types.js';\n\n/**\n * Creates field references for type-safe query building\n */\ntype FieldRefs<TSchema extends z.ZodObject<z.ZodRawShape>> = {\n [K in keyof z.infer<TSchema>]: FieldRef<K & string, z.infer<TSchema>[K]>;\n};\n\n/**\n * DynamoTable - Defines a DynamoDB table with type-safe schema\n *\n * @example\n * ```ts\n * const TodoTable = new DynamoTable({\n * tableName: 'prod-todo-table',\n * schema: z.object({\n * id: z.string(),\n * taskListId: z.string(),\n * text: z.string(),\n * isDone: z.boolean(),\n * }),\n * pk: 'id',\n * indexes: {\n * byTaskId: { name: 'gsi_by_task_id', pk: 'taskListId' }\n * }\n * });\n * ```\n */\nexport class DynamoTable<\n TSchema extends z.ZodObject<z.ZodRawShape>,\n TPk extends keyof z.infer<TSchema>,\n TSk extends keyof z.infer<TSchema> | undefined = undefined,\n TIndexes extends Record<string, IndexDefinition> = Record<\n string,\n IndexDefinition\n >,\n> {\n public readonly tableName: string;\n public readonly schema: TSchema;\n public readonly pk: TPk;\n public readonly sk: TSk;\n public readonly indexes: TIndexes;\n public readonly field: FieldRefs<TSchema>;\n\n constructor(config: DynamoTableConfig<TSchema, TPk, TSk, TIndexes>) {\n this.tableName = config.tableName;\n this.schema = config.schema;\n this.pk = config.pk;\n this.sk = config.sk as TSk;\n this.indexes = (config.indexes ?? {}) as TIndexes;\n\n // Create field references for query building\n this.field = this.createFieldRefs();\n }\n\n private createFieldRefs(): FieldRefs<TSchema> {\n const shape = this.schema.shape;\n const refs: Record<string, FieldRef<string, unknown>> = {};\n\n for (const key of Object.keys(shape)) {\n refs[key] = {\n fieldName: key,\n _type: undefined as unknown,\n };\n }\n\n return refs as FieldRefs<TSchema>;\n }\n\n /**\n * Validate an item against the schema\n */\n validate(item: unknown): z.infer<TSchema> {\n return this.schema.parse(item);\n }\n\n /**\n * Safely validate an item, returning a result object\n */\n safeParse(item: unknown): z.SafeParseReturnType<unknown, z.infer<TSchema>> {\n return this.schema.safeParse(item);\n }\n\n /**\n * Get the partition key value from an item\n */\n getPk(item: z.infer<TSchema>): z.infer<TSchema>[TPk] {\n return item[this.pk];\n }\n\n /**\n * Get the sort key value from an item (if defined)\n */\n getSk(\n item: z.infer<TSchema>,\n ): TSk extends keyof z.infer<TSchema> ? z.infer<TSchema>[TSk] : undefined {\n if (this.sk === undefined) {\n return undefined as TSk extends keyof z.infer<TSchema>\n ? z.infer<TSchema>[TSk]\n : undefined;\n }\n return item[\n this.sk as keyof z.infer<TSchema>\n ] as TSk extends keyof z.infer<TSchema> ? z.infer<TSchema>[TSk] : undefined;\n }\n\n /**\n * Get the list of field names in the schema\n */\n getFieldNames(): (keyof z.infer<TSchema>)[] {\n return Object.keys(this.schema.shape) as (keyof z.infer<TSchema>)[];\n }\n\n /**\n * Check if a field exists in the schema\n */\n hasField(fieldName: string): fieldName is keyof z.infer<TSchema> & string {\n return fieldName in this.schema.shape;\n }\n}\n\n/**\n * Helper type to extract the shape from a Zod schema\n */\nexport type InferSchema<T> =\n T extends DynamoTable<infer TSchema, any, any, any>\n ? z.infer<TSchema>\n : never;\n\n/**\n * Helper type to extract field names from a table\n */\nexport type TableFields<T> =\n T extends DynamoTable<infer TSchema, any, any, any>\n ? keyof z.infer<TSchema>\n : never;\n\n/**\n * Helper type to get the pk field name\n */\nexport type TablePk<T> =\n T extends DynamoTable<any, infer TPk, any, any> ? TPk : never;\n\n/**\n * Helper type to get the sk field name\n */\nexport type TableSk<T> =\n T extends DynamoTable<any, any, infer TSk, any> ? TSk : never;\n\n/**\n * Helper type to get indexes\n */\nexport type TableIndexes<T> =\n T extends DynamoTable<any, any, any, infer TIndexes> ? TIndexes : never;\n","import { z } from 'zod';\n\nimport { DynamoTable } from './table.js';\nimport type { IndexDefinition } from './types.js';\n\n/**\n * Helper function to define a schema with type inference\n * This provides a cleaner API for defining tables\n *\n * @example\n * ```ts\n * const TodoTable = defineSchema({\n * tableName: 'prod-todo-table',\n * schema: z.object({\n * id: z.string(),\n * taskListId: z.string(),\n * text: z.string(),\n * isDone: z.boolean(),\n * }),\n * pk: 'id',\n * indexes: {\n * byTaskId: { name: 'gsi_by_task_id', pk: 'taskListId' }\n * }\n * });\n * ```\n */\nexport function defineSchema<\n TSchema extends z.ZodObject<z.ZodRawShape>,\n TPk extends keyof z.infer<TSchema> & string,\n TSk extends (keyof z.infer<TSchema> & string) | undefined = undefined,\n TIndexes extends Record<string, IndexDefinition> = Record<\n string,\n IndexDefinition\n >,\n>(config: {\n tableName: string;\n schema: TSchema;\n pk: TPk;\n sk?: TSk;\n indexes?: TIndexes;\n}): DynamoTable<TSchema, TPk, TSk, TIndexes> {\n return new DynamoTable(config);\n}\n\n/**\n * System table schemas for the reactive engine\n */\nexport const SystemSchemas = {\n /**\n * ReactiveConnections - Tracks active WebSocket connections\n */\n connections: z.object({\n connectionId: z.string(),\n context: z.record(z.unknown()).optional(),\n connectedAt: z.number(),\n ttl: z.number(),\n }),\n\n /**\n * ReactiveDependencies - The inverted index for O(1) lookups\n */\n dependencies: z.object({\n pk: z.string(), // Format: \"TableName#FieldName#FieldValue\"\n sk: z.string(), // ConnectionID#SubscriptionID\n connectionId: z.string(),\n subscriptionId: z.string(),\n tableName: z.string(),\n fieldName: z.string(),\n fieldValue: z.string(),\n ttl: z.number(),\n }),\n\n /**\n * ReactiveConnectionQueries - Stores subscription state for diffing\n */\n queries: z.object({\n pk: z.string(), // ConnectionID\n sk: z.string(), // SubscriptionID\n connectionId: z.string(),\n subscriptionId: z.string(),\n queryMetadata: z.object({\n tableName: z.string(),\n indexName: z.string().optional(),\n filterConditions: z.array(z.unknown()),\n sortField: z.string().optional(),\n sortOrder: z.enum(['asc', 'desc']).optional(),\n limit: z.number().optional(),\n }),\n lastResult: z.array(z.unknown()),\n dependencies: z.array(z.string()),\n createdAt: z.number(),\n updatedAt: z.number(),\n ttl: z.number(),\n }),\n};\n\n/**\n * System table names\n */\nexport const SystemTableNames = {\n connections: 'ReactiveConnections',\n dependencies: 'ReactiveDependencies',\n queries: 'ReactiveConnectionQueries',\n} as const;\n"]}
|