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

Strict partial loading #3443

Closed
parisholley opened this issue Sep 1, 2022 · 5 comments
Closed

Strict partial loading #3443

parisholley opened this issue Sep 1, 2022 · 5 comments
Labels
enhancement New feature or request
Milestone

Comments

@parisholley
Copy link
Contributor

Is your feature request related to a problem? Please describe.

const result = await mikro.findOneOrFail(MyEntity, 1, {
  fields: ['field1', 'field2'],
});

When using with mongo, it is possible to "select" certain fields and return them, however the return type ends up being Loaded<Entity, 'field1' | 'field2'> and still allowing the developer to access unselected fields.

Describe the solution you'd like
I'd like to see a new Selected type which would effectively be an Omit to make sure no one is accessing unqueried data.

@parisholley parisholley added the enhancement New feature or request label Sep 1, 2022
@B4nan B4nan added the help wanted Extra attention is needed label Sep 4, 2022
@B4nan
Copy link
Member

B4nan commented Sep 5, 2022

Just a note for anybody who would like to give this a shot - this needs to be about the Loaded type, not about changing the return type. Partial loading can be combined with populate hints, and the hints are even inferred (if you dont provide populate, its inferred from fields).

FYI there was someone few months ago on slack trying to implement this, and ended up with quite breaking solution. We might need to wait for v6 with something like this.

@B4nan
Copy link
Member

B4nan commented Feb 28, 2023

I managed to hack initial PoC for this, and to make the property access fail, we would have to get rid of the intersection with the entity type (type Loaded<T> = T & { ... }) which is needed for assignability. Will spend few more hours with this during the week, maybe I will have some ideas to get around it.

What I can do relatively easily is to type such not-selected properties to never, which won't fail on access, but can at least fail on misusage.

@B4nan
Copy link
Member

B4nan commented Mar 1, 2023

I think I found a way to make this work with actual property omission. It has its own quirks, but generally should work and should be worth it. The only real downside is that the partial loading will need to work the same as populate hints - as a simple array of relation names (with nested dot path support). I think that's a small feature to sacrifice when you compare it to the added strictness of the loaded result.

Still have to crack the nested partial loading support, as well as fix many TS errors in the codebase caused by the changes, but I feel more confident this will land in v6.

edit: last challenge - combination of partial loading and populate hints

edit2: it is happening!

@B4nan B4nan removed the help wanted Extra attention is needed label Mar 1, 2023
@B4nan B4nan added this to the 6.0 milestone Mar 1, 2023
@B4nan B4nan changed the title Selected<Entity> type Strict partial loading Mar 1, 2023
B4nan added a commit that referenced this issue Mar 3, 2023
The `Loaded` type is now improved to support the partial loading hints (`fields` option).
When used, the returned type will only allow accessing selected properties. Primary keys
are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Mar 3, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
@B4nan
Copy link
Member

B4nan commented Mar 3, 2023

Closing as implemented via #4092, let's test this!

@B4nan B4nan closed this as completed Mar 3, 2023
@parisholley
Copy link
Contributor Author

parisholley commented Mar 4, 2023

woot! thanks @B4nan, will test out soon. have another 50/month :)

B4nan added a commit that referenced this issue Mar 19, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Apr 6, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Apr 10, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Apr 12, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Apr 26, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue May 14, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue May 14, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue May 24, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue May 26, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Jun 11, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Sep 10, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Sep 20, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Sep 24, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Sep 30, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Oct 2, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Oct 17, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Oct 21, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Oct 25, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Nov 2, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
B4nan added a commit that referenced this issue Nov 5, 2023
The `Loaded` type is now improved to support the partial loading hints
(`fields` option). When used, the returned type will only allow
accessing selected properties. Primary keys are automatically selected.

```ts
// book is typed to `Selected<Book, 'author', 'title' | 'author.email'>`
const book = await em.findOneOrFail(Book, 1, {
  fields: ['title', 'author.email'],
  populate: ['author'],
});

const id = book.id; // ok, PK is selected automatically
const title = book.title; // ok, title is selected
const publisher = book.publisher; // fail, not selected
const author = book.author.id; // ok, PK is selected automatically
const email = book.author.email; // ok, selected
const name = book.author.name; // fail, not selected
```

BREAKING CHANGE:
`FindOptions.fields` now accepts only array of strings, like `populate`.

Closes #3443
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants