tywalch/electrodb

[Feature Request] Required container attributes can have empty values

tobyspark opened this issue · 2 comments

Modelling empty lists and sets by omitting the property is understandable from a storage perspective, but adds overhead to the business logic consuming the objects. As a modelling layer over DynamoDB, ElectroDB could abstract this storage requirement away.

Feature Request – The required property of list and set attributes should allow empty sets and lists, marshalling to and from null behind the scenes.

For context, are you speaking about something like this?

/* Model queries, see results, share with friends */

import { Entity, Service } from "electrodb";

const table = "your_table_name";

/* Tasks Entity */
const listHolder = new Entity(
  {
    model: {
      entity: "listHolder",
      version: "1",
      service: "app"
    },
    attributes: {
      id: {
        type: 'string',
        required: true,
      },
      set: {
        type: 'set',
        items: 'string',
        required: true,
        default: [],
      },
    },
    indexes: {
      main: {
        pk: {
          field: 'pk',
          composite: ['id'],
        }
      }
    }
  },
  { table }
);

async function demonstrateIssue() {
  await listHolder
    .create({ id: 'example', set: [] })
    .go();

  const { data } = await listHolder
    .get({ id: 'example' })
    .go();

  if (!data) return;

  console.log(data.set.length); // TypeError: Cannot read property 'length' of undefined
}

This one got me today.

Our workaround:

  • set convertEmptyValues: true
DynamoDBDocumentClient.from(ddbClient, {
    marshallOptions: {
        convertEmptyValues: true, 
    },
})

Note that convertEmptyValues: true also sets empty strings / blobs to null, so you have to use a get() hook there too.

  • use a get() hook to replace null values:
attributes: {
        set: {
            type: 'set',
            required: true,
            items: ['A', 'B', 'C'] as const,
            get: (val: any, item: any) => val !== null ? val : [],
        },
    },

It's weird that the document client allows empty strings, but doesn't allow empty sets, even though it's possible to add empty sets manually in AWS.