New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(core): rework serialization rules to always respect populate hint #4203
Conversation
b988874
to
05bc9d4
Compare
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## v6 #4203 +/- ##
==========================================
- Coverage 99.51% 99.49% -0.03%
==========================================
Files 219 219
Lines 14305 14351 +46
Branches 3265 3277 +12
==========================================
+ Hits 14236 14278 +42
- Misses 68 72 +4
Partials 1 1
... and 1 file with indirect coverage changes Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report in Codecov by Sentry. |
05bc9d4
to
14fc933
Compare
14fc933
to
49966d0
Compare
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
mikro-orm#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes mikro-orm#4138 Closes mikro-orm#4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
#4203) Implicit serialization, so calling `toObject()` or `toJSON()` on the entity, as opposed to explicitly using the `serialize()` helper, now works entirely based on `populate` hints. This means that, unless you explicitly marked some entity as populated via `wrap(entity).populated()`, it will be part of the serialized form only if it was part of the `populate` hint: ```ts // let's say both Author and Book entity has a m:1 relation to Publisher entity // we only populate the publisher relation of the Book entity const user = await em.findOneOrFail(Author, 1, { populate: ['books.publisher'], }); const dto = wrap(user).toObject(); console.log(dto.publisher); // only the FK, e.g. `123` console.log(dto.books[0].publisher); // populated, e.g. `{ id: 123, name: '...' }` ``` Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (`fields` option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via `hidden: true` in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO. ```ts const user = await em.findOneOrFail(Author, 1, { fields: ['books.publisher.name'], }); const dto = wrap(user).toObject(); // only the publisher's name will be available, previously there would be also `book.author` // `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }` ``` **This also works for embeddables, including nesting and object mode.** This method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the `populate` option. The method signature still accepts single object or an array of objects, but always returns an array. To serialize single entity, you can use array destructing, or use `wrap(entity).serialize()` which handles a single entity only. ```ts const dtos = serialize([user1, user, ...], { exclude: ['id', 'email'], forceObject: true }); const [dto1] = serialize(user, { exclude: ['id', 'email'], forceObject: true }); const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true }); ``` Closes #4138 Closes #4199
Implicit serialization changes
Implicit serialization, so calling
toObject()
ortoJSON()
on the entity, as opposed to explicitly using theserialize()
helper, now works entirely based onpopulate
hints. This means that, unless you explicitly marked some entity as populated viawrap(entity).populated()
, it will be part of the serialized form only if it was part of thepopulate
hint:Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (
fields
option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it viahidden: true
in the property options. Main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO.This also works for embeddables, including nesting and object mode.
serialize
helper always returns arrayThis method used to return a single object conditionally based on its inputs, but the solution broke intellisense for the
populate
option. The method signature still accepts single object or an array of objects, but always returns an array.To serialize single entity, you can use array destructing, or use
wrap(entity).serialize()
which handles a single entity only.Closes #4138
Closes #4199