@nikovirtala/typesafe-dynamodb 0.0.1 → 0.0.2
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/README.md +46 -9
- package/examples/schema-validated-delete-document.ts +63 -0
- package/examples/schema-validated-get-document.ts +59 -0
- package/examples/schema-validated-put-document.ts +64 -0
- package/examples/schema-validated-query-document.ts +69 -0
- package/examples/schema-validated-scan-document.ts +57 -0
- package/examples/schema-validated-stream-event.ts +60 -0
- package/examples/schema-validated-update-document.ts +75 -0
- package/lib/schema-validated-delete-document-command.d.ts +6 -0
- package/lib/schema-validated-delete-document-command.js +10 -0
- package/lib/schema-validated-document-client.d.ts +35 -0
- package/lib/schema-validated-document-client.js +25 -0
- package/lib/schema-validated-get-document-command.d.ts +6 -0
- package/lib/schema-validated-get-document-command.js +10 -0
- package/lib/schema-validated-put-document-command.d.ts +6 -0
- package/lib/schema-validated-put-document-command.js +10 -0
- package/lib/schema-validated-query-document-command.d.ts +6 -0
- package/lib/schema-validated-query-document-command.js +10 -0
- package/lib/schema-validated-scan-document-command.d.ts +6 -0
- package/lib/schema-validated-scan-document-command.js +10 -0
- package/lib/schema-validated-stream-event.d.ts +4 -0
- package/lib/schema-validated-stream-event.js +30 -0
- package/lib/schema-validated-update-document-command.d.ts +6 -0
- package/lib/schema-validated-update-document-command.js +10 -0
- package/package.json +4 -1
- package/perf/README.md +114 -0
- package/perf/performance-test.ts +563 -0
package/README.md
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
# typesafe-dynamodb
|
|
1
|
+
# @nikovirtala/typesafe-dynamodb
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/js/@nikovirtala%2Ftypesafe-dynamodb)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@nikovirtala/typesafe-dynamodb` is a fork of `typesafe-dynamodb` (a type-only library which replaces the type signatures of the AWS SDK v3's DynamoDB client) with schema validation based on [zod](https://zod.dev).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
It substitutes `getItem`, `putItem`, `deleteItem` and `query` API methods with type-safe and schema validated alternatives that are aware of the data in your tables and also adaptive to the semantics of the API request, e.g. by validating `ExpressionAttributeNames` and `ExpressionAttributeValues` contain all the values used in a `ConditionExpression` string, or by understanding the effect of a `ProjectionExpression` on the returned data type.
|
|
8
|
+
|
|
9
|
+
The end goal is to provide types and validation that have total understanding of the AWS DynamoDB API and enable full utilization of the TypeScript type system for modeling complex DynamoDB Tables, such as the application of union types and template string literals for single-table designs without forgetting runtime safety.
|
|
8
10
|
|
|
9
11
|

|
|
10
12
|
|
|
11
13
|
## Installation
|
|
12
14
|
|
|
13
15
|
```
|
|
14
|
-
npm install --save-dev typesafe-dynamodb
|
|
16
|
+
npm install --save-dev @nikovirtala/typesafe-dynamodb
|
|
15
17
|
```
|
|
16
18
|
|
|
17
19
|
## Usage
|
|
@@ -108,7 +110,7 @@ import { TypeSafeDocumentClientV3 } from "typesafe-dynamodb/lib/document-client-
|
|
|
108
110
|
const client = new DynamoDBClient({});
|
|
109
111
|
|
|
110
112
|
const docClient = DynamoDBDocumentClient.from(
|
|
111
|
-
client
|
|
113
|
+
client,
|
|
112
114
|
) as TypeSafeDocumentClientV3<MyType, "key", "sort">;
|
|
113
115
|
```
|
|
114
116
|
|
|
@@ -134,7 +136,7 @@ Same for the `Item` in the response:
|
|
|
134
136
|
|
|
135
137
|
### Single Table Design
|
|
136
138
|
|
|
137
|
-
Below are two `interface` declarations, representing two types of data stored in a single DynamoDB
|
|
139
|
+
Below are two `interface` declarations, representing two types of data stored in a single DynamoDB Table - `User` and `Order`. Single table design in DynamoDB is achieved by creating "composite keys", e.g. `USER#${UserID}`. In TypeScript, we use template literal types to encode this in the Type System.
|
|
138
140
|
|
|
139
141
|
```ts
|
|
140
142
|
interface User<UserID extends string = string> {
|
|
@@ -149,7 +151,7 @@ interface User<UserID extends string = string> {
|
|
|
149
151
|
|
|
150
152
|
interface Order<
|
|
151
153
|
UserID extends string = string,
|
|
152
|
-
OrderID extends string = string
|
|
154
|
+
OrderID extends string = string,
|
|
153
155
|
> {
|
|
154
156
|
PK: `USER#${UserID}`;
|
|
155
157
|
SK: `ORDER#${OrderID}`;
|
|
@@ -187,6 +189,41 @@ export async function handle(
|
|
|
187
189
|
|
|
188
190
|
The event's type is derived from the data type and the the `StreamViewType`, e.g. `"NEW_IMAGE" | "OLD_IMAGE" | "KEYS_ONLY" | "NEW_AND_OLD_IMAGES"`.
|
|
189
191
|
|
|
192
|
+
### Schema-Validated DynamoDBStreamEvent
|
|
193
|
+
|
|
194
|
+
Validate DynamoDB stream events at runtime using Zod schemas:
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import { z } from "zod";
|
|
198
|
+
import { validateStreamEvent } from "typesafe-dynamodb";
|
|
199
|
+
import type { DynamoDBStreamEvent } from "typesafe-dynamodb/lib/stream-event";
|
|
200
|
+
|
|
201
|
+
const UserSchema = z.object({
|
|
202
|
+
PK: z.string(),
|
|
203
|
+
SK: z.string(),
|
|
204
|
+
name: z.string(),
|
|
205
|
+
email: z.string().email(),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
type User = z.infer<typeof UserSchema>;
|
|
209
|
+
|
|
210
|
+
export async function handle(
|
|
211
|
+
event: DynamoDBStreamEvent<User, "PK", "SK", "NEW_AND_OLD_IMAGES">,
|
|
212
|
+
) {
|
|
213
|
+
try {
|
|
214
|
+
const validatedEvent = validateStreamEvent(event, UserSchema);
|
|
215
|
+
// Process validated stream records
|
|
216
|
+
} catch (error) {
|
|
217
|
+
if (error instanceof z.ZodError) {
|
|
218
|
+
console.error("Schema validation failed:", error.issues);
|
|
219
|
+
}
|
|
220
|
+
throw error;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The `validateStreamEvent` function validates both `NewImage` and `OldImage` data against your Zod schema, ensuring runtime type safety for your stream processing logic.
|
|
226
|
+
|
|
190
227
|
### Filter result with ProjectionExpression
|
|
191
228
|
|
|
192
229
|
The `ProjectionExpression` field is parsed and applied to filter the returned type of `getItem` and `query`.
|
|
@@ -293,4 +330,4 @@ const unmarshalled: {
|
|
|
293
330
|
readonly list: readonly [...];
|
|
294
331
|
readonly record: Unmarshall<...>;
|
|
295
332
|
};
|
|
296
|
-
```
|
|
333
|
+
```
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { SchemaValidatedDocumentClient } from "../src/schema-validated-document-client";
|
|
5
|
+
import { SchemaValidatedDeleteDocumentCommand } from "../src/schema-validated-delete-document-command";
|
|
6
|
+
|
|
7
|
+
const UserSchema = z.object({
|
|
8
|
+
pk: z.templateLiteral(["USER", "#", z.uuid()]),
|
|
9
|
+
sk: z.literal("METADATA"),
|
|
10
|
+
userId: z.string(),
|
|
11
|
+
email: z.string().email(),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
age: z.number().min(0),
|
|
14
|
+
preferences: z.object({
|
|
15
|
+
theme: z.enum(["light", "dark"]),
|
|
16
|
+
notifications: z.boolean(),
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
type User = z.infer<typeof UserSchema>;
|
|
21
|
+
|
|
22
|
+
const client = new DynamoDBClient({ region: "eu-west-1" });
|
|
23
|
+
const documentClient = DynamoDBDocumentClient.from(client);
|
|
24
|
+
const schemaValidatedDocumentClient = new SchemaValidatedDocumentClient(
|
|
25
|
+
documentClient,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const DeleteUserCommand = SchemaValidatedDeleteDocumentCommand<
|
|
29
|
+
User,
|
|
30
|
+
"pk",
|
|
31
|
+
"sk"
|
|
32
|
+
>(UserSchema);
|
|
33
|
+
|
|
34
|
+
async function deleteUserDocumentExample() {
|
|
35
|
+
try {
|
|
36
|
+
const result = await schemaValidatedDocumentClient.send(
|
|
37
|
+
new DeleteUserCommand({
|
|
38
|
+
TableName: "Users",
|
|
39
|
+
Key: {
|
|
40
|
+
pk: "USER#00000000-0000-0000-0000-000000000000",
|
|
41
|
+
sk: "METADATA",
|
|
42
|
+
},
|
|
43
|
+
ConditionExpression: "attribute_exists(pk)",
|
|
44
|
+
ReturnValues: "ALL_OLD",
|
|
45
|
+
}),
|
|
46
|
+
UserSchema,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (result.Attributes) {
|
|
50
|
+
console.log("Deleted user:", result.Attributes);
|
|
51
|
+
return result.Attributes;
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (error instanceof z.ZodError) {
|
|
55
|
+
console.error("Schema validation failed:", error.issues);
|
|
56
|
+
} else {
|
|
57
|
+
console.error("DynamoDB error:", error);
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { deleteUserDocumentExample, UserSchema };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { SchemaValidatedDocumentClient } from "../src/schema-validated-document-client";
|
|
5
|
+
import { SchemaValidatedGetDocumentCommand } from "../src/schema-validated-get-document-command";
|
|
6
|
+
|
|
7
|
+
const UserSchema = z.object({
|
|
8
|
+
pk: z.templateLiteral(["USER", "#", z.uuid()]),
|
|
9
|
+
sk: z.literal("METADATA"),
|
|
10
|
+
userId: z.string(),
|
|
11
|
+
email: z.string().email(),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
age: z.number().min(0),
|
|
14
|
+
preferences: z.object({
|
|
15
|
+
theme: z.enum(["light", "dark"]),
|
|
16
|
+
notifications: z.boolean(),
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
type User = z.infer<typeof UserSchema>;
|
|
21
|
+
|
|
22
|
+
const client = new DynamoDBClient({ region: "eu-west-1" });
|
|
23
|
+
const documentClient = DynamoDBDocumentClient.from(client);
|
|
24
|
+
const schemaValidatedDocumentClient = new SchemaValidatedDocumentClient(
|
|
25
|
+
documentClient,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const GetUserCommand = SchemaValidatedGetDocumentCommand<User, "pk", "sk">(
|
|
29
|
+
UserSchema,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
async function getUserDocumentExample() {
|
|
33
|
+
try {
|
|
34
|
+
const result = await schemaValidatedDocumentClient.send(
|
|
35
|
+
new GetUserCommand({
|
|
36
|
+
TableName: "Users",
|
|
37
|
+
Key: {
|
|
38
|
+
pk: "USER#00000000-0000-0000-0000-000000000000",
|
|
39
|
+
sk: "METADATA",
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
UserSchema,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (result.Item) {
|
|
46
|
+
console.log("Validated user:", result.Item);
|
|
47
|
+
return result.Item;
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error instanceof z.ZodError) {
|
|
51
|
+
console.error("Schema validation failed:", error.issues);
|
|
52
|
+
} else {
|
|
53
|
+
console.error("DynamoDB error:", error);
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { getUserDocumentExample, UserSchema };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { SchemaValidatedDocumentClient } from "../src/schema-validated-document-client";
|
|
5
|
+
import { SchemaValidatedPutDocumentCommand } from "../src/schema-validated-put-document-command";
|
|
6
|
+
|
|
7
|
+
const UserSchema = z.object({
|
|
8
|
+
pk: z.templateLiteral(["USER", "#", z.uuid()]),
|
|
9
|
+
sk: z.literal("METADATA"),
|
|
10
|
+
userId: z.string(),
|
|
11
|
+
email: z.string().email(),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
age: z.number().min(0),
|
|
14
|
+
preferences: z.object({
|
|
15
|
+
theme: z.enum(["light", "dark"]),
|
|
16
|
+
notifications: z.boolean(),
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
type User = z.infer<typeof UserSchema>;
|
|
21
|
+
|
|
22
|
+
const client = new DynamoDBClient({ region: "eu-west-1" });
|
|
23
|
+
const documentClient = DynamoDBDocumentClient.from(client);
|
|
24
|
+
const schemaValidatedDocumentClient = new SchemaValidatedDocumentClient(
|
|
25
|
+
documentClient,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const PutUserCommand = SchemaValidatedPutDocumentCommand<User>(UserSchema);
|
|
29
|
+
|
|
30
|
+
async function putUserDocumentExample() {
|
|
31
|
+
try {
|
|
32
|
+
const result = await schemaValidatedDocumentClient.send(
|
|
33
|
+
new PutUserCommand({
|
|
34
|
+
TableName: "Users",
|
|
35
|
+
Item: {
|
|
36
|
+
pk: "USER#00000000-0000-0000-0000-000000000000",
|
|
37
|
+
sk: "METADATA",
|
|
38
|
+
userId: "user123",
|
|
39
|
+
email: "user@example.com",
|
|
40
|
+
name: "John Doe",
|
|
41
|
+
age: 30,
|
|
42
|
+
preferences: {
|
|
43
|
+
theme: "dark",
|
|
44
|
+
notifications: true,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
ConditionExpression: "attribute_not_exists(pk)",
|
|
48
|
+
}),
|
|
49
|
+
UserSchema,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
console.log("User created successfully:", result);
|
|
53
|
+
return result;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof z.ZodError) {
|
|
56
|
+
console.error("Schema validation failed:", error.issues);
|
|
57
|
+
} else {
|
|
58
|
+
console.error("DynamoDB error:", error);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { putUserDocumentExample, UserSchema };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { SchemaValidatedDocumentClient } from "../src/schema-validated-document-client";
|
|
5
|
+
import { SchemaValidatedQueryDocumentCommand } from "../src/schema-validated-query-document-command";
|
|
6
|
+
|
|
7
|
+
const OrderSchema = z.object({
|
|
8
|
+
pk: z.templateLiteral(["USER", "#", z.uuid()]),
|
|
9
|
+
sk: z.templateLiteral(["ORDER", "#", z.string()]),
|
|
10
|
+
userId: z.string(),
|
|
11
|
+
orderId: z.string(),
|
|
12
|
+
status: z.enum(["PLACED", "SHIPPED", "DELIVERED"]),
|
|
13
|
+
amount: z.number().min(0),
|
|
14
|
+
items: z.array(
|
|
15
|
+
z.object({
|
|
16
|
+
productId: z.string(),
|
|
17
|
+
quantity: z.number().min(1),
|
|
18
|
+
price: z.number().min(0),
|
|
19
|
+
}),
|
|
20
|
+
),
|
|
21
|
+
createdAt: z.string().datetime(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
type Order = z.infer<typeof OrderSchema>;
|
|
25
|
+
|
|
26
|
+
const client = new DynamoDBClient({ region: "eu-west-1" });
|
|
27
|
+
const documentClient = DynamoDBDocumentClient.from(client);
|
|
28
|
+
const schemaValidatedDocumentClient = new SchemaValidatedDocumentClient(
|
|
29
|
+
documentClient,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const QueryOrdersCommand =
|
|
33
|
+
SchemaValidatedQueryDocumentCommand<Order>(OrderSchema);
|
|
34
|
+
|
|
35
|
+
async function queryUserOrdersExample() {
|
|
36
|
+
try {
|
|
37
|
+
const result = await schemaValidatedDocumentClient.send(
|
|
38
|
+
new QueryOrdersCommand({
|
|
39
|
+
TableName: "Orders",
|
|
40
|
+
KeyConditionExpression:
|
|
41
|
+
"pk = :userId AND begins_with(sk, :orderPrefix)",
|
|
42
|
+
FilterExpression: "#status = :status",
|
|
43
|
+
ExpressionAttributeNames: {
|
|
44
|
+
"#status": "status",
|
|
45
|
+
},
|
|
46
|
+
ExpressionAttributeValues: {
|
|
47
|
+
":userId": "USER#00000000-0000-0000-0000-000000000000",
|
|
48
|
+
":orderPrefix": "ORDER#",
|
|
49
|
+
":status": "SHIPPED",
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
OrderSchema,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (result.Items) {
|
|
56
|
+
console.log("Validated orders:", result.Items);
|
|
57
|
+
return result.Items;
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error instanceof z.ZodError) {
|
|
61
|
+
console.error("Schema validation failed:", error.issues);
|
|
62
|
+
} else {
|
|
63
|
+
console.error("DynamoDB error:", error);
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { queryUserOrdersExample, OrderSchema };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { SchemaValidatedDocumentClient } from "../src/schema-validated-document-client";
|
|
5
|
+
import { SchemaValidatedScanDocumentCommand } from "../src/schema-validated-scan-document-command";
|
|
6
|
+
|
|
7
|
+
const UserSchema = z.object({
|
|
8
|
+
pk: z.templateLiteral(["USER", "#", z.uuid()]),
|
|
9
|
+
sk: z.literal("METADATA"),
|
|
10
|
+
userId: z.string(),
|
|
11
|
+
email: z.string().email(),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
age: z.number().min(0),
|
|
14
|
+
preferences: z.object({
|
|
15
|
+
theme: z.enum(["light", "dark"]),
|
|
16
|
+
notifications: z.boolean(),
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
type User = z.infer<typeof UserSchema>;
|
|
21
|
+
|
|
22
|
+
const client = new DynamoDBClient({ region: "eu-west-1" });
|
|
23
|
+
const documentClient = DynamoDBDocumentClient.from(client);
|
|
24
|
+
const schemaValidatedDocumentClient = new SchemaValidatedDocumentClient(
|
|
25
|
+
documentClient,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const ScanUsersCommand = SchemaValidatedScanDocumentCommand<User>(UserSchema);
|
|
29
|
+
|
|
30
|
+
async function scanUsersDocumentExample() {
|
|
31
|
+
try {
|
|
32
|
+
const result = await schemaValidatedDocumentClient.send(
|
|
33
|
+
new ScanUsersCommand({
|
|
34
|
+
TableName: "Users",
|
|
35
|
+
FilterExpression: "age > :minAge",
|
|
36
|
+
ExpressionAttributeValues: {
|
|
37
|
+
":minAge": 18,
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
UserSchema,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (result.Items) {
|
|
44
|
+
console.log("Validated users:", result.Items);
|
|
45
|
+
return result.Items;
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error instanceof z.ZodError) {
|
|
49
|
+
console.error("Schema validation failed:", error.issues);
|
|
50
|
+
} else {
|
|
51
|
+
console.error("DynamoDB error:", error);
|
|
52
|
+
}
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { scanUsersDocumentExample, UserSchema };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { validateStreamEvent } from "../src/schema-validated-stream-event";
|
|
3
|
+
import type { DynamoDBStreamEvent } from "../src/stream-event";
|
|
4
|
+
|
|
5
|
+
const UserSchema = z.object({
|
|
6
|
+
pk: z.templateLiteral(["USER", "#", z.string()]),
|
|
7
|
+
sk: z.literal("PROFILE"),
|
|
8
|
+
userId: z.string(),
|
|
9
|
+
email: z.string().email(),
|
|
10
|
+
name: z.string(),
|
|
11
|
+
age: z.number().min(0),
|
|
12
|
+
preferences: z.object({
|
|
13
|
+
theme: z.enum(["light", "dark"]),
|
|
14
|
+
notifications: z.boolean(),
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
type User = z.infer<typeof UserSchema>;
|
|
19
|
+
|
|
20
|
+
export async function handleUserStreamEvent(
|
|
21
|
+
event: DynamoDBStreamEvent<User, "pk", "sk", "NEW_AND_OLD_IMAGES">,
|
|
22
|
+
) {
|
|
23
|
+
try {
|
|
24
|
+
const validatedEvent = validateStreamEvent(event, UserSchema);
|
|
25
|
+
|
|
26
|
+
for (const record of validatedEvent.Records) {
|
|
27
|
+
console.log(`Processing ${record.eventName} event for ${record.eventID}`);
|
|
28
|
+
|
|
29
|
+
if (record.dynamodb?.NewImage) {
|
|
30
|
+
console.log("New user data validated successfully");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (record.dynamodb?.OldImage) {
|
|
34
|
+
console.log("Old user data validated successfully");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
switch (record.eventName) {
|
|
38
|
+
case "INSERT":
|
|
39
|
+
console.log("User created");
|
|
40
|
+
break;
|
|
41
|
+
case "MODIFY":
|
|
42
|
+
console.log("User updated");
|
|
43
|
+
break;
|
|
44
|
+
case "REMOVE":
|
|
45
|
+
console.log("User deleted");
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error instanceof z.ZodError) {
|
|
51
|
+
console.error("Schema validation failed:", error.issues);
|
|
52
|
+
throw new Error(`Invalid stream data: ${error.message}`);
|
|
53
|
+
} else {
|
|
54
|
+
console.error("Stream processing error:", error);
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { UserSchema };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { SchemaValidatedDocumentClient } from "../src/schema-validated-document-client";
|
|
5
|
+
import { SchemaValidatedUpdateDocumentCommand } from "../src/schema-validated-update-document-command";
|
|
6
|
+
|
|
7
|
+
const UserSchema = z.object({
|
|
8
|
+
pk: z.templateLiteral(["USER", "#", z.uuid()]),
|
|
9
|
+
sk: z.literal("METADATA"),
|
|
10
|
+
userId: z.string(),
|
|
11
|
+
email: z.string().email(),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
age: z.number().min(0),
|
|
14
|
+
preferences: z.object({
|
|
15
|
+
theme: z.enum(["light", "dark"]),
|
|
16
|
+
notifications: z.boolean(),
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
type User = z.infer<typeof UserSchema>;
|
|
21
|
+
|
|
22
|
+
const client = new DynamoDBClient({ region: "eu-west-1" });
|
|
23
|
+
const documentClient = DynamoDBDocumentClient.from(client);
|
|
24
|
+
const schemaValidatedDocumentClient = new SchemaValidatedDocumentClient(
|
|
25
|
+
documentClient,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const UpdateUserCommand = SchemaValidatedUpdateDocumentCommand<
|
|
29
|
+
User,
|
|
30
|
+
"pk",
|
|
31
|
+
"sk"
|
|
32
|
+
>(UserSchema);
|
|
33
|
+
|
|
34
|
+
async function updateUserDocumentExample() {
|
|
35
|
+
try {
|
|
36
|
+
const result = await schemaValidatedDocumentClient.send(
|
|
37
|
+
new UpdateUserCommand({
|
|
38
|
+
TableName: "Users",
|
|
39
|
+
Key: {
|
|
40
|
+
pk: "USER#00000000-0000-0000-0000-000000000000",
|
|
41
|
+
sk: "METADATA",
|
|
42
|
+
},
|
|
43
|
+
UpdateExpression:
|
|
44
|
+
"SET #name = :name, #age = :age, #preferences.#theme = :theme",
|
|
45
|
+
ExpressionAttributeNames: {
|
|
46
|
+
"#name": "name",
|
|
47
|
+
"#age": "age",
|
|
48
|
+
"#preferences": "preferences",
|
|
49
|
+
"#theme": "theme",
|
|
50
|
+
},
|
|
51
|
+
ExpressionAttributeValues: {
|
|
52
|
+
":name": "John Doe",
|
|
53
|
+
":age": 30,
|
|
54
|
+
":theme": "dark",
|
|
55
|
+
},
|
|
56
|
+
ReturnValues: "ALL_NEW",
|
|
57
|
+
}),
|
|
58
|
+
UserSchema,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
if (result.Attributes) {
|
|
62
|
+
console.log("Updated user:", result.Attributes);
|
|
63
|
+
return result.Attributes;
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error instanceof z.ZodError) {
|
|
67
|
+
console.error("Schema validation failed:", error.issues);
|
|
68
|
+
} else {
|
|
69
|
+
console.error("DynamoDB error:", error);
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { updateUserDocumentExample, UserSchema };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { DeleteCommand } from "./delete-item";
|
|
3
|
+
import type { JsonFormat } from "./json-format";
|
|
4
|
+
export declare function SchemaValidatedDeleteDocumentCommand<Item extends object, PartitionKey extends keyof Item, RangeKey extends keyof Item | undefined>(schema: z.ZodSchema<Item>): DeleteCommand<Item, PartitionKey, RangeKey, JsonFormat.Document> & {
|
|
5
|
+
_schema: z.ZodSchema<Item>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SchemaValidatedDeleteDocumentCommand = SchemaValidatedDeleteDocumentCommand;
|
|
4
|
+
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
5
|
+
function SchemaValidatedDeleteDocumentCommand(schema) {
|
|
6
|
+
const Command = lib_dynamodb_1.DeleteCommand;
|
|
7
|
+
Command._schema = schema;
|
|
8
|
+
return Command;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLXZhbGlkYXRlZC1kZWxldGUtZG9jdW1lbnQtY29tbWFuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zY2hlbWEtdmFsaWRhdGVkLWRlbGV0ZS1kb2N1bWVudC1jb21tYW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBS0Esb0ZBWUM7QUFqQkQsd0RBQXdFO0FBS3hFLFNBQWdCLG9DQUFvQyxDQUtsRCxNQUF5QjtJQUl6QixNQUFNLE9BQU8sR0FBRyw0QkFBcUIsQ0FBQztJQUN0QyxPQUFPLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztJQUN6QixPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVsZXRlQ29tbWFuZCBhcyBfRGVsZXRlQ29tbWFuZCB9IGZyb20gXCJAYXdzLXNkay9saWItZHluYW1vZGJcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgdHlwZSB7IERlbGV0ZUNvbW1hbmQgfSBmcm9tIFwiLi9kZWxldGUtaXRlbVwiO1xuaW1wb3J0IHR5cGUgeyBKc29uRm9ybWF0IH0gZnJvbSBcIi4vanNvbi1mb3JtYXRcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIFNjaGVtYVZhbGlkYXRlZERlbGV0ZURvY3VtZW50Q29tbWFuZDxcbiAgSXRlbSBleHRlbmRzIG9iamVjdCxcbiAgUGFydGl0aW9uS2V5IGV4dGVuZHMga2V5b2YgSXRlbSxcbiAgUmFuZ2VLZXkgZXh0ZW5kcyBrZXlvZiBJdGVtIHwgdW5kZWZpbmVkLFxuPihcbiAgc2NoZW1hOiB6LlpvZFNjaGVtYTxJdGVtPixcbik6IERlbGV0ZUNvbW1hbmQ8SXRlbSwgUGFydGl0aW9uS2V5LCBSYW5nZUtleSwgSnNvbkZvcm1hdC5Eb2N1bWVudD4gJiB7XG4gIF9zY2hlbWE6IHouWm9kU2NoZW1hPEl0ZW0+O1xufSB7XG4gIGNvbnN0IENvbW1hbmQgPSBfRGVsZXRlQ29tbWFuZCBhcyBhbnk7XG4gIENvbW1hbmQuX3NjaGVtYSA9IHNjaGVtYTtcbiAgcmV0dXJuIENvbW1hbmQ7XG59XG4iXX0=
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare class SchemaValidatedDocumentClient {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: DynamoDBDocumentClient);
|
|
6
|
+
send<T, Item extends object>(command: T, schema?: z.ZodSchema<Item>): Promise<T extends {
|
|
7
|
+
_brand: "UpdateItemCommand";
|
|
8
|
+
} ? {
|
|
9
|
+
Attributes?: Item;
|
|
10
|
+
$metadata: any;
|
|
11
|
+
} : T extends {
|
|
12
|
+
_brand: "DeleteItemCommand";
|
|
13
|
+
} ? {
|
|
14
|
+
Attributes?: Item;
|
|
15
|
+
$metadata: any;
|
|
16
|
+
} : T extends {
|
|
17
|
+
_brand: "PutItemCommand";
|
|
18
|
+
} ? {
|
|
19
|
+
Attributes?: Item;
|
|
20
|
+
$metadata: any;
|
|
21
|
+
} : T extends {
|
|
22
|
+
_brand: "GetItemCommand";
|
|
23
|
+
} ? {
|
|
24
|
+
Item?: Item;
|
|
25
|
+
$metadata: any;
|
|
26
|
+
} : T extends {
|
|
27
|
+
_brand: "QueryCommand" | "ScanCommand";
|
|
28
|
+
} ? {
|
|
29
|
+
Items?: Item[];
|
|
30
|
+
$metadata: any;
|
|
31
|
+
Count?: number;
|
|
32
|
+
ScannedCount?: number;
|
|
33
|
+
LastEvaluatedKey?: any;
|
|
34
|
+
} : Awaited<ReturnType<DynamoDBDocumentClient["send"]>>>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SchemaValidatedDocumentClient = void 0;
|
|
4
|
+
class SchemaValidatedDocumentClient {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
async send(command, schema) {
|
|
9
|
+
const result = await this.client.send(command);
|
|
10
|
+
if (schema) {
|
|
11
|
+
if ("Item" in result && result.Item) {
|
|
12
|
+
result.Item = schema.parse(result.Item);
|
|
13
|
+
}
|
|
14
|
+
if ("Attributes" in result && result.Attributes) {
|
|
15
|
+
result.Attributes = schema.parse(result.Attributes);
|
|
16
|
+
}
|
|
17
|
+
if ("Items" in result && result.Items) {
|
|
18
|
+
result.Items = result.Items.map((item) => schema.parse(item));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.SchemaValidatedDocumentClient = SchemaValidatedDocumentClient;
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLXZhbGlkYXRlZC1kb2N1bWVudC1jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvc2NoZW1hLXZhbGlkYXRlZC1kb2N1bWVudC1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBR0EsTUFBYSw2QkFBNkI7SUFDeEMsWUFBb0IsTUFBOEI7UUFBOUIsV0FBTSxHQUFOLE1BQU0sQ0FBd0I7SUFBRyxDQUFDO0lBRXRELEtBQUssQ0FBQyxJQUFJLENBQ1IsT0FBVSxFQUNWLE1BQTBCO1FBb0IxQixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQWMsQ0FBQyxDQUFDO1FBRXRELElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxJQUFJLE1BQU0sSUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNuQyxNQUFjLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ25ELENBQUM7WUFFRCxJQUFJLFlBQVksSUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUMvQyxNQUFjLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQy9ELENBQUM7WUFFRCxJQUFJLE9BQU8sSUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNyQyxNQUFjLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBUyxFQUFFLEVBQUUsQ0FDckQsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FDbkIsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxNQUFhLENBQUM7SUFDdkIsQ0FBQztDQUNGO0FBN0NELHNFQTZDQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IER5bmFtb0RCRG9jdW1lbnRDbGllbnQgfSBmcm9tIFwiQGF3cy1zZGsvbGliLWR5bmFtb2RiXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuXG5leHBvcnQgY2xhc3MgU2NoZW1hVmFsaWRhdGVkRG9jdW1lbnRDbGllbnQge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNsaWVudDogRHluYW1vREJEb2N1bWVudENsaWVudCkge31cblxuICBhc3luYyBzZW5kPFQsIEl0ZW0gZXh0ZW5kcyBvYmplY3Q+KFxuICAgIGNvbW1hbmQ6IFQsXG4gICAgc2NoZW1hPzogei5ab2RTY2hlbWE8SXRlbT4sXG4gICk6IFByb21pc2U8XG4gICAgVCBleHRlbmRzIHsgX2JyYW5kOiBcIlVwZGF0ZUl0ZW1Db21tYW5kXCIgfVxuICAgICAgPyB7IEF0dHJpYnV0ZXM/OiBJdGVtOyAkbWV0YWRhdGE6IGFueSB9XG4gICAgICA6IFQgZXh0ZW5kcyB7IF9icmFuZDogXCJEZWxldGVJdGVtQ29tbWFuZFwiIH1cbiAgICAgICAgPyB7IEF0dHJpYnV0ZXM/OiBJdGVtOyAkbWV0YWRhdGE6IGFueSB9XG4gICAgICAgIDogVCBleHRlbmRzIHsgX2JyYW5kOiBcIlB1dEl0ZW1Db21tYW5kXCIgfVxuICAgICAgICAgID8geyBBdHRyaWJ1dGVzPzogSXRlbTsgJG1ldGFkYXRhOiBhbnkgfVxuICAgICAgICAgIDogVCBleHRlbmRzIHsgX2JyYW5kOiBcIkdldEl0ZW1Db21tYW5kXCIgfVxuICAgICAgICAgICAgPyB7IEl0ZW0/OiBJdGVtOyAkbWV0YWRhdGE6IGFueSB9XG4gICAgICAgICAgICA6IFQgZXh0ZW5kcyB7IF9icmFuZDogXCJRdWVyeUNvbW1hbmRcIiB8IFwiU2NhbkNvbW1hbmRcIiB9XG4gICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgSXRlbXM/OiBJdGVtW107XG4gICAgICAgICAgICAgICAgICAkbWV0YWRhdGE6IGFueTtcbiAgICAgICAgICAgICAgICAgIENvdW50PzogbnVtYmVyO1xuICAgICAgICAgICAgICAgICAgU2Nhbm5lZENvdW50PzogbnVtYmVyO1xuICAgICAgICAgICAgICAgICAgTGFzdEV2YWx1YXRlZEtleT86IGFueTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDogQXdhaXRlZDxSZXR1cm5UeXBlPER5bmFtb0RCRG9jdW1lbnRDbGllbnRbXCJzZW5kXCJdPj5cbiAgPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5jbGllbnQuc2VuZChjb21tYW5kIGFzIGFueSk7XG5cbiAgICBpZiAoc2NoZW1hKSB7XG4gICAgICBpZiAoXCJJdGVtXCIgaW4gcmVzdWx0ICYmIHJlc3VsdC5JdGVtKSB7XG4gICAgICAgIChyZXN1bHQgYXMgYW55KS5JdGVtID0gc2NoZW1hLnBhcnNlKHJlc3VsdC5JdGVtKTtcbiAgICAgIH1cblxuICAgICAgaWYgKFwiQXR0cmlidXRlc1wiIGluIHJlc3VsdCAmJiByZXN1bHQuQXR0cmlidXRlcykge1xuICAgICAgICAocmVzdWx0IGFzIGFueSkuQXR0cmlidXRlcyA9IHNjaGVtYS5wYXJzZShyZXN1bHQuQXR0cmlidXRlcyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChcIkl0ZW1zXCIgaW4gcmVzdWx0ICYmIHJlc3VsdC5JdGVtcykge1xuICAgICAgICAocmVzdWx0IGFzIGFueSkuSXRlbXMgPSByZXN1bHQuSXRlbXMubWFwKChpdGVtOiBhbnkpID0+XG4gICAgICAgICAgc2NoZW1hLnBhcnNlKGl0ZW0pLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQgYXMgYW55O1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { GetCommand } from "./get-command";
|
|
3
|
+
import type { JsonFormat } from "./json-format";
|
|
4
|
+
export declare function SchemaValidatedGetDocumentCommand<Item extends object, PartitionKey extends keyof Item, RangeKey extends keyof Item | undefined>(schema: z.ZodSchema<Item>): GetCommand<Item, PartitionKey, RangeKey, JsonFormat.Document> & {
|
|
5
|
+
_schema: z.ZodSchema<Item>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SchemaValidatedGetDocumentCommand = SchemaValidatedGetDocumentCommand;
|
|
4
|
+
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
5
|
+
function SchemaValidatedGetDocumentCommand(schema) {
|
|
6
|
+
const Command = lib_dynamodb_1.GetCommand;
|
|
7
|
+
Command._schema = schema;
|
|
8
|
+
return Command;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLXZhbGlkYXRlZC1nZXQtZG9jdW1lbnQtY29tbWFuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zY2hlbWEtdmFsaWRhdGVkLWdldC1kb2N1bWVudC1jb21tYW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBS0EsOEVBWUM7QUFqQkQsd0RBQWtFO0FBS2xFLFNBQWdCLGlDQUFpQyxDQUsvQyxNQUF5QjtJQUl6QixNQUFNLE9BQU8sR0FBRyx5QkFBa0IsQ0FBQztJQUNuQyxPQUFPLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztJQUN6QixPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR2V0Q29tbWFuZCBhcyBfR2V0Q29tbWFuZCB9IGZyb20gXCJAYXdzLXNkay9saWItZHluYW1vZGJcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgdHlwZSB7IEdldENvbW1hbmQgfSBmcm9tIFwiLi9nZXQtY29tbWFuZFwiO1xuaW1wb3J0IHR5cGUgeyBKc29uRm9ybWF0IH0gZnJvbSBcIi4vanNvbi1mb3JtYXRcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIFNjaGVtYVZhbGlkYXRlZEdldERvY3VtZW50Q29tbWFuZDxcbiAgSXRlbSBleHRlbmRzIG9iamVjdCxcbiAgUGFydGl0aW9uS2V5IGV4dGVuZHMga2V5b2YgSXRlbSxcbiAgUmFuZ2VLZXkgZXh0ZW5kcyBrZXlvZiBJdGVtIHwgdW5kZWZpbmVkLFxuPihcbiAgc2NoZW1hOiB6LlpvZFNjaGVtYTxJdGVtPixcbik6IEdldENvbW1hbmQ8SXRlbSwgUGFydGl0aW9uS2V5LCBSYW5nZUtleSwgSnNvbkZvcm1hdC5Eb2N1bWVudD4gJiB7XG4gIF9zY2hlbWE6IHouWm9kU2NoZW1hPEl0ZW0+O1xufSB7XG4gIGNvbnN0IENvbW1hbmQgPSBfR2V0Q29tbWFuZCBhcyBhbnk7XG4gIENvbW1hbmQuX3NjaGVtYSA9IHNjaGVtYTtcbiAgcmV0dXJuIENvbW1hbmQ7XG59XG4iXX0=
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { JsonFormat } from "./json-format";
|
|
3
|
+
import type { PutCommand } from "./put-item";
|
|
4
|
+
export declare function SchemaValidatedPutDocumentCommand<Item extends object>(schema: z.ZodSchema<Item>): PutCommand<Item, JsonFormat.Document> & {
|
|
5
|
+
_schema: z.ZodSchema<Item>;
|
|
6
|
+
};
|