Created
February 24, 2023 19:18
-
-
Save tywalch/6ea6a8146e1d70ae999c2c7068d660f6 to your computer and use it in GitHub Desktop.
ElectroDB + Zod
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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