Skip to content

Commit

Permalink
docs: improve advanced section + add note about Opt type
Browse files Browse the repository at this point in the history
  • Loading branch information
B4nan committed Nov 9, 2023
1 parent 26681a9 commit ba6d83b
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 7 deletions.
18 changes: 18 additions & 0 deletions docs/docs/guide/02-relationships.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,24 @@ Article {
}
```

#### Alternative approach with `Opt` type

Another way to make TypeScript aware of what properties are optional is the `Opt` type, you can intersect it with the actual property type. This way the above problem with extending classes is no longer present, as we operate on property level:

```ts title='article.entity.ts'
export class Article extends BaseEntity {

@Property({ unique: true })
slug: string & Opt;

@Property({ length: 1000 })
description: Opt<string>; // can be used via generics too

// ...

}
```

## Populating relationships

What if we want to fetch the `Article` together with the `author` relation? We can use `populate` hints for that:
Expand Down
18 changes: 18 additions & 0 deletions docs/docs/guide/04-advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,20 @@ export function verifyArticlePermissions(user: User, article: Article): void {
}
```

### Upserting entities

Alternatively, we could use `em.upsert()` instead to create or update the entity in one step. It will use `INSERT ON CONFLICT` query under the hood:

```diff
-const article = await db.article.findOneOrFail(+params.id);
-verifyArticlePermissions(user, article);
-wrap(article).assign(request.body as Article);
-await db.em.flush();
+const article = await db.article.upsert(request.body as Article);
```

To upsert many entities in a batch, you can use `em.upsertMany()`, which will handle everything within a single query.

### Removing entities

There are several approaches to removing an entity. In this case, we first load the entity, if it does not exist, we return `notFount: true` in the response, if it does, we remove it via `em.remove()`, which marks the entity for removal on the following `flush()` call.
Expand Down Expand Up @@ -1064,6 +1078,8 @@ MikroORM has a simple [result caching](../caching.md) mechanism, all you need to
- A number for explicit expiration (in milliseconds).
- A tuple with first element being the `cacheKey` (`string`) and the second element the expiration (`number`). You can use the cacheKey to clear the cache via `em.clearCache()`.

Let's enable the caching for our article listing endpoint, with a 5-second expiration:

```ts title='modules/article/routes.ts'
// list articles
app.get('/', async request => {
Expand All @@ -1079,6 +1095,8 @@ app.get('/', async request => {
});
```

Now when you enable [debug mode](../logging.md) and try to access the endpoint several times within 5 seconds, you should see just the first request producing queries.

## ⛳ Checkpoint 4

Our app is shaping quite well, we now have all the endpoints implemented and covered with basic tests.
Expand Down
14 changes: 7 additions & 7 deletions docs/docs/guide/xx-todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ draft: true
- [x] virtual entities - article listing, using QB, also mention findAndCount
- [x] embeddables on user profile (social links)
- [x] mention QB getResult, execute and awaiting the QB directly
- [x] mention em.upsert()
- [ ] soft delete via `onFlush` event - show on comments
- [ ] em.upsert()

## Things to showcase

Expand All @@ -42,20 +42,20 @@ draft: true
- [x] mention persisting via EM, and that its equivalent via repos, and that they are not entity bound, It's all the same EM
- [x] general CRUD with entities
- [x] batch CRUD
- [ ] test `Rel<T>` type with ESM and reflect-metadata, use code tabs for both? the ts-morph setup would be optional with a "skip" link at the top
- [x] serialization
- [x] explain constructor usage invariant
- [ ] orphan removal
- [ ] add note about existing database and entity generator
- [x] virtual `User.token` property
- [x] get endpoint, 404 via config, note about local override
- [ ] cascading and propagation
- [ ] default values
- [x] repositories with custom methods, maybe note about base entity repo
- [x] using QB
- [x] em.create() and that it's required for using interface only entities
- [x] using virtual entities
- [ ] find a way to have the reflection package as dev dependency without much hustle, or at least add a bonus section about this and deployment/docker
- [ ] test `Rel<T>` type with ESM and reflect-metadata, use code tabs for both? the ts-morph setup would be optional with a "skip" link at the top
- [ ] orphan removal
- [ ] add note about existing database and entity generator
- [ ] cascading and propagation
- [ ] default values
- [ ] GeneratedCacheAdapter
- [ ] example how to go about scripts (forking or allowing global context) and CRON jobs (request context decorator or explicit helper usage)

TODO:
Expand Down

0 comments on commit ba6d83b

Please sign in to comment.