Skip to content
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

Merged
merged 1 commit into from Apr 11, 2023

Conversation

B4nan
Copy link
Member

@B4nan B4nan commented Apr 8, 2023

Implicit serialization changes

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:

// 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.

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.

serialize helper always returns array

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.

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

@B4nan B4nan changed the base branch from master to v6 April 8, 2023 08:17
@B4nan B4nan changed the title Serialization rules feat(core): rework serialization rules to always respect populate hint Apr 8, 2023
@B4nan B4nan force-pushed the serialization-rules branch 3 times, most recently from b988874 to 05bc9d4 Compare April 8, 2023 10:13
@codecov
Copy link

codecov bot commented Apr 8, 2023

Codecov Report

Patch coverage: 98.62% and project coverage change: -0.03 ⚠️

Comparison is base (d87545a) 99.51% compared to head (14fc933) 99.49%.

❗ Current head 14fc933 differs from pull request most recent head 49966d0. Consider uploading reports for the commit 49966d0 to get more accurate results

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              
Impacted Files Coverage Δ
packages/core/src/decorators/Entity.ts 100.00% <ø> (ø)
packages/core/src/drivers/IDatabaseDriver.ts 100.00% <ø> (ø)
packages/core/src/entity/EntityHelper.ts 100.00% <ø> (ø)
packages/core/src/entity/EntityRepository.ts 96.36% <ø> (ø)
packages/core/src/typings.ts 100.00% <ø> (ø)
packages/core/src/unit-of-work/UnitOfWork.ts 100.00% <ø> (ø)
packages/core/src/utils/Configuration.ts 99.25% <ø> (ø)
...ges/core/src/serialization/SerializationContext.ts 98.41% <95.23%> (-1.59%) ⬇️
packages/core/src/EntityManager.ts 97.98% <95.45%> (-0.11%) ⬇️
packages/core/src/drivers/DatabaseDriver.ts 99.46% <100.00%> (ø)
... and 10 more

... 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.
📢 Do you have feedback about the report comment? Let us know in this issue.

@B4nan B4nan merged commit 5165c10 into v6 Apr 11, 2023
6 checks passed
@B4nan B4nan deleted the serialization-rules branch April 11, 2023 20:13
B4nan added a commit that referenced this pull request Apr 12, 2023
#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
B4nan added a commit that referenced this pull request Apr 26, 2023
#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
jsprw pushed a commit to jsprw/mikro-orm-full-text-operators that referenced this pull request May 7, 2023
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
B4nan added a commit that referenced this pull request May 14, 2023
#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
B4nan added a commit that referenced this pull request May 14, 2023
#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
B4nan added a commit that referenced this pull request May 24, 2023
#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
B4nan added a commit that referenced this pull request May 26, 2023
#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
B4nan added a commit that referenced this pull request Jun 11, 2023
#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
B4nan added a commit that referenced this pull request Sep 10, 2023
#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
B4nan added a commit that referenced this pull request Sep 20, 2023
#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
B4nan added a commit that referenced this pull request Sep 24, 2023
#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
B4nan added a commit that referenced this pull request Sep 30, 2023
#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
@B4nan B4nan mentioned this pull request Oct 2, 2023
22 tasks
B4nan added a commit that referenced this pull request Oct 2, 2023
#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
B4nan added a commit that referenced this pull request Oct 17, 2023
#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
B4nan added a commit that referenced this pull request Oct 21, 2023
#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
B4nan added a commit that referenced this pull request Oct 25, 2023
#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
B4nan added a commit that referenced this pull request Nov 2, 2023
#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
B4nan added a commit that referenced this pull request Nov 5, 2023
#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant