From a94422602533931fc2a30e621c57139b3ac6e5b2 Mon Sep 17 00:00:00 2001 From: Harminder Virk Date: Tue, 10 Sep 2024 15:58:42 +0530 Subject: [PATCH] fix: JSON stringify DML json property default value (#9074) --- .../src/dml/__tests__/entity-builder.spec.ts | 103 ++++++++++++++++++ .../src/dml/__tests__/json-property.spec.ts | 20 +++- .../helpers/entity-builder/define-property.ts | 21 ++++ 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts index cff7055028..85dc14f078 100644 --- a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts +++ b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts @@ -1344,6 +1344,109 @@ describe("Entity builder", () => { }, }) }) + + test("define JSON property with default value", () => { + const user = model.define("user", { + id: model.number(), + email: model.text(), + phones: model.json().default({ number: "22222222" }), + }) + + expect(user.name).toEqual("user") + expect(user.parse().tableName).toEqual("user") + + const User = toMikroORMEntity(user) + expectTypeOf(new User()).toMatchTypeOf<{ + id: number + email: string + phones: Record + created_at: Date + updated_at: Date + deleted_at: Date | null + }>() + + const metaData = MetadataStorage.getMetadataFromDecorator(User) + expect(metaData.className).toEqual("User") + expect(metaData.path).toEqual("User") + + expect(metaData.filters).toEqual({ + softDeletable: { + name: "softDeletable", + cond: expect.any(Function), + default: true, + args: false, + }, + }) + + expect(metaData.properties).toEqual({ + id: { + reference: "scalar", + type: "number", + columnType: "integer", + name: "id", + fieldName: "id", + nullable: false, + getter: false, + setter: false, + }, + email: { + reference: "scalar", + type: "string", + columnType: "text", + name: "email", + fieldName: "email", + nullable: false, + getter: false, + setter: false, + }, + created_at: { + reference: "scalar", + type: "date", + columnType: "timestamptz", + name: "created_at", + fieldName: "created_at", + defaultRaw: "now()", + onCreate: expect.any(Function), + nullable: false, + getter: false, + setter: false, + }, + phones: { + getter: false, + name: "phones", + fieldName: "phones", + nullable: false, + reference: "scalar", + default: JSON.stringify({ number: "22222222" }), + setter: false, + columnType: "jsonb", + type: "any", + }, + updated_at: { + reference: "scalar", + type: "date", + columnType: "timestamptz", + name: "updated_at", + fieldName: "updated_at", + defaultRaw: "now()", + onCreate: expect.any(Function), + onUpdate: expect.any(Function), + nullable: false, + getter: false, + setter: false, + }, + deleted_at: { + reference: "scalar", + type: "date", + columnType: "timestamptz", + name: "deleted_at", + fieldName: "deleted_at", + nullable: true, + getter: false, + setter: false, + }, + }) + }) }) describe("Entity builder | id", () => { diff --git a/packages/core/utils/src/dml/__tests__/json-property.spec.ts b/packages/core/utils/src/dml/__tests__/json-property.spec.ts index 2a1d0d087e..887c615276 100644 --- a/packages/core/utils/src/dml/__tests__/json-property.spec.ts +++ b/packages/core/utils/src/dml/__tests__/json-property.spec.ts @@ -5,7 +5,7 @@ describe("JSON property", () => { test("create json property type", () => { const property = new JSONProperty() - expectTypeOf(property["$dataType"]).toEqualTypeOf() + expectTypeOf(property["$dataType"]).toEqualTypeOf>() expect(property.parse("coordinates")).toEqual({ fieldName: "coordinates", dataType: { @@ -16,4 +16,22 @@ describe("JSON property", () => { relationships: [], }) }) + + test("create json property with default value", () => { + const property = new JSONProperty().default({ a: 1 }) + + expectTypeOf(property["$dataType"]).toEqualTypeOf>() + expect(property.parse("coordinates")).toEqual({ + fieldName: "coordinates", + dataType: { + name: "json", + }, + defaultValue: { + a: 1, + }, + nullable: false, + indexes: [], + relationships: [], + }) + }) }) diff --git a/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts b/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts index e1537136d5..13fd90d7c0 100644 --- a/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts +++ b/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts @@ -214,6 +214,27 @@ export function defineProperty( return } + /** + * Handling JSON property separately to stringify its default value + */ + if (field.dataType.name === "json") { + Property({ + columnType: "jsonb", + type: "any", + nullable: field.nullable, + fieldName: field.fieldName, + /** + * MikroORM does not ignore undefined values for default when generating + * the database schema SQL. Conditionally add it here to prevent undefined + * from being set as default value in SQL. + */ + ...(isDefined(field.defaultValue) && { + default: JSON.stringify(field.defaultValue), + }), + })(MikroORMEntity.prototype, field.fieldName) + return + } + /** * Define rest of properties */