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

zirkelc commented May 22, 2023

Copy link
Copy Markdown

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

@Nitinrajyadav

Copy link
Copy Markdown

+1

@JeremyJonas

Copy link
Copy Markdown

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

@severi

severi commented Dec 3, 2024

Copy link
Copy Markdown
Author

+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
Copy Markdown

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

zirkelc commented Dec 14, 2024

Copy link
Copy Markdown

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
Copy Markdown

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