edgedb-zod
is a code generator for Zod schemas from your EdgeDB database schema.
2 types of schemas will be generated:
Create
: All properties excluding link propertiesUpdate
: All properties excluding link and readonly properties
To run the CLI: npx edgedb-zod [options]
or pnpm exec edgedb-zod
Currently the supported options are:
--outputDir
: The output directory relative from youredgedb.toml
--target ts|mts
: If set tomts
will include.js
in import statements
Feature | Status |
---|---|
Scalars | See table |
Ranges | 🔴 |
Arrays, tuples | 🟢 |
Union types | 🔴 |
Abstract objects | 🟢 |
Overloaded properties | 🟢 |
Regex constraints | 🟢 |
Min, max constraints | 🔴 |
Custom validators | 🔴 |
Property annotations | 🔴 |
EdgeDB Type | Supported | Zod Type | Constraints |
---|---|---|---|
std::str |
🟢 | z.string() |
- |
std::bool |
🟢 | z.boolean() |
- |
std::json |
🟢 | z.unknown() |
- |
std::uuid |
🟢 | z.string().uuid() |
- |
std::enum |
🟢 | z.enum() |
- |
std::int16 |
🟢 | z.number().int().min(-32768).max(32768) |
16-bit unsigned integer |
std::int32 |
🟢 | z.number().int().min(-2147483647).max(2147483647) |
32-bit unsigned integer |
std::int64 |
🟢 | z.bigint().min(-9223372036854775808n).max(9223372036854775807n) |
64-bit unsigned integer |
std::bigint |
🟢 | z.bigint() |
- |
std::float32 |
🟢 | z.number().min(-3.40282347e38).max(3.40282347e38) |
32-bit float |
std::float64 |
🟢 | z.number() |
64-bit float |
std::datetime |
🟢 | z.string().datetime({ offset: true }) |
ISO datetime with timezone |
std::duration |
🟢 | z.string().duration() |
ISO duration format |
cal::local_datetime |
🟢 | z.string().datetime({ local: true }) |
Local datetime without timezone |
cal::local_date |
🔴 | - | - |
cal::local_time |
🟢 | z.string().time() |
Local time format |
cal::relative_duration |
🔴 | - | - |
cal::date_duration |
🔴 | - | - |
std::bytes |
🔴 | - | - |
std::sequence |
🔴 | - | - |
Are we missing any? Please open an issue or PR.
Partial output of edgedb-zod/modules/default.ts
:
// #region default::User
export const CreateUserSchema = z.
object({ // default::HasTimestamps
createdAt: z.string().datetime().optional(), // std::datetime
updatedAt: z.string().datetime().optional(), // std::datetime
})
.extend({ // default::User
name: z.string(), // std::str
emailAddress: z.string().regex(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/), // std::str
password: z.string(), // std::str
});
export const UpdateUserSchema = z.
object({ // default::HasTimestamps
updatedAt: z.string().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?)?Z?$/).optional(), // std::datetime
})
.extend({ // default::User
name: z.string(), // std::str
emailAddress: z.string().regex(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/), // std::str
password: z.string(), // std::str
});
// #endregion