tywalch / electrodb

A DynamoDB library to ease the use of modeling complex hierarchical relationships and implementing a Single Table Design while keeping your query code readable.
MIT License
956 stars 58 forks source link

How to create a map attribute with unknown keys? #348

Closed ides15 closed 5 months ago

ides15 commented 5 months ago

I'd like to make an entity that looks like

const Person = new Entity(
  {
    model: {
      entity: "person",
      version: "1",
      service: "person",
    },
    attributes: {
      name: {
        type: "string",
        required: true,
      },
      interestsScore: {
        type: "map",
      },
    },
  },
)

where the interestsScore could basically be a TypeScript Record type, where the keys are unknown:

await Person.create({
  name: "John",
  interestsScore: {
    skiing: 8,
    music: 5,
    running: 2
  }
})

await Person.create({
  name: "Alex",
  interestsScore: {
    hiking: 9,
    sleeping: 10
  }
})

Any attribute with type map requires the properties key to be set, but I don't know the values of each property beforehand. If I set properties: {}, the interestsScore field doesn't get type safety - I can set interestsScore to a string, boolean, number, etc.

How can I create this attribute? Bonus points if I can create a map attribute that has string keys, and each value is also a map containing specific properties:

await Person.create({
  name: "Alex",
  interestsScore: {
    hiking: {
      score: 9,
      addedOn: "2024-02-04T12:00:00.000",
    },
    sleeping: {
      score: 10,
      addedOn: "2024-02-04T13:00:00.000",
    }
  }
})

Sorry in advance if this is already mentioned in the docs, I must've missed it. Thanks!

ides15 commented 5 months ago

Looks like I can actually use the CustomAttributeType to do what I want here:

const Person = new Entity(
  {
    model: {
      entity: "person",
      version: "1",
      service: "person",
    },
    attributes: {
      name: {
        type: "string",
        required: true,
      },
      interestsScore: {
        type: CustomAttributeType<Record<string, string>>("any"),
      },
    },
  },
)
tywalch commented 5 months ago

Hi @ides15 👋

This is exactly what I was hoping you'd find! Glad you found the answer, let me know if you have any further questions!