Skip to content

Instantly share code, notes, and snippets.

@tywalch
Created February 24, 2023 19:18
Show Gist options
  • Save tywalch/6ea6a8146e1d70ae999c2c7068d660f6 to your computer and use it in GitHub Desktop.
Save tywalch/6ea6a8146e1d70ae999c2c7068d660f6 to your computer and use it in GitHub Desktop.
ElectroDB + Zod
import { z } from 'zod';
import { Entity, CustomAttributeType } from 'electrodb';
import { v4 as uuid } from 'uuid';
import { DocumentClient } from "aws-sdk/clients/dynamodb";
const client = new DocumentClient();
const table = 'my_table';
const zUserDetail = z.object({
firstName: z.string().min(1).max(18),
lastName: z.string().min(1).max(18),
phone: z.string().min(10).max(14).optional(),
email: z.string().email(),
url: z.string().url().optional(),
});
type UserDetail = z.infer<typeof zUserDetail>;
const User = new Entity({
model: {
entity: 'user',
service: 'auth',
version: '01',
},
attributes: {
id: {
type: 'string',
default: () => uuid(),
},
accountId: {
type: 'string'
},
detail: {
// use CustomAttributeType if you would like type safety, otherwise use the string 'any' to
// set the attribute's type typescript 'any' and then lean into zod's validation below.
// type: 'any',
type: CustomAttributeType<UserDetail>('any'),
validate: (val: UserDetail) => {
if (!zUserDetail.safeParse(val).success) {
throw new Error('Invalid user detail');
}
},
}
},
indexes: {
byAccount: {
pk: {
field: 'pk',
composite: ['accountId']
},
sk: {
field: 'sk',
composite: ['id']
}
}
}
}, { table, client });
async function main() {
// will successfully perform a dynamodb put operation
await User.put({
accountId: '123456',
detail: {
firstName: 'John',
lastName: 'Doe',
phone: '555-555-5555',
email: 'john.doe@email.com',
url: 'https://example.com',
}
}).go();
// will also successfully perform a dynamodb put operation (commented properties are "optional" per zod)
await User.put({
accountId: '123456',
detail: {
firstName: 'John',
lastName: 'Doe',
// phone: '555-555-5555',
email: 'john.doe@email.com',
// url: 'https://example.com',
}
}).go();
// will cause a typing error because the detail object is not valid typing per the use of `CustomAttributeType`
await User.put({
accountId: '123456',
detail: {
// firstName: 'John',
lastName: 'Doe',
// phone: '555-555-5555',
email: 'john.doe@email.com',
// url: 'https://example.com',
}
}).go();
// even if the typing is set to 'any', zod will still validate the object via the attribute's `validate` function
const detail: any = {
// firstName: 'John',
lastName: 'Doe',
// phone: '555-555-5555',
email: 'john.doe@email.com',
// url: 'https://example.com',
}
await User.put({ accountId: '123456', detail }).go();
}
await User.put({
accountId: '123456',
detail: {
firstName: 'John',
lastName: 'Doe',
phone: '555-555-5555',
email: 'john.doe@email.com',
url: 'https://example.com',
}
}).go();
createUser('123', {
firstName: 'John',
lastName: 'Doe',
phone: '555-555-5555',
email: 'john.doe@email.com',
url: 'https://example.com',
}
console.log(createUser('123', {
firstName: 'John',
lastName: 'Doe',
// phone: '555-555-5555',
email: 'john.doe@email.com',
// url: 'https://example.com'
}));
// @ts-ignore
console.log(createUser('123', {
// firstName: 'John',
lastName: 'Doe',
phone: '555-555-5555',
email: 'john.doe@email.com',
url: 'https://example.com'
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment