Skip to content

Instantly share code, notes, and snippets.

@severi
Last active November 11, 2025 19:07
Show Gist options
  • Select an option

  • Save severi/5d181a3e779f41a5e5fce1b7dcd17a89 to your computer and use it in GitHub Desktop.

Select an option

Save severi/5d181a3e779f41a5e5fce1b7dcd17a89 to your computer and use it in GitHub Desktop.
import { z } from 'zod';
const VehicleSchema = z.object({
id: z.string(),
itemType: z.literal('VEHICLE'),
licencePlateNumber: z.string(),
});
const HouseSchema = z.object({
id: z.string(),
itemType: z.literal('HOUSE'),
address: z.string(),
city: z.string(),
country: z.string(),
});
const ItemModelZod = z.discriminatedUnion('itemType', [VehicleSchema, HouseSchema]);
const ItemEntity = new Entity({
model: {
entity: 'item',
service: 'auth',
version: '01',
},
attributes: {
id: {
type: 'string',
},
itemType: {
type: 'string'
},
/*
also allow any other attributes to be inserted besides these two i.e. in this case
- licencePlateNumber
- address
- city
- country
without having to explicitly define them here
With for example large/complex discriminated unions keeping this up-to-date could be quite cumbersome
and force us to basically list all the possible attributes that an item in the union might have
One interesting option could of course be if these could be automatically created from the zod schema...
*/
},
indexes: {
byItemType: {
pk: {
field: 'pk',
composite: ['itemType']
},
sk: {
field: 'sk',
composite: ['id']
}
}
}
}, { table, client });
const item = ItemModelZod.parse({
id: '123456',
itemType: 'VEHICLE',
licencePlateNumber: 'abcde',
});
await ItemEntity.put(item).go();
@zirkelc
Copy link

zirkelc commented May 22, 2023

I'm looking for exact the same thing: deriving the Electro schema from a Zod schema. Did you find a solution?

@Nitinrajyadav
Copy link

+1

@JeremyJonas
Copy link

+1 anyone have a solution yet? Just starting to explore

@severi
Copy link
Author

severi commented Dec 3, 2024

+1 anyone have a solution yet? Just starting to explore

Unfortunately not, see my answer here tywalch/electrodb#216 (reply in thread)

@peterb154
Copy link

I just did something similar this week. I was googling to see if anyone had a better solution. Here’s what I came up with:

// Define Zod schema first
export const videoSchema = z.object({
  slug: z.string().min(2).max(100),
  bucket: z.string().min(2).max(100),
  objectKey: z.string().min(2).max(100),
  createdAt: z.string(),
  title: z.string().min(5).max(100),
  description: z.string().max(500),
  tags: z.array(z.string()),
  duration: z.number().gt(0),
  thumbnail: z.string(),
  videoUrl: z.string()
});

type ElectroDBAttribute = Attribute;

// Helper function to convert Zod schema to ElectroDB attributes
function zodToElectroDB(schema: z.ZodObject<z.ZodRawShape>) {
  const attributes: Record<string, ElectroDBAttribute> = {};
  
  Object.entries(schema.shape).forEach(([key, value]) => {
    if (value instanceof z.ZodString) {
      attributes[key] = { type: "string" };
    } else if (value instanceof z.ZodNumber) {
      attributes[key] = { type: "number" };
    } else if (value instanceof z.ZodArray) {
      attributes[key] = { 
        type: "list", 
        items: { type: "string" } // array of strings
      };
    }
    // Add more type conversions as needed
  });

  return attributes;
}

// Create ElectroDB entity using the converted schema
export const Video = new Entity(
  {
    model: {
      entity: "Video",
      version: "1",
      service: "videos",
    },
    attributes: zodToElectroDB(videoSchema),
    indexes: {
      byS3Key: {
        pk: { field: "pk", composite: ["bucket"] },
        sk: { field: "sk", composite: ["objectKey"] },
      },
      bySlug: {
        index: "gsi1pk-gsi1sk-index",
        pk: { field: "gsi1pk", composite: ["slug"] },
        sk: { field: "gsi1sk", composite: ["slug"] },
      },
    },
  },
  { client, table }
);

@zirkelc
Copy link

zirkelc commented Dec 14, 2024

I tried something similar awhile ago, but they main issue I have is that you'll loose Entity type-safety when using the get/update/set... methods. I started to work on a type helper to infer the type Entity attribute types from a Zod schema, but got nowhere.

@JeremyJonas
Copy link

In it case helps anyone, here is link to discussion with type inference / assertion solution that has been working quite well tywalch/electrodb#216 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment