diff --git a/README.md b/README.md index 40319f2..143cb0f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A simple and experimental dynamodb data mapper. ## Features -- Simplified data modeling and mapping to DynamoDB types +- Data modeling and mapping to DynamoDB types - Data validation using [Joi](https://joi.dev/) - [Autogenerating IDs](#Creating) - Complete typescript typings @@ -21,7 +21,6 @@ A simple and experimental dynamodb data mapper. - Paging - Complex querying - Number and binary sets -- Date types - Local indexes ## Installation diff --git a/src/index.test.ts b/src/index.test.ts index 0a01d6c..485dc06 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -261,6 +261,70 @@ describe("omanyd", () => { const savedThing = await ThingStore.create({ list: [] }); expect(savedThing.list).toEqual([]); }); + + it("should save and return date objects", async () => { + interface Thing { + id: string; + date: Date; + } + const ThingStore = Omanyd.define({ + name: "basicDate", + hashKey: "id", + schema: Joi.object({ + id: Omanyd.types.id(), + date: Joi.date(), + }), + }); + + await Omanyd.createTables(); + + const savedThing = await ThingStore.create({ + date: new Date("2023-03-02T11:49:00.000Z"), + }); + const readThing = await ThingStore.getByHashKey(savedThing.id); + expect(savedThing.date).toBeInstanceOf(Date); + expect(savedThing.date).toEqual(new Date("2023-03-02T11:49:00.000Z")); + expect(readThing?.date).toBeInstanceOf(Date); + expect(readThing?.date).toEqual(new Date("2023-03-02T11:49:00.000Z")); + }); + + it("should save and return dates nested within objects", async () => { + interface Thing { + id: string; + a: { + b: { + date: Date; + }; + }; + } + const ThingStore = Omanyd.define({ + name: "nestedDate", + hashKey: "id", + schema: Joi.object({ + id: Omanyd.types.id(), + a: Joi.object({ + b: Joi.object({ + date: Joi.date().required(), + }).required(), + }).required(), + }), + }); + + await Omanyd.createTables(); + + const savedThing = await ThingStore.create({ + a: { + b: { + date: new Date("2023-03-02T11:49:00.000Z"), + }, + }, + }); + const readThing = await ThingStore.getByHashKey(savedThing.id); + expect(savedThing.a.b.date).toBeInstanceOf(Date); + expect(savedThing.a.b.date).toEqual(new Date("2023-03-02T11:49:00.000Z")); + expect(readThing?.a.b.date).toBeInstanceOf(Date); + expect(readThing?.a.b.date).toEqual(new Date("2023-03-02T11:49:00.000Z")); + }); }); describe("range key", () => { diff --git a/src/serializer.ts b/src/serializer.ts index 5ab43d2..3c8641b 100644 --- a/src/serializer.ts +++ b/src/serializer.ts @@ -18,6 +18,10 @@ class Serializer { return { BOOL: value }; } + private date(value: Date): AWSDDB.AttributeValue { + return this.string(value.toISOString()); + } + private object( o: PlainObject, schema: Joi.ObjectSchema @@ -119,6 +123,8 @@ class Serializer { return this.boolean(userValue); } else if (schema.type === "any") { return this.any(userValue); + } else if (schema.type === "date") { + return this.date(userValue); } else { throw new Error(`Unable to handle Joi schema type: "${schema.type}"`); }