Compare commits

...

215 Commits

Author SHA1 Message Date
forehalo
bffc294620 fix(core): oauth popup blocked in safari (#8144)
fix(core): oauth popup blocked in safari

fix(core): standarize auth routes

fix AF-1352
2024-09-06 08:26:27 +00:00
forehalo
be4df0f8ac fix(server): created user in update table should not have defualt value (#8134) 2024-09-06 06:42:04 +00:00
forehalo
64d2b926a2 fix(server): remove default auth redirect url (#8140) 2024-09-06 06:26:59 +00:00
JimmFly
a027cef457 fix(core): some fonts are unavailable (#8139)
close AF-1349 AF-1347
2024-09-06 05:08:12 +00:00
fundon
7d93fae1dd fix(core): inlineEditor on rich-text may be null (#8131)
See 3d3d9d7862/packages/affine/components/src/rich-text/rich-text.ts (L348-L350)
https://github.com/toeverything/blocksuite/blob/master/packages/affine/components/src/rich-text/rich-text.ts#L36
2024-09-06 03:50:05 +00:00
EYHN
702c03539f fix(core): fix member list fallback size (#8133) 2024-09-06 02:38:30 +00:00
EYHN
52cd6102cb fix: fix download fonts script (#8125) 2024-09-06 00:37:57 +08:00
EYHN
74cd175d37 feat(core): invoice service (#8124) 2024-09-05 23:56:58 +08:00
akumatus
9cbe416c2c feat(core): shape editor settings (#8122)
<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/cdf4f95c-15b4-4eac-be57-26974f9ca02b.mov">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/cdf4f95c-15b4-4eac-be57-26974f9ca02b.mov">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/cdf4f95c-15b4-4eac-be57-26974f9ca02b.mov">录屏2024-09-05 21.20.31.mov</video>
2024-09-05 15:24:37 +00:00
EYHN
f4db4058f8 feat(core): make permission and invoice offline available (#8123) 2024-09-05 15:11:27 +00:00
JimmFly
8be67dce82 fix(core): remove joined workspace icon from current worksapce card (#8117)
close PD-1669
2024-09-05 14:58:29 +00:00
fundon
017e89f458 fix(core): should be bound to the correct object (#8121)
<img width="795" alt="Screenshot 2024-09-05 at 18 05 35" src="https://github.com/user-attachments/assets/46f277e9-9be6-4f71-b765-fc442a3a9c64">
2024-09-05 14:46:04 +00:00
pengx17
d3f50a2e38 feat(core): expose skip login button to web (#8115)
![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/634cce16-bba2-480f-9126-94b22a782a9a.png)

Allow user skip login page on client
2024-09-05 14:33:22 +00:00
JimmFly
d0010a1d11 chore: add i18n support for ai confirm modal (#8116) 2024-09-05 14:20:40 +00:00
JimmFly
10fe79a9a8 chore: remove deprecated admin panel (#8120) 2024-09-05 14:07:34 +00:00
akumatus
4bbb94c32d feat(core): bump blocksuite (#8114) 2024-09-05 13:54:56 +00:00
JimmFly
5083fe3cfd feat(core): update i18n resources (#8119) 2024-09-05 12:37:06 +00:00
fundon
de1a51bf7c fix(core): should open a new tab with parameters (#8118)
Closes [AF-1343](https://linear.app/affine-design/issue/AF-1343/点击-center-peek-右侧的按钮时,应该携带参数)
2024-09-05 10:30:39 +00:00
pengx17
7621758c76 fix(electron): tune offline mode filter (#8113) 2024-09-05 10:08:56 +00:00
pengx17
f7816a5b28 chore(electron): downgrade electron to v31 (#8111) 2024-09-05 09:49:35 +00:00
JimmFly
5c67f98e90 fix(admin): nav bar incorrectly active state (#7870) 2024-09-05 09:35:22 +00:00
pengx17
d5ecf503c2 fix(mobile): journal button should not show for edgeless (#8110) 2024-09-05 09:16:26 +00:00
pengx17
2a2a969394 feat(mobile): add share button (#8109) 2024-09-05 09:16:25 +00:00
EYHN
691bfed185 feat(core): selector for editorSetting hooks (#8108) 2024-09-05 08:44:11 +00:00
JimmFly
3837c84791 feat(core): temporarily add page mode editor settings to appearance settings (#8090)
Will remove it when editor settings is released.

![CleanShot 2024-09-04 at 18 19 29@2x](https://github.com/user-attachments/assets/2b2b75ff-acbf-4ca9-ae60-292e73663e13)
2024-09-05 08:30:01 +00:00
fundon
059030fbeb fix(core): link generation for selected blocks (#8087)
Closes [BS-1321](https://linear.app/affine-design/issue/BS-1321/copy-link-to-selected-block)

https://github.com/user-attachments/assets/6102fc7f-9551-4dd4-83b1-758dd0a946f0
2024-09-05 07:47:40 +00:00
akumatus
19a7d1eb92 feat(core): observe editor settings change and update edgeless editor (#8105)
<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/cfdd0578-274c-42e3-9ef5-5528e8b25306.mov">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/cfdd0578-274c-42e3-9ef5-5528e8b25306.mov">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/cfdd0578-274c-42e3-9ef5-5528e8b25306.mov">录屏2024-09-05 14.32.41.mov</video>
2024-09-05 07:30:20 +00:00
JimmFly
f452414952 fix(core): hide the footer that blocks the toolbar in shared page (#8091)
close PD-1405 CLOUD-64

https://github.com/user-attachments/assets/f6ed2dfc-d238-41d8-abaf-684193a080ff
2024-09-05 07:14:23 +00:00
CatsJuice
03c2051926 feat(component): startScopedViewTranstion func to support scoped view transition (#8093)
AF-1293
2024-09-05 06:45:29 +00:00
CatsJuice
73dd1d3326 fix(mobile): fixed all docs header, remove doc card tags layout strategy (#8104)
close AF-1326
2024-09-05 06:29:18 +00:00
renovate
24acce2eac chore: bump up @blocksuite/icons version to v2.1.67 (#8006)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@blocksuite/icons](https://redirect.github.com/toeverything/icons) | [`2.1.66` -> `2.1.67`](https://renovatebot.com/diffs/npm/@blocksuite%2ficons/2.1.66/2.1.67) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@blocksuite%2ficons/2.1.67?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@blocksuite%2ficons/2.1.67?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@blocksuite%2ficons/2.1.66/2.1.67?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@blocksuite%2ficons/2.1.66/2.1.67?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>toeverything/icons (@&#8203;blocksuite/icons)</summary>

### [`v2.1.67`](8842286f0a...4bdeb1d0ae)

[Compare Source](8842286f0a...4bdeb1d0ae)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41Ni4wIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-05 05:41:33 +00:00
Yifeng Wang
b711b087c5 docs: add electron build troubleshooting (#8102) 2024-09-05 13:39:01 +08:00
renovate
23748c83a1 chore: bump up @faker-js/faker version to v9 (#8097)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@faker-js/faker](https://redirect.github.com/faker-js/faker) | [`^8.4.1` -> `^9.0.0`](https://renovatebot.com/diffs/npm/@faker-js%2ffaker/8.4.1/9.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@faker-js%2ffaker/9.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@faker-js%2ffaker/9.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@faker-js%2ffaker/8.4.1/9.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@faker-js%2ffaker/8.4.1/9.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>faker-js/faker (@&#8203;faker-js/faker)</summary>

### [`v9.0.0`](https://redirect.github.com/faker-js/faker/blob/HEAD/CHANGELOG.md#900-2024-09-02)

[Compare Source](https://redirect.github.com/faker-js/faker/compare/v8.4.1...v9.0.0)

No noteworthy changes to [9.0.0-rc.1](https://redirect.github.com/faker-js/faker/blob/next/CHANGELOG.md#900-rc1-2024-08-19)

For those upgrading from earlier versions, please refer to our [Migration Guide](https://v9.fakerjs.dev/guide/upgrading.html) for detailed instructions.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41OS4yIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-05 04:43:03 +00:00
renovate
7c3666ad6d chore: bump up rustc version to v1.80.1 (#8099)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [rustc](https://redirect.github.com/rust-lang/rust) | patch | `1.80.0` -> `1.80.1` |

---

### Release Notes

<details>
<summary>rust-lang/rust (rustc)</summary>

### [`v1.80.1`](https://redirect.github.com/rust-lang/rust/compare/1.80.0...1.80.1)

[Compare Source](https://redirect.github.com/rust-lang/rust/compare/1.80.0...1.80.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41OS4yIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-05 04:19:58 +00:00
renovate
03a071e4cb chore: bump up all non-major dependencies (#8077)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence | Type | Update |
|---|---|---|---|---|---|---|---|
| [@aws-sdk/client-s3](https://redirect.github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://redirect.github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.637.0` -> `3.645.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.637.0/3.645.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.637.0/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.637.0/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@aws-sdk/client-s3](https://redirect.github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://redirect.github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.637.0` -> `3.645.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.637.0/3.645.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.637.0/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.637.0/3.645.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@nx/vite](https://nx.dev) ([source](https://redirect.github.com/nrwl/nx/tree/HEAD/packages/vite)) | [`19.6.4` -> `19.6.5`](https://renovatebot.com/diffs/npm/@nx%2fvite/19.6.4/19.6.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nx%2fvite/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nx%2fvite/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nx%2fvite/19.6.4/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nx%2fvite/19.6.4/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@sentry/esbuild-plugin](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/tree/main/packages/esbuild-plugin) ([source](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins)) | [`2.22.3` -> `2.22.4`](https://renovatebot.com/diffs/npm/@sentry%2fesbuild-plugin/2.22.3/2.22.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2fesbuild-plugin/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2fesbuild-plugin/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2fesbuild-plugin/2.22.3/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2fesbuild-plugin/2.22.3/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@sentry/webpack-plugin](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/tree/main/packages/webpack-plugin) ([source](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins)) | [`2.22.3` -> `2.22.4`](https://renovatebot.com/diffs/npm/@sentry%2fwebpack-plugin/2.22.3/2.22.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2fwebpack-plugin/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2fwebpack-plugin/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2fwebpack-plugin/2.22.3/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2fwebpack-plugin/2.22.3/2.22.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@toeverything/theme](https://redirect.github.com/toeverything/design) | [`1.0.7` -> `1.0.8`](https://renovatebot.com/diffs/npm/@toeverything%2ftheme/1.0.7/1.0.8) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@toeverything%2ftheme/1.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@toeverything%2ftheme/1.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@toeverything%2ftheme/1.0.7/1.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@toeverything%2ftheme/1.0.7/1.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`20.16.3` -> `20.16.5`](https://renovatebot.com/diffs/npm/@types%2fnode/20.16.3/20.16.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.16.3/20.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.16.3/20.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [cssnano](https://redirect.github.com/cssnano/cssnano) | [`7.0.5` -> `7.0.6`](https://renovatebot.com/diffs/npm/cssnano/7.0.5/7.0.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/cssnano/7.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/cssnano/7.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/cssnano/7.0.5/7.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/cssnano/7.0.5/7.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [electron](https://redirect.github.com/electron/electron) | [`32.0.1` -> `32.0.2`](https://renovatebot.com/diffs/npm/electron/32.0.1/32.0.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/electron/32.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/electron/32.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/electron/32.0.1/32.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/electron/32.0.1/32.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [embla-carousel-react](https://www.embla-carousel.com) ([source](https://redirect.github.com/davidjerleke/embla-carousel)) | [`8.2.0` -> `8.2.1`](https://renovatebot.com/diffs/npm/embla-carousel-react/8.2.0/8.2.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/embla-carousel-react/8.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/embla-carousel-react/8.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/embla-carousel-react/8.2.0/8.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/embla-carousel-react/8.2.0/8.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [http-proxy-middleware](https://redirect.github.com/chimurai/http-proxy-middleware) | [`3.0.1` -> `3.0.2`](https://renovatebot.com/diffs/npm/http-proxy-middleware/3.0.1/3.0.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/http-proxy-middleware/3.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/http-proxy-middleware/3.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/http-proxy-middleware/3.0.1/3.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/http-proxy-middleware/3.0.1/3.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [marked](https://marked.js.org) ([source](https://redirect.github.com/markedjs/marked)) | [`14.1.0` -> `14.1.1`](https://renovatebot.com/diffs/npm/marked/14.1.0/14.1.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/marked/14.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/marked/14.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/marked/14.1.0/14.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/marked/14.1.0/14.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [msw](https://mswjs.io) ([source](https://redirect.github.com/mswjs/msw)) | [`2.4.1` -> `2.4.2`](https://renovatebot.com/diffs/npm/msw/2.4.1/2.4.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/msw/2.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/msw/2.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/msw/2.4.1/2.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/msw/2.4.1/2.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [nodemailer](https://nodemailer.com/) ([source](https://redirect.github.com/nodemailer/nodemailer)) | [`6.9.14` -> `6.9.15`](https://renovatebot.com/diffs/npm/nodemailer/6.9.14/6.9.15) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nodemailer/6.9.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nodemailer/6.9.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nodemailer/6.9.14/6.9.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nodemailer/6.9.14/6.9.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [nx](https://nx.dev) ([source](https://redirect.github.com/nrwl/nx/tree/HEAD/packages/nx)) | [`19.6.4` -> `19.6.5`](https://renovatebot.com/diffs/npm/nx/19.6.4/19.6.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nx/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nx/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nx/19.6.4/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nx/19.6.4/19.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [openai](https://redirect.github.com/openai/openai-node) | [`4.57.0` -> `4.57.3`](https://renovatebot.com/diffs/npm/openai/4.57.0/4.57.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/openai/4.57.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/openai/4.57.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/openai/4.57.0/4.57.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/openai/4.57.0/4.57.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [postcss](https://postcss.org/) ([source](https://redirect.github.com/postcss/postcss)) | [`8.4.44` -> `8.4.45`](https://renovatebot.com/diffs/npm/postcss/8.4.44/8.4.45) | [![age](https://developer.mend.io/api/mc/badges/age/npm/postcss/8.4.45?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/postcss/8.4.45?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/postcss/8.4.44/8.4.45?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/postcss/8.4.44/8.4.45?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [serde_json](https://redirect.github.com/serde-rs/json) | `1.0.127` -> `1.0.128` | [![age](https://developer.mend.io/api/mc/badges/age/crate/serde_json/1.0.128?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/serde_json/1.0.128?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/serde_json/1.0.127/1.0.128?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/serde_json/1.0.127/1.0.128?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [sqlx](https://redirect.github.com/launchbadge/sqlx) | `0.8.1` -> `0.8.2` | [![age](https://developer.mend.io/api/mc/badges/age/crate/sqlx/0.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/sqlx/0.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/sqlx/0.8.1/0.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/sqlx/0.8.1/0.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [vaul](https://vaul.emilkowal.ski/) ([source](https://redirect.github.com/emilkowalski/vaul)) | [`0.9.1` -> `0.9.2`](https://renovatebot.com/diffs/npm/vaul/0.9.1/0.9.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vaul/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vaul/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vaul/0.9.1/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vaul/0.9.1/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [vite](https://vitejs.dev) ([source](https://redirect.github.com/vitejs/vite/tree/HEAD/packages/vite)) | [`5.4.2` -> `5.4.3`](https://renovatebot.com/diffs/npm/vite/5.4.2/5.4.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite/5.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/5.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/5.4.2/5.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/5.4.2/5.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [webpack-dev-server](https://redirect.github.com/webpack/webpack-dev-server) | [`5.0.4` -> `5.1.0`](https://renovatebot.com/diffs/npm/webpack-dev-server/5.0.4/5.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/webpack-dev-server/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/webpack-dev-server/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/webpack-dev-server/5.0.4/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/webpack-dev-server/5.0.4/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [wrangler](https://redirect.github.com/cloudflare/workers-sdk) ([source](https://redirect.github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler)) | [`3.73.0` -> `3.74.0`](https://renovatebot.com/diffs/npm/wrangler/3.73.0/3.74.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.73.0/3.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.73.0/3.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |

---

### Release Notes

<details>
<summary>aws/aws-sdk-js-v3 (@&#8203;aws-sdk/client-s3)</summary>

### [`v3.645.0`](https://redirect.github.com/aws/aws-sdk-js-v3/blob/HEAD/clients/client-s3/CHANGELOG.md#36450-2024-09-04)

[Compare Source](https://redirect.github.com/aws/aws-sdk-js-v3/compare/v3.637.0...v3.645.0)

**Note:** Version bump only for package [@&#8203;aws-sdk/client-s3](https://redirect.github.com/aws-sdk/client-s3)

</details>

<details>
<summary>nrwl/nx (@&#8203;nx/vite)</summary>

### [`v19.6.5`](https://redirect.github.com/nrwl/nx/releases/tag/19.6.5)

[Compare Source](https://redirect.github.com/nrwl/nx/compare/19.6.4...19.6.5)

#### 19.6.5 (2024-09-03)

##### 🩹 Fixes

-   **core:** handle file change conflicts between sync generators ([#&#8203;27695](https://redirect.github.com/nrwl/nx/pull/27695))
-   **core:** filter branch in preparation for nx import ([#&#8203;27652](https://redirect.github.com/nrwl/nx/pull/27652))
-   **core:** add parallelism to target defaults schema ([#&#8203;27710](https://redirect.github.com/nrwl/nx/pull/27710))
-   **core:** bump plugin pool attempts to work with slow runtimes ([#&#8203;27726](https://redirect.github.com/nrwl/nx/pull/27726))
-   **detox:** fix name with camel case ([#&#8203;27602](https://redirect.github.com/nrwl/nx/pull/27602))
-   **expo:** fix unable to build expo local for yarn 4 ([#&#8203;26992](https://redirect.github.com/nrwl/nx/pull/26992))
-   **expo:** add cacheVersion to metro.config ([#&#8203;27646](https://redirect.github.com/nrwl/nx/pull/27646))
-   **misc:** fix the URL of the [@&#8203;naxodev/nx-cloudflare](https://redirect.github.com/naxodev/nx-cloudflare) plugin ([#&#8203;27723](https://redirect.github.com/nrwl/nx/pull/27723))
-   **nx-dev:** show first tab if none selected ([#&#8203;27701](https://redirect.github.com/nrwl/nx/pull/27701))
-   **react-native:** change hermesCommand to build android ([#&#8203;27641](https://redirect.github.com/nrwl/nx/pull/27641))
-   **release:** release plan command should take filters and touched projects into account ([#&#8203;27706](https://redirect.github.com/nrwl/nx/pull/27706))
-   **release:** version plan changelogs should contain authors and refs ([#&#8203;27737](https://redirect.github.com/nrwl/nx/pull/27737))

##### ❤️  Thank You

-   Austin Fahsl [@&#8203;fahslaj](https://redirect.github.com/fahslaj)
-   Emily Xiong [@&#8203;xiongemi](https://redirect.github.com/xiongemi)
-   Isaac Mann [@&#8203;isaacplmann](https://redirect.github.com/isaacplmann)
-   Jack Hsu [@&#8203;jaysoo](https://redirect.github.com/jaysoo)
-   James Henry [@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)
-   Leosvel Pérez Espinosa [@&#8203;leosvelperez](https://redirect.github.com/leosvelperez)
-   MaxKless [@&#8203;MaxKless](https://redirect.github.com/MaxKless)
-   Nicolas Beaussart
-   Victor Berchet [@&#8203;vicb](https://redirect.github.com/vicb)

</details>

<details>
<summary>getsentry/sentry-javascript-bundler-plugins (@&#8203;sentry/esbuild-plugin)</summary>

### [`v2.22.4`](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#2224)

[Compare Source](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/compare/2.22.3...2.22.4)

-   feat(react-component-annotate): Handle function body returning a ternary ([#&#8203;598](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/issues/598))
-   fix: Allow injection plugins to apply to files with query parameters and fragments in their name ([#&#8203;597](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/issues/597))

Work in this release contributed by [@&#8203;Thristhart](https://redirect.github.com/Thristhart). Thank you for your contribution!

</details>

<details>
<summary>toeverything/design (@&#8203;toeverything/theme)</summary>

### [`v1.0.8`](https://redirect.github.com/toeverything/design/compare/1.0.7...1.0.8)

[Compare Source](https://redirect.github.com/toeverything/design/compare/1.0.7...1.0.8)

</details>

<details>
<summary>cssnano/cssnano (cssnano)</summary>

### [`v7.0.6`](https://redirect.github.com/cssnano/cssnano/releases/tag/cssnano%407.0.6): v7.0.6

[Compare Source](https://redirect.github.com/cssnano/cssnano/compare/cssnano@7.0.5...cssnano@7.0.6)

#### What's Changed

-   Update postcss-calc and selector-parser by [@&#8203;ludofischer](https://redirect.github.com/ludofischer) in [https://github.com/cssnano/cssnano/pull/1663](https://redirect.github.com/cssnano/cssnano/pull/1663)
-   fix(postcss-convert-values): convert `0ms` to `0s` by [@&#8203;btea](https://redirect.github.com/btea) in [https://github.com/cssnano/cssnano/pull/1665](https://redirect.github.com/cssnano/cssnano/pull/1665)

**Full Changelog**: https://github.com/cssnano/cssnano/compare/cssnano@7.0.5...cssnano@7.0.6

</details>

<details>
<summary>electron/electron (electron)</summary>

### [`v32.0.2`](https://redirect.github.com/electron/electron/releases/tag/v32.0.2): electron v32.0.2

[Compare Source](https://redirect.github.com/electron/electron/compare/v32.0.1...v32.0.2)

### Release Notes for v32.0.2

#### Fixes

-   Fixed `MenuItem.click` handler not setting `focusedWindow` parameter when focused window is a `BaseWindow`. [#&#8203;43437](https://redirect.github.com/electron/electron/pull/43437) <span style="font-size:small;">(Also in [31](https://redirect.github.com/electron/electron/pull/43439), [33](https://redirect.github.com/electron/electron/pull/43438))</span>
-   Fixed an issue where `BaseWindow.setTouchBar` didn't work as expected. [#&#8203;43421](https://redirect.github.com/electron/electron/pull/43421) <span style="font-size:small;">(Also in [30](https://redirect.github.com/electron/electron/pull/43419), [31](https://redirect.github.com/electron/electron/pull/43420), [33](https://redirect.github.com/electron/electron/pull/43422))</span>
-   Fixed bug where camera permissions affected screen sharing. [#&#8203;43544](https://redirect.github.com/electron/electron/pull/43544)
-   Fixed devtools to allow restoring saved dock state on Linux when WCO is enabled. [#&#8203;43501](https://redirect.github.com/electron/electron/pull/43501) <span style="font-size:small;">(Also in [31](https://redirect.github.com/electron/electron/pull/43500), [33](https://redirect.github.com/electron/electron/pull/43499))</span>
-   Fixed electron app in ozone/wayland not being focused when launched from another app. [#&#8203;43548](https://redirect.github.com/electron/electron/pull/43548) <span style="font-size:small;">(Also in [31](https://redirect.github.com/electron/electron/pull/43547), [33](https://redirect.github.com/electron/electron/pull/43546))</span>

#### Other Changes

-   Updated Chromium to 128.0.6613.84. [#&#8203;43425](https://redirect.github.com/electron/electron/pull/43425)

#### Documentation

-   Documentation changes: [#&#8203;43459](https://redirect.github.com/electron/electron/pull/43459)

</details>

<details>
<summary>davidjerleke/embla-carousel (embla-carousel-react)</summary>

### [`v8.2.1`](https://redirect.github.com/davidjerleke/embla-carousel/compare/v8.2.0...81c506653be467c0878240ac02f25b0626136b89)

[Compare Source](https://redirect.github.com/davidjerleke/embla-carousel/compare/v8.2.0...v8.2.1)

</details>

<details>
<summary>chimurai/http-proxy-middleware (http-proxy-middleware)</summary>

### [`v3.0.2`](https://redirect.github.com/chimurai/http-proxy-middleware/blob/HEAD/CHANGELOG.md#v302)

[Compare Source](https://redirect.github.com/chimurai/http-proxy-middleware/compare/v3.0.1...v3.0.2)

-   refactor(dependency): replace is-plain-obj with is-plain-object ([#&#8203;1031](https://redirect.github.com/chimurai/http-proxy-middleware/pull/1031))
-   chore(package): upgrade to eslint v9 ([#&#8203;1032](https://redirect.github.com/chimurai/http-proxy-middleware/pull/1032))
-   fix(logger-plugin): handle undefined protocol and hostname ([#&#8203;1036](https://redirect.github.com/chimurai/http-proxy-middleware/pull/1036))

</details>

<details>
<summary>markedjs/marked (marked)</summary>

### [`v14.1.1`](https://redirect.github.com/markedjs/marked/compare/v14.1.0...f3c387fbcf9f9a7738072c29ec5f1ed5a326438c)

[Compare Source](https://redirect.github.com/markedjs/marked/compare/v14.1.0...v14.1.1)

</details>

<details>
<summary>mswjs/msw (msw)</summary>

### [`v2.4.2`](https://redirect.github.com/mswjs/msw/releases/tag/v2.4.2)

[Compare Source](https://redirect.github.com/mswjs/msw/compare/v2.4.1...v2.4.2)

#### v2.4.2 (2024-09-04)

##### Bug Fixes

-   **cli:** support windows paths in the `init` command ([#&#8203;2260](https://redirect.github.com/mswjs/msw/issues/2260)) ([`ba285b8`](ba285b887c)) [@&#8203;ivanfernandez2646](https://redirect.github.com/ivanfernandez2646) [@&#8203;kettanaito](https://redirect.github.com/kettanaito)
-   use typescript@4.8 as the minimal supported version ([#&#8203;2251](https://redirect.github.com/mswjs/msw/issues/2251)) ([`6b2a7e6`](6b2a7e6be8)) [@&#8203;THETCR](https://redirect.github.com/THETCR) [@&#8203;kettanaito](https://redirect.github.com/kettanaito)
-   keep `graphql` import as require in cjs ([#&#8203;2258](https://redirect.github.com/mswjs/msw/issues/2258)) ([`b977602`](b97760270b)) [@&#8203;kettanaito](https://redirect.github.com/kettanaito)

</details>

<details>
<summary>nodemailer/nodemailer (nodemailer)</summary>

### [`v6.9.15`](https://redirect.github.com/nodemailer/nodemailer/blob/HEAD/CHANGELOG.md#6915-2024-08-08)

[Compare Source](https://redirect.github.com/nodemailer/nodemailer/compare/v6.9.14...v6.9.15)

##### Bug Fixes

-   Fix memory leak ([#&#8203;1667](https://redirect.github.com/nodemailer/nodemailer/issues/1667)) ([baa28f6](baa28f6596))
-   **mime:** Added GeoJSON closes [#&#8203;1637](https://redirect.github.com/nodemailer/nodemailer/issues/1637) ([#&#8203;1665](https://redirect.github.com/nodemailer/nodemailer/issues/1665)) ([79b8293](79b8293ad5))

</details>

<details>
<summary>openai/openai-node (openai)</summary>

### [`v4.57.3`](https://redirect.github.com/openai/openai-node/blob/HEAD/CHANGELOG.md#4573-2024-09-04)

[Compare Source](https://redirect.github.com/openai/openai-node/compare/v4.57.2...v4.57.3)

Full Changelog: [v4.57.2...v4.57.3](https://redirect.github.com/openai/openai-node/compare/v4.57.2...v4.57.3)

##### Bug Fixes

-   **helpers/zod:** avoid import issue in certain environments ([#&#8203;1039](https://redirect.github.com/openai/openai-node/issues/1039)) ([e238daa](e238daa7c1))

##### Chores

-   **internal:** minor bump qs version ([#&#8203;1037](https://redirect.github.com/openai/openai-node/issues/1037)) ([8ec218e](8ec218e9ef))

### [`v4.57.2`](https://redirect.github.com/openai/openai-node/blob/HEAD/CHANGELOG.md#4572-2024-09-04)

[Compare Source](https://redirect.github.com/openai/openai-node/compare/v4.57.1...v4.57.2)

Full Changelog: [v4.57.1...v4.57.2](https://redirect.github.com/openai/openai-node/compare/v4.57.1...v4.57.2)

##### Chores

-   **internal:** dependency updates ([#&#8203;1035](https://redirect.github.com/openai/openai-node/issues/1035)) ([e815fb6](e815fb6dee))

### [`v4.57.1`](https://redirect.github.com/openai/openai-node/blob/HEAD/CHANGELOG.md#4571-2024-09-03)

[Compare Source](https://redirect.github.com/openai/openai-node/compare/v4.57.0...v4.57.1)

Full Changelog: [v4.57.0...v4.57.1](https://redirect.github.com/openai/openai-node/compare/v4.57.0...v4.57.1)

##### Bug Fixes

-   **assistants:** correctly accumulate tool calls when streaming ([#&#8203;1031](https://redirect.github.com/openai/openai-node/issues/1031)) ([d935ad3](d935ad3fa3))
-   **client:** correct File construction from node-fetch Responses ([#&#8203;1029](https://redirect.github.com/openai/openai-node/issues/1029)) ([22ebdc2](22ebdc2ca7))
-   runTools without stream should not emit user message events ([#&#8203;1005](https://redirect.github.com/openai/openai-node/issues/1005)) ([22ded4d](22ded4d549))

##### Chores

-   **internal/tests:** workaround bug in recent types/node release ([3c7bdfd](3c7bdfdb37))

</details>

<details>
<summary>postcss/postcss (postcss)</summary>

### [`v8.4.45`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8445)

[Compare Source](https://redirect.github.com/postcss/postcss/compare/8.4.44...8.4.45)

-   Removed unnecessary fix which could lead to infinite loop.

</details>

<details>
<summary>serde-rs/json (serde_json)</summary>

### [`v1.0.128`](https://redirect.github.com/serde-rs/json/releases/tag/1.0.128)

[Compare Source](https://redirect.github.com/serde-rs/json/compare/1.0.127...1.0.128)

-   Support serializing maps containing 128-bit integer keys to serde_json::Value ([#&#8203;1188](https://redirect.github.com/serde-rs/json/issues/1188), thanks [@&#8203;Mrreadiness](https://redirect.github.com/Mrreadiness))

</details>

<details>
<summary>launchbadge/sqlx (sqlx)</summary>

### [`v0.8.2`](https://redirect.github.com/launchbadge/sqlx/blob/HEAD/CHANGELOG.md#082---2024-09-02)

[Compare Source](https://redirect.github.com/launchbadge/sqlx/compare/v0.8.1...v0.8.2)

10 pull requests were merged this release cycle.

This release addresses a few regressions that have occurred, and refines SQLx's MSRV policy (see [the FAQ](FAQ.md)).

##### Added

-   \[[#&#8203;3447]]: Clarify usage of Json/Jsonb in query macros \[\[[@&#8203;Lachstec](https://redirect.github.com/Lachstec)]]

##### Changed

-   \[[#&#8203;3424]]: Remove deprecated feature-names from `Cargo.toml` files in examples \[\[[@&#8203;carschandler](https://redirect.github.com/carschandler)]]

##### Fixed

-   \[[#&#8203;3403]]: Fix ([#&#8203;3395](https://redirect.github.com/launchbadge/sqlx/issues/3395)) sqlx::test macro in 0.8 \[\[[@&#8203;joeydewaal](https://redirect.github.com/joeydewaal)]]
-   \[[#&#8203;3411]]: fix: Use rfc3339 to decode date from text \[\[[@&#8203;pierre-wehbe](https://redirect.github.com/pierre-wehbe)]]
-   \[[#&#8203;3453]]: fix([#&#8203;3445](https://redirect.github.com/launchbadge/sqlx/issues/3445)): PgHasArrayType \[\[[@&#8203;joeydewaal](https://redirect.github.com/joeydewaal)]]
    -   Fixes `#[sqlx(no_pg_array)]` being forbidden on `#[derive(Type)]` structs.
-   \[[#&#8203;3454]]: fix: non snake case warning \[\[[@&#8203;joeydewaal](https://redirect.github.com/joeydewaal)]]
-   \[[#&#8203;3459]]: Pgsql cube type compile fail \[\[[@&#8203;kdesjard](https://redirect.github.com/kdesjard)]]
-   \[[#&#8203;3465]]: fix(postgres): max number of binds is 65535, not 32767 (regression) \[\[[@&#8203;abonander](https://redirect.github.com/abonander)]]
-   \[[#&#8203;3467]]: fix cancellation issues with `PgListener`, `PgStream::recv()` \[\[[@&#8203;abonander](https://redirect.github.com/abonander)]]
    -   Fixes cryptic `unknown message: "\\0"` error
-   \[[#&#8203;3474]]: Fix try_get example in README.md \[\[[@&#8203;luveti](https://redirect.github.com/luveti)]]

[#&#8203;3403]: https://redirect.github.com/launchbadge/sqlx/pull/3403

[#&#8203;3411]: https://redirect.github.com/launchbadge/sqlx/pull/3411

[#&#8203;3424]: https://redirect.github.com/launchbadge/sqlx/pull/3424

[#&#8203;3447]: https://redirect.github.com/launchbadge/sqlx/pull/3447

[#&#8203;3453]: https://redirect.github.com/launchbadge/sqlx/pull/3453

[#&#8203;3454]: https://redirect.github.com/launchbadge/sqlx/pull/3454

[#&#8203;3455]: https://redirect.github.com/launchbadge/sqlx/pull/3455

[#&#8203;3459]: https://redirect.github.com/launchbadge/sqlx/pull/3459

[#&#8203;3465]: https://redirect.github.com/launchbadge/sqlx/pull/3465

[#&#8203;3467]: https://redirect.github.com/launchbadge/sqlx/pull/3467

[#&#8203;3474]: https://redirect.github.com/launchbadge/sqlx/pull/3474

</details>

<details>
<summary>emilkowalski/vaul (vaul)</summary>

### [`v0.9.2`](https://redirect.github.com/emilkowalski/vaul/releases/tag/v0.9.2)

[Compare Source](https://redirect.github.com/emilkowalski/vaul/compare/v0.9.1...v0.9.2)

Expect much more updates in the very near future :)

#### What's Changed

-   fix(src): Replace `React.useLayoutEffect` with `useIsomorphicLayoutEffect` by [@&#8203;axeldesutter](https://redirect.github.com/axeldesutter) in [https://github.com/emilkowalski/vaul/pull/368](https://redirect.github.com/emilkowalski/vaul/pull/368)
-   build: upgrade bundler by [@&#8203;huozhi](https://redirect.github.com/huozhi) in [https://github.com/emilkowalski/vaul/pull/315](https://redirect.github.com/emilkowalski/vaul/pull/315)
-   chore: update pnpm by [@&#8203;emilkowalski](https://redirect.github.com/emilkowalski) in [https://github.com/emilkowalski/vaul/pull/401](https://redirect.github.com/emilkowalski/vaul/pull/401)

#### New Contributors

-   [@&#8203;axeldesutter](https://redirect.github.com/axeldesutter) made their first contribution in [https://github.com/emilkowalski/vaul/pull/368](https://redirect.github.com/emilkowalski/vaul/pull/368)

**Full Changelog**: https://github.com/emilkowalski/vaul/compare/v0.9.1...v0.9.2

</details>

<details>
<summary>vitejs/vite (vite)</summary>

### [`v5.4.3`](https://redirect.github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small543-2024-09-03-small)

[Compare Source](https://redirect.github.com/vitejs/vite/compare/v5.4.2...v5.4.3)

-   fix: allow getting URL of JS files in publicDir ([#&#8203;17915](https://redirect.github.com/vitejs/vite/issues/17915)) ([943ece1](943ece177e)), closes [#&#8203;17915](https://redirect.github.com/vitejs/vite/issues/17915)
-   fix: cjs warning respect the logLevel flag ([#&#8203;17993](https://redirect.github.com/vitejs/vite/issues/17993)) ([dc3c14f](dc3c14f39f)), closes [#&#8203;17993](https://redirect.github.com/vitejs/vite/issues/17993)
-   fix: improve CJS warning trace information ([#&#8203;17926](https://redirect.github.com/vitejs/vite/issues/17926)) ([5c5f82c](5c5f82c84b)), closes [#&#8203;17926](https://redirect.github.com/vitejs/vite/issues/17926)
-   fix: only remove entry assets handled by Vite core ([#&#8203;17916](https://redirect.github.com/vitejs/vite/issues/17916)) ([ebfaa7e](ebfaa7e601)), closes [#&#8203;17916](https://redirect.github.com/vitejs/vite/issues/17916)
-   fix: waitForRequestIdle locked ([#&#8203;17982](https://redirect.github.com/vitejs/vite/issues/17982)) ([ad13760](ad1376018a)), closes [#&#8203;17982](https://redirect.github.com/vitejs/vite/issues/17982)
-   fix(css): fix directory index import in sass modern api ([#&#8203;17960](https://redirect.github.com/vitejs/vite/issues/17960)) ([9b001ba](9b001baa70)), closes [#&#8203;17960](https://redirect.github.com/vitejs/vite/issues/17960)
-   fix(css): fix sass `file://` reference ([#&#8203;17909](https://redirect.github.com/vitejs/vite/issues/17909)) ([561b940](561b940f6f)), closes [#&#8203;17909](https://redirect.github.com/vitejs/vite/issues/17909)
-   fix(css): fix sass modern source map ([#&#8203;17938](https://redirect.github.com/vitejs/vite/issues/17938)) ([d428e7e](d428e7e3a0)), closes [#&#8203;17938](https://redirect.github.com/vitejs/vite/issues/17938)
-   fix(deps): bump tsconfck  ([#&#8203;17990](https://redirect.github.com/vitejs/vite/issues/17990)) ([8c661b2](8c661b20e9)), closes [#&#8203;17990](https://redirect.github.com/vitejs/vite/issues/17990)
-   fix(html): rewrite assets url in <template> ([#&#8203;17988](https://redirect.github.com/vitejs/vite/issues/17988)) ([413c86a](413c86aa97)), closes [#&#8203;17988](https://redirect.github.com/vitejs/vite/issues/17988)
-   fix(preload): add crossorigin attribute in CSS link tags ([#&#8203;17930](https://redirect.github.com/vitejs/vite/issues/17930)) ([15871c7](15871c75e0)), closes [#&#8203;17930](https://redirect.github.com/vitejs/vite/issues/17930)
-   chore: reduce diffs with v6 branch ([#&#8203;17942](https://redirect.github.com/vitejs/vite/issues/17942)) ([bf9065a](bf9065aa13)), closes [#&#8203;17942](https://redirect.github.com/vitejs/vite/issues/17942)
-   chore(deps): update all non-major dependencies ([#&#8203;17945](https://redirect.github.com/vitejs/vite/issues/17945)) ([cfb621e](cfb621e7a5)), closes [#&#8203;17945](https://redirect.github.com/vitejs/vite/issues/17945)
-   chore(deps): update all non-major dependencies ([#&#8203;17991](https://redirect.github.com/vitejs/vite/issues/17991)) ([0ca53cf](0ca53cff9f)), closes [#&#8203;17991](https://redirect.github.com/vitejs/vite/issues/17991)

</details>

<details>
<summary>webpack/webpack-dev-server (webpack-dev-server)</summary>

### [`v5.1.0`](https://redirect.github.com/webpack/webpack-dev-server/blob/HEAD/CHANGELOG.md#510-2024-09-03)

[Compare Source](https://redirect.github.com/webpack/webpack-dev-server/compare/v5.0.4...v5.1.0)

##### Features

-   add visual progress indicators ([a8f40b7](a8f40b74e6))
-   added the `app` option to be `Function` (by default only with `connect` compatibility frameworks) ([3096148](3096148746))
-   allow the `server` option to be `Function` ([#&#8203;5275](https://redirect.github.com/webpack/webpack-dev-server/issues/5275)) ([02a1c6d](02a1c6d788))
-   http2 support for `connect` and `connect` compatibility frameworks which support HTTP2 ([#&#8203;5267](https://redirect.github.com/webpack/webpack-dev-server/issues/5267)) ([6509a3f](6509a3fd3e))

##### Bug Fixes

-   check the `platform` property to determinate the target ([#&#8203;5269](https://redirect.github.com/webpack/webpack-dev-server/issues/5269)) ([c3b532c](c3b532c636))
-   ipv6 output ([#&#8203;5270](https://redirect.github.com/webpack/webpack-dev-server/issues/5270)) ([06005e7](06005e7cb9))
-   replace `rimraf` with `rm` ([#&#8203;5162](https://redirect.github.com/webpack/webpack-dev-server/issues/5162)) ([1a1561f](1a1561f09b))
-   replace default gateway ([#&#8203;5255](https://redirect.github.com/webpack/webpack-dev-server/issues/5255)) ([f5f0902](f5f09024ff))
-   support `devServer: false` ([#&#8203;5272](https://redirect.github.com/webpack/webpack-dev-server/issues/5272)) ([8b341cb](8b341cb8c1))

##### [5.0.4](https://redirect.github.com/webpack/webpack-dev-server/compare/v5.0.3...v5.0.4) (2024-03-19)

##### Bug Fixes

-   **security:** bump webpack-dev-middleware ([#&#8203;5112](https://redirect.github.com/webpack/webpack-dev-server/issues/5112)) ([aab576a](aab576a9e4))

##### [5.0.3](https://redirect.github.com/webpack/webpack-dev-server/compare/v5.0.2...v5.0.3) (2024-03-12)

##### Bug Fixes

-   **types:** proxy ([#&#8203;5101](https://redirect.github.com/webpack/webpack-dev-server/issues/5101)) ([6e1aed3](6e1aed30ff))

##### [5.0.2](https://redirect.github.com/webpack/webpack-dev-server/compare/v5.0.1...v5.0.2) (2024-02-16)

##### Bug Fixes

-   types ([#&#8203;5057](https://redirect.github.com/webpack/webpack-dev-server/issues/5057)) ([da2c24d](da2c24ddd9))

##### [5.0.1](https://redirect.github.com/webpack/webpack-dev-server/compare/v5.0.0...v5.0.1) (2024-02-13)

##### Bug Fixes

-   avoid using eval in client ([#&#8203;5045](https://redirect.github.com/webpack/webpack-dev-server/issues/5045)) ([7681477](76814771dc))
-   overlay and `require-trusted-types-for` ([#&#8203;5046](https://redirect.github.com/webpack/webpack-dev-server/issues/5046)) ([e115436](e115436771))

</details>

<details>
<summary>cloudflare/workers-sdk (wrangler)</summary>

### [`v3.74.0`](https://redirect.github.com/cloudflare/workers-sdk/blob/HEAD/packages/wrangler/CHANGELOG.md#3740)

[Compare Source](https://redirect.github.com/cloudflare/workers-sdk/compare/wrangler@3.73.0...wrangler@3.74.0)

##### Minor Changes

-   [#&#8203;6574](https://redirect.github.com/cloudflare/workers-sdk/pull/6574) [`dff8d44`](dff8d44f4e) Thanks [@&#8203;CarmenPopoviciu](https://redirect.github.com/CarmenPopoviciu)! - feat: add support for experimental assets in `wrangler dev` watch mode

##### Patch Changes

-   [#&#8203;6605](https://redirect.github.com/cloudflare/workers-sdk/pull/6605) [`c4f0d9e`](c4f0d9e01e) Thanks [@&#8203;WalshyDev](https://redirect.github.com/WalshyDev)! - fix: ensure we update non-versioned Worker settings for the new deploy path in `wrangler deploy`

-   Updated dependencies \[[`e8975a9`](e8975a93a4)]:
    -   miniflare@3.20240821.1

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41OS4yIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-05 03:46:53 +00:00
fundon
2bdf8c6ef3 chore(core): track copy block to link action (#8056)
part of [BS-1254](https://linear.app/affine-design/issue/BS-1254/增加-block-reference-的埋点)
2024-09-05 03:21:25 +00:00
LongYinan
c6840c8674 fix(server): wrong mobile root in dev env 2024-09-05 11:18:43 +08:00
akumatus
5f3dd867ad feat(core): support snapshot preview in editor settings (#8094)
<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/sJGviKxfE3Ap685cl5bj/a991f7d2-f9c6-4241-a24b-b8c01cb86af3.mov">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/sJGviKxfE3Ap685cl5bj/a991f7d2-f9c6-4241-a24b-b8c01cb86af3.mov">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/a991f7d2-f9c6-4241-a24b-b8c01cb86af3.mov">录屏2024-09-04 22.26.47.mov</video>
2024-09-05 02:58:54 +00:00
pengx17
b680c1839b fix(core): edit tag should not jump to its detail (#8070)
fix AF-1324
2024-09-05 02:46:07 +00:00
pengx17
1cac2f6ccd feat(core): add journal navigation tracking (#8046)
fix AF-1314
2024-09-05 02:31:58 +00:00
CatsJuice
06552a1120 fix(mobile): explorer node touch optimization (#8101)
close AF-1338
2024-09-05 02:18:28 +00:00
Yifeng Wang
416faba2bc chore: support http proxy in bump script (#8098) 2024-09-05 10:14:51 +08:00
pengx17
93ae724c66 chore(electron): downgrade electron to v31 (#8095)
fix AF-1337
it seems the way how we load web worker file in electron no longer works.
created an upstream issue in https://github.com/electron/electron/issues/43556
2024-09-05 01:30:26 +00:00
pengx17
989e8830f7 fix(mobile): workspace selector not close on click outside (#8096) 2024-09-04 16:57:57 +00:00
pengx17
0ae5673aaa feat(electron): add offline mode (#8086)
fix AF-1334

It seems `session.enableNetworkEmulation({ offline: true });` does not work - https://github.com/electron/electron/issues/21250

implemented using an in-house solution.

When turned on:

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/6805735b-1006-4e51-be46-c047b0f1a82c.png)
2024-09-04 10:46:43 +00:00
CatsJuice
51bc40d2a8 fix(mobile): header will be clipped when modal opened and page scrolled (#8079)
close AF-1332

This issue is caused by radix, it will set `overflow: hidden` to body when modal opened. And header is implemented with `position: sticky`.

> **why not use `position: fixed` for header?**
>
> We need to handle `padding-top` manually to avoid content covered by header.
2024-09-04 09:36:18 +00:00
EYHN
2524491bd1 fix(env): is mobile flag (#8005)
only 'mobile' entry has isMobile = true flag
2024-09-04 09:21:36 +00:00
Brooooooklyn
53886a7cd3 fix(server): wrong env variable condition in nginx conf (#8084) 2024-09-04 08:57:04 +00:00
JimmFly
f688c057eb feat(core): impl AI switch (#8018)
close PD-1658

https://github.com/user-attachments/assets/2f3d1d26-1879-4d95-b80c-7c0965cefbd0
2024-09-04 08:44:05 +00:00
EYHN
eb16c273ee feat(core): apply default doc mode setting (#8083) 2024-09-04 08:31:36 +00:00
EYHN
01b2339173 refactor(core): better block link (#8082) 2024-09-04 08:13:22 +00:00
EYHN
2799e8cd43 fix(electron): fix ci (#8085) 2024-09-04 08:00:09 +00:00
EYHN
fb64bc7e55 feat(core): indexer upgrade (#8062) 2024-09-04 07:31:03 +00:00
EYHN
51f3566bec fix(core): fix menu bugs (#8074) 2024-09-04 07:19:09 +00:00
pengx17
01e6370dd2 fix(electron): use CTRL+= to zoom in on windows (#8081)
fix AF-1291
2024-09-04 04:23:55 +00:00
pengx17
2ac803c73f feat(mobile): sign in page (#8039)
fix AF-1237
2024-09-04 03:58:54 +00:00
CatsJuice
0d6f468385 fix(component): nested modal view-transition support (#8073)
<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/LakojjjzZNf6ogjOVwKE/b8033923-8f08-4c72-96b6-d790fc0ff703.mp4">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/LakojjjzZNf6ogjOVwKE/b8033923-8f08-4c72-96b6-d790fc0ff703.mp4">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/LakojjjzZNf6ogjOVwKE/b8033923-8f08-4c72-96b6-d790fc0ff703.mp4">CleanShot 2024-09-03 at 18.36.17.mp4</video>
2024-09-04 01:29:22 +00:00
CatsJuice
ec3b97d069 fix(component): replace storybook-dark-mode with globalTypes toolbar impl (#8066) 2024-09-03 15:18:24 +00:00
pengx17
7dde509970 fix(core): page info modal styles (#8067) 2024-09-03 12:46:37 +00:00
Saul-Mirone
681f4561fb chore: bump bs (#8071) 2024-09-03 12:12:59 +00:00
pengx17
d00f86c3ce fix(core): handle modal overlay click event correctly (#8063)
1. overlay click + hide is brought back. this is because modal (ormobile menu)'s `onPointerDownOutside` is bound to document.body. Code in e58af08f63/packages/frontend/core/src/modules/explorer/views/tree/node.tsx (L353-L356) will stop the event from bubbling to the document element.
2. when Menu's set to modal=true, the parent is set to pointer-events: none as well. changed menu to modal false instead.

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/3e50281f-839d-4463-af00-dff2fce8202b.png)
2024-09-03 12:00:00 +00:00
pengx17
ae3b13bfb4 fix(electron): only the active view should respond to CMD+N (#8068) 2024-09-03 11:48:06 +00:00
renovate
aad442e73d chore: bump up @sentry/react version to v8.28.0 (#8072)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@sentry/react](https://redirect.github.com/getsentry/sentry-javascript/tree/master/packages/react) ([source](https://redirect.github.com/getsentry/sentry-javascript)) | [`8.27.0` -> `8.28.0`](https://renovatebot.com/diffs/npm/@sentry%2freact/8.27.0/8.28.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2freact/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2freact/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2freact/8.27.0/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2freact/8.27.0/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>getsentry/sentry-javascript (@&#8203;sentry/react)</summary>

### [`v8.28.0`](https://redirect.github.com/getsentry/sentry-javascript/releases/tag/8.28.0)

##### Important Changes

-   **Beta release of official NestJS SDK**

This release contains the beta version of `@sentry/nestjs`! For details on how to use it, check out the
[README](https://redirect.github.com/getsentry/sentry-javascript/blob/master/packages/nestjs/README.md). Any feedback/bug reports
are greatly appreciated, please reach out on GitHub.

-   **fix(browser): Remove faulty LCP, FCP and FP normalization logic ([#&#8203;13502](https://redirect.github.com/getsentry/sentry-javascript/issues/13502))**

This release fixes a bug in the `@sentry/browser` package and all SDKs depending on this package (e.g. `@sentry/react`
or `@sentry/nextjs`) that caused the SDK to send incorrect web vital values for the LCP, FCP and FP vitals. The SDK
previously incorrectly processed the original values as they were reported from the browser. When updating your SDK to
this version, you might experience an increase in LCP, FCP and FP values, which potentially leads to a decrease in your
performance score in the Web Vitals Insights module in Sentry. This is because the previously reported values were
smaller than the actually measured values. We apologize for the inconvenience!

##### Other Changes

-   feat(nestjs): Add `SentryGlobalGraphQLFilter` ([#&#8203;13545](https://redirect.github.com/getsentry/sentry-javascript/issues/13545))
-   feat(nestjs): Automatic instrumentation of nestjs interceptors after route execution ([#&#8203;13264](https://redirect.github.com/getsentry/sentry-javascript/issues/13264))
-   feat(nextjs): Add `bundleSizeOptimizations` to build options ([#&#8203;13323](https://redirect.github.com/getsentry/sentry-javascript/issues/13323))
-   feat(nextjs): Stabilize `captureRequestError` ([#&#8203;13550](https://redirect.github.com/getsentry/sentry-javascript/issues/13550))
-   feat(nuxt): Wrap config in nuxt context ([#&#8203;13457](https://redirect.github.com/getsentry/sentry-javascript/issues/13457))
-   feat(profiling): Expose profiler as top level primitive ([#&#8203;13512](https://redirect.github.com/getsentry/sentry-javascript/issues/13512))
-   feat(replay): Add layout shift to CLS replay data ([#&#8203;13386](https://redirect.github.com/getsentry/sentry-javascript/issues/13386))
-   feat(replay): Upgrade rrweb packages to 2.26.0 ([#&#8203;13483](https://redirect.github.com/getsentry/sentry-javascript/issues/13483))
-   fix(cdn): Do not mangle \_metadata ([#&#8203;13426](https://redirect.github.com/getsentry/sentry-javascript/issues/13426))
-   fix(cdn): Fix SDK source for CDN bundles ([#&#8203;13475](https://redirect.github.com/getsentry/sentry-javascript/issues/13475))
-   fix(nestjs): Check arguments before instrumenting with `@Injectable` ([#&#8203;13544](https://redirect.github.com/getsentry/sentry-javascript/issues/13544))
-   fix(nestjs): Ensure exception and host are correctly passed on when using [@&#8203;WithSentry](https://redirect.github.com/WithSentry) ([#&#8203;13564](https://redirect.github.com/getsentry/sentry-javascript/issues/13564))
-   fix(node): Suppress tracing for transport request execution rather than transport creation ([#&#8203;13491](https://redirect.github.com/getsentry/sentry-javascript/issues/13491))
-   fix(replay): Consider more things as DOM mutations for dead clicks ([#&#8203;13518](https://redirect.github.com/getsentry/sentry-javascript/issues/13518))
-   fix(vue): Correctly obtain component name ([#&#8203;13484](https://redirect.github.com/getsentry/sentry-javascript/issues/13484))

Work in this release was contributed by [@&#8203;leopoldkristjansson](https://redirect.github.com/leopoldkristjansson), [@&#8203;mhuggins](https://redirect.github.com/mhuggins) and [@&#8203;filips123](https://redirect.github.com/filips123). Thank you for your
contributions!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41OS4yIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-03 11:35:00 +00:00
renovate
4595df9b0e chore: bump up react-day-picker version to v9 (#7559)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [react-day-picker](https://daypicker.dev) ([source](https://redirect.github.com/gpbl/react-day-picker)) | [`^8.10.1` -> `^9.0.0`](https://renovatebot.com/diffs/npm/react-day-picker/8.10.1/9.0.8) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-day-picker/9.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-day-picker/9.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-day-picker/8.10.1/9.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-day-picker/8.10.1/9.0.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>gpbl/react-day-picker (react-day-picker)</summary>

### [`v9.0.8`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.8)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.7...v9.0.8)

This release fixes a regression in v9.0.7 affecting range mode.

#### What's Changed

-   fix: update the displayed month only if start/end month change by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2358](https://redirect.github.com/gpbl/react-day-picker/pull/2358)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.7...v9.0.8

### [`v9.0.7`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.7)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.6...v9.0.7)

This release improves compatibility with v8 and fix an issue with the calendar navigation.

#### What's Changed

-   fix: update calendar state when `startMonth` or `endMonth` change by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2343](https://redirect.github.com/gpbl/react-day-picker/pull/2343)
-   feat: allow partial locales, export `defaultLocale` by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2348](https://redirect.github.com/gpbl/react-day-picker/pull/2348)
-   feat: allow `undefined` as initially selected value, as it was in v8 by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2341](https://redirect.github.com/gpbl/react-day-picker/pull/2341)
-   docs: changed class name `calendar` to  `root` in the examples by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2347](https://redirect.github.com/gpbl/react-day-picker/pull/2347)
-   docs: replaced deprecated props by [@&#8203;josephmarkus](https://redirect.github.com/josephmarkus) in [https://github.com/gpbl/react-day-picker/pull/2336](https://redirect.github.com/gpbl/react-day-picker/pull/2336)\*

#### New Contributors

-   [@&#8203;josephmarkus](https://redirect.github.com/josephmarkus) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2336](https://redirect.github.com/gpbl/react-day-picker/pull/2336)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.6...v9.0.7

### [`v9.0.6`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.6)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.5...v9.0.6)

This release addresses the failed import of the common-js module for some app builder and add new `data-` attributes to help the integration with Tailwind. Thanks for your feedback!

#### What's Changed

-   fix(build): add package.json to dist/cjs module by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2330](https://redirect.github.com/gpbl/react-day-picker/pull/2330)
-   feat: add new data-attributes to the day cells by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2331](https://redirect.github.com/gpbl/react-day-picker/pull/2331)

#### New Contributors

-   [@&#8203;lesleh](https://redirect.github.com/lesleh) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2329](https://redirect.github.com/gpbl/react-day-picker/pull/2329)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.5...v9.0.6

### [`v9.0.5`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.5)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.4...v9.0.5)

This release improves the range mode behavior (see the [updated docs](https://daypicker.dev/docs/selection-modes#range-mode)) and address some styling issues.

#### What's Changed

-   fix: improved range mode to work with min / required props by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2326](https://redirect.github.com/gpbl/react-day-picker/pull/2326)
-   fix(style): typo in css rdp-hidden module css breaking CSS builds by [@&#8203;ayuhito](https://redirect.github.com/ayuhito) in [https://github.com/gpbl/react-day-picker/pull/2307](https://redirect.github.com/gpbl/react-day-picker/pull/2307)
-   fix(style): borders grid are not collapsed by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2323](https://redirect.github.com/gpbl/react-day-picker/pull/2323)
-   fix(style): week numbers are now centered by [@&#8203;gpbl](https://redirect.github.com/gpbl) in c919ad829c

#### New Contributors

-   [@&#8203;ayuhito](https://redirect.github.com/ayuhito) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2307](https://redirect.github.com/gpbl/react-day-picker/pull/2307)
-   [@&#8203;rishabh-ink](https://redirect.github.com/rishabh-ink) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2311](https://redirect.github.com/gpbl/react-day-picker/pull/2311)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.4...v9.0.5

### [`v9.0.4`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.4)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.3...v9.0.4)

This release fixes some bugs and improves compatibility with v8.10. Thanks for your feedback and patience! 🤖

#### What's Changed

-   fix(css): typo in `.rdp-range_end` by [@&#8203;AlessioDP](https://redirect.github.com/AlessioDP) in [https://github.com/gpbl/react-day-picker/pull/2298](https://redirect.github.com/gpbl/react-day-picker/pull/2298)
-   fix(css): dropdown is transparent in Windows OS by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2300](https://redirect.github.com/gpbl/react-day-picker/pull/2300)
-   fix: `endMonth` date not working as expected by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2301](https://redirect.github.com/gpbl/react-day-picker/pull/2301)
-   feat: added back `onDayMouseEnter` and `onDayMouseLeave` by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2304](https://redirect.github.com/gpbl/react-day-picker/pull/2304)

#### New Contributors

-   [@&#8203;AlessioDP](https://redirect.github.com/AlessioDP) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2298](https://redirect.github.com/gpbl/react-day-picker/pull/2298)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.3...v9.0.4

### [`v9.0.3`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.3)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.2...v9.0.3)

This release fixes two issues found with the grid style and the range mode.

#### What's Changed

-   fix: alignment of grid elements by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2294](https://redirect.github.com/gpbl/react-day-picker/pull/2294)
-   fix: range mode not updating when selected prop changes by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2295](https://redirect.github.com/gpbl/react-day-picker/pull/2295)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.2...v9.0.3

### [`v9.0.2`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.2)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.1...v9.0.2)

This update improves backward compatibility with v8.10.1 for range selection mode.

#### What's Changed

-   feat: add `excludeDisabled` prop for range mode by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2290](https://redirect.github.com/gpbl/react-day-picker/pull/2290)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.1...v9.0.2

### [`v9.0.1`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.1)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v9.0.0...v9.0.1)

This update improves backward compatibility with v8.10.1.

#### What's Changed

-   fix: prop types not being correctly interpreted by TS by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2283](https://redirect.github.com/gpbl/react-day-picker/pull/2283)
-   feat: add `DeprecatedUI` enum by [@&#8203;gpbl](https://redirect.github.com/gpbl) in [https://github.com/gpbl/react-day-picker/pull/2284](https://redirect.github.com/gpbl/react-day-picker/pull/2284)

**Full Changelog**: https://github.com/gpbl/react-day-picker/compare/v9.0.0...v9.0.1

### [`v9.0.0`](https://redirect.github.com/gpbl/react-day-picker/releases/tag/v9.0.0)

[Compare Source](https://redirect.github.com/gpbl/react-day-picker/compare/v8.10.1...v9.0.0)

DayPicker v9 is a major release including significant updates related to accessibility, customization and localization.

-   See the updated docs at https://daypicker.dev and the [upgrading Guide](https://daypicker.dev/upgrading) for more details.

##### Install the Latest Version

```bash
npm install react-day-picker@latest
```

#### What’s New

-   Moved `date-fns` from peer dependencies to dependencies.
-   Added support for [UTC dates](https://daypicker.dev/docs/localization#utc-dates) and [Jalali Calendar](https://daypicker.dev/docs/localization#jalali-calendar).
-   [Enhanced accessibility](https://daypicker.dev/docs/accessibility) to better comply with [WCAG 2.1](https://www.w3.org/TR/WCAG21/) recommendations.
-   [Simplified styles](https://daypicker.dev/docs/styling) and new CSS variables for easier customization.
-   Improved selection logic for [range mode](https://daypicker.dev/docs/selection-modes.mdx).
-   New `dropdown-years` and `dropdown-months` caption layouts.
-   New `hideWeekdayRow` and `hideNavigation` props.
-   Updated for a complete [custom components](https://daypicker.dev/guides/custom-components) support.
-   Improved typings and props for better compatibility in TypeScript `strict` mode.

#### Breaking Changes

While we tried to keep the API as stable as possible, some breaking changes were necessary to improve the library:

-   The updated ARIA labels could require new translations or updated unit tests selectors.
-   Custom CSS styles will likely break, due to the updated CSS classes and simplified styles.
-   Custom Components have new API and may break.
-   Some typings have been renamed or deprecated.
-   The `useInput` hook has been removed. See [Input fields](https://daypicker.dev/guides/input-fields) guide for more details.
-   `onWeekNumberClick` has been removed. Use a custom component to handle week number clicks.
-   The updated build system to ESM and CommonJS could break some custom bundler.

##### Upgrading Guide

We prepared a [Upgrading guide](https://daypicker.dev/upgrading) for help upgrading your app to v9. We welcome [feedback](https://redirect.github.com/gpbl/react-day-picker/discussions) about the upgrade process, to ensure it's smooth for everyone.

#### Compatibility

DayPicker v9 is compatible with React 16.8+.

#### Get Support and Report Issues

Get support, report issues, and provide feedback on the [Discussion forums](https://redirect.github.com/gpbl/react-day-picker/discussions). Thanks.

#### New Contributors

-   [@&#8203;grzegorzpokorski](https://redirect.github.com/grzegorzpokorski) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2124](https://redirect.github.com/gpbl/react-day-picker/pull/2124)
-   [@&#8203;zaaakher](https://redirect.github.com/zaaakher) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2137](https://redirect.github.com/gpbl/react-day-picker/pull/2137)
-   [@&#8203;ArthurGoupil](https://redirect.github.com/ArthurGoupil) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2230](https://redirect.github.com/gpbl/react-day-picker/pull/2230)
-   [@&#8203;johnnysedh3lllo](https://redirect.github.com/johnnysedh3lllo) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2252](https://redirect.github.com/gpbl/react-day-picker/pull/2252)
-   [@&#8203;xardit](https://redirect.github.com/xardit) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2254](https://redirect.github.com/gpbl/react-day-picker/pull/2254)
-   [@&#8203;dave-meyer](https://redirect.github.com/dave-meyer) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2231](https://redirect.github.com/gpbl/react-day-picker/pull/2231)
-   [@&#8203;benasher44](https://redirect.github.com/benasher44) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2249](https://redirect.github.com/gpbl/react-day-picker/pull/2249)
-   [@&#8203;RyanCavanaugh](https://redirect.github.com/RyanCavanaugh) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2275](https://redirect.github.com/gpbl/react-day-picker/pull/2275)
-   [@&#8203;kesoji](https://redirect.github.com/kesoji) made their first contribution in [https://github.com/gpbl/react-day-picker/pull/2281](https://redirect.github.com/gpbl/react-day-picker/pull/2281)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzEuNCIsInVwZGF0ZWRJblZlciI6IjM4LjU5LjIiLCJ0YXJnZXRCcmFuY2giOiJjYW5hcnkiLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->
2024-09-03 10:28:42 +00:00
renovate
106f332c19 chore: bump up vitest monorepo to v2 (major) (#7449)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@vitest/coverage-istanbul](https://togithub.com/vitest-dev/vitest/tree/main/packages/coverage-istanbul#readme) ([source](https://togithub.com/vitest-dev/vitest/tree/HEAD/packages/coverage-istanbul)) | [`1.6.0` -> `2.0.5`](https://renovatebot.com/diffs/npm/@vitest%2fcoverage-istanbul/1.6.0/2.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vitest%2fcoverage-istanbul/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vitest%2fcoverage-istanbul/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vitest%2fcoverage-istanbul/1.6.0/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vitest%2fcoverage-istanbul/1.6.0/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@vitest/ui](https://togithub.com/vitest-dev/vitest/tree/main/packages/ui#readme) ([source](https://togithub.com/vitest-dev/vitest/tree/HEAD/packages/ui)) | [`1.6.0` -> `2.0.5`](https://renovatebot.com/diffs/npm/@vitest%2fui/1.6.0/2.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vitest%2fui/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vitest%2fui/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vitest%2fui/1.6.0/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vitest%2fui/1.6.0/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [vitest](https://togithub.com/vitest-dev/vitest) ([source](https://togithub.com/vitest-dev/vitest/tree/HEAD/packages/vitest)) | [`1.6.0` -> `2.0.5`](https://renovatebot.com/diffs/npm/vitest/1.6.0/2.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vitest/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vitest/1.6.0/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/1.6.0/2.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>vitest-dev/vitest (@&#8203;vitest/coverage-istanbul)</summary>

### [`v2.0.5`](https://togithub.com/vitest-dev/vitest/releases/tag/v2.0.5)

[Compare Source](https://togithub.com/vitest-dev/vitest/compare/v2.0.4...v2.0.5)

#####    🚀 Features

-   Introduce experimental reported tasks  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6149](https://togithub.com/vitest-dev/vitest/issues/6149) [<samp>(13d85)</samp>](https://togithub.com/vitest-dev/vitest/commit/13d85bd1)
    -   This is part of the experimental API and doesn't follow semver. We are hoping to stabilize it for 2.1. If you are working with custom reporters, give this a go!

#####    🐞 Bug Fixes

-   Show a difference between string characters if both values are strings  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6191](https://togithub.com/vitest-dev/vitest/issues/6191) [<samp>(29176)</samp>](https://togithub.com/vitest-dev/vitest/commit/291766d7)
-   `testNamePattern` adds leading space  -  by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6186](https://togithub.com/vitest-dev/vitest/issues/6186) [<samp>(073a5)</samp>](https://togithub.com/vitest-dev/vitest/commit/073a50c9)
-   **browser**:
    -   Don't bundle `afterEach` cleanup hooks in node entrypoint  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6192](https://togithub.com/vitest-dev/vitest/issues/6192) [<samp>(e6fbc)</samp>](https://togithub.com/vitest-dev/vitest/commit/e6fbc620)
    -   UserEvent.setup initiates a separate state for userEvent instance  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6088](https://togithub.com/vitest-dev/vitest/issues/6088) [<samp>(883f3)</samp>](https://togithub.com/vitest-dev/vitest/commit/883f3482)
    -   Correctly import optimized module in vi.importActual  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6219](https://togithub.com/vitest-dev/vitest/issues/6219) [<samp>(804ff)</samp>](https://togithub.com/vitest-dev/vitest/commit/804ff2fd)
    -   Passing options to hover/unhover  -  by [@&#8203;MNeverOff](https://togithub.com/MNeverOff) in [https://github.com/vitest-dev/vitest/issues/6175](https://togithub.com/vitest-dev/vitest/issues/6175) [<samp>(d4c00)</samp>](https://togithub.com/vitest-dev/vitest/commit/d4c005bc)
    -   Improve unique CSS selector generation  -  by [@&#8203;zacharyvoase](https://togithub.com/zacharyvoase) and **Zack Voase** in [https://github.com/vitest-dev/vitest/issues/6243](https://togithub.com/vitest-dev/vitest/issues/6243) [<samp>(e7acd)</samp>](https://togithub.com/vitest-dev/vitest/commit/e7acd0cf)
-   **vitest**:
    -   Remove nuxt from auto inline deps  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(93882)</samp>](https://togithub.com/vitest-dev/vitest/commit/93882f38)
    -   Improve `defineProject` and `defineWorkspace` types  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6198](https://togithub.com/vitest-dev/vitest/issues/6198) [<samp>(8cd82)</samp>](https://togithub.com/vitest-dev/vitest/commit/8cd8272b)
    -   Correctly resolve mocked `node:*` imports in `__mocks__` folder  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6204](https://togithub.com/vitest-dev/vitest/issues/6204) [<samp>(a48be)</samp>](https://togithub.com/vitest-dev/vitest/commit/a48be6ff)
-   **web-worker**:
    -   Expose globals on self  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6170](https://togithub.com/vitest-dev/vitest/issues/6170) [<samp>(12bb5)</samp>](https://togithub.com/vitest-dev/vitest/commit/12bb567e)

#####     [View changes on GitHub](https://togithub.com/vitest-dev/vitest/compare/v2.0.4...v2.0.5)

### [`v2.0.4`](https://togithub.com/vitest-dev/vitest/releases/tag/v2.0.4)

[Compare Source](https://togithub.com/vitest-dev/vitest/compare/v2.0.3...v2.0.4)

#####    🐞 Bug Fixes

-   One-line environment options  -  by [@&#8203;hahanein](https://togithub.com/hahanein) in [https://github.com/vitest-dev/vitest/issues/5105](https://togithub.com/vitest-dev/vitest/issues/5105) [<samp>(38269)</samp>](https://togithub.com/vitest-dev/vitest/commit/38269415)
-   Resolve assets imported with `require`  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6159](https://togithub.com/vitest-dev/vitest/issues/6159) [<samp>(807a2)</samp>](https://togithub.com/vitest-dev/vitest/commit/807a2cbc)
-   **browser**:
    -   Don't panic if [@&#8203;vitest/browser](https://togithub.com/vitest/browser) is installed outside of project root  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6135](https://togithub.com/vitest-dev/vitest/issues/6135) [<samp>(ccfcd)</samp>](https://togithub.com/vitest-dev/vitest/commit/ccfcd488)
    -   Set global filepath  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6190](https://togithub.com/vitest-dev/vitest/issues/6190) [<samp>(0d0b4)</samp>](https://togithub.com/vitest-dev/vitest/commit/0d0b46b1)
    -   Allow preview and open in the editor screenshot error from ui  -  by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/6113](https://togithub.com/vitest-dev/vitest/issues/6113) [<samp>(2d620)</samp>](https://togithub.com/vitest-dev/vitest/commit/2d62051f)
-   **coverage**:
    -   Global thresholds to include files from glob thresholds  -  by [@&#8203;thor-juhasz](https://togithub.com/thor-juhasz) and [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6172](https://togithub.com/vitest-dev/vitest/issues/6172) [<samp>(02e3f)</samp>](https://togithub.com/vitest-dev/vitest/commit/02e3f003)
    -   Consistent type-only file handling  -  by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6183](https://togithub.com/vitest-dev/vitest/issues/6183) [<samp>(90576)</samp>](https://togithub.com/vitest-dev/vitest/commit/90576148)
    -   Ignore `*.cts` files  -  by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6189](https://togithub.com/vitest-dev/vitest/issues/6189) [<samp>(5da45)</samp>](https://togithub.com/vitest-dev/vitest/commit/5da45db1)
    -   Add `thresholds.<glob>.100` option  -  by [@&#8203;thor-juhasz](https://togithub.com/thor-juhasz) and [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6174](https://togithub.com/vitest-dev/vitest/issues/6174) [<samp>(f6845)</samp>](https://togithub.com/vitest-dev/vitest/commit/f68453f8)
-   **spy**:
    -   Fix `mockImplementation` for function overload and unions  -  by [@&#8203;hi-ogawa](https://togithub.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/6181](https://togithub.com/vitest-dev/vitest/issues/6181) [<samp>(7a75b)</samp>](https://togithub.com/vitest-dev/vitest/commit/7a75bd4c)

#####     [View changes on GitHub](https://togithub.com/vitest-dev/vitest/compare/v2.0.3...v2.0.4)

### [`v2.0.3`](https://togithub.com/vitest-dev/vitest/releases/tag/v2.0.3)

[Compare Source](https://togithub.com/vitest-dev/vitest/compare/v2.0.2...v2.0.3)

#####    🚀 Features

-   **ui**: Show all suites/tests when parent matches  -  by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/6106](https://togithub.com/vitest-dev/vitest/issues/6106) [<samp>(840e0)</samp>](https://togithub.com/vitest-dev/vitest/commit/840e02f1)

#####    🐞 Bug Fixes

-   `--inspect-brk` stop on Windows  -  by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6110](https://togithub.com/vitest-dev/vitest/issues/6110) [<samp>(f8519)</samp>](https://togithub.com/vitest-dev/vitest/commit/f851982e)
-   **browser**:
    -   Don't import from "vite"  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(35655)</samp>](https://togithub.com/vitest-dev/vitest/commit/35655419)
    -   Allow immidiate reinvalidation of mocked dependencies  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6108](https://togithub.com/vitest-dev/vitest/issues/6108) [<samp>(f44cc)</samp>](https://togithub.com/vitest-dev/vitest/commit/f44cc917)
-   **spy**:
    -   Fix type error when assigning `vi.spyOn` to `MockInstance` of function overload  -  by [@&#8203;hi-ogawa](https://togithub.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/6086](https://togithub.com/vitest-dev/vitest/issues/6086) [<samp>(e9f9a)</samp>](https://togithub.com/vitest-dev/vitest/commit/e9f9adcd)
-   **vite-node**:
    -   Remove suffix slash on file protocol for window  -  by [@&#8203;syi0808](https://togithub.com/syi0808) in [https://github.com/vitest-dev/vitest/issues/6109](https://togithub.com/vitest-dev/vitest/issues/6109) [<samp>(93ebd)</samp>](https://togithub.com/vitest-dev/vitest/commit/93ebdefc)

#####     [View changes on GitHub](https://togithub.com/vitest-dev/vitest/compare/v2.0.2...v2.0.3)

### [`v2.0.2`](https://togithub.com/vitest-dev/vitest/releases/tag/v2.0.2)

[Compare Source](https://togithub.com/vitest-dev/vitest/compare/v2.0.1...v2.0.2)

#####    🐞 Bug Fixes

-   **browser**:
    -   Remove [@&#8203;vitest/runner](https://togithub.com/vitest/runner) > pretty-format from prebundling because it doesn't exist  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6075](https://togithub.com/vitest-dev/vitest/issues/6075) [<samp>(a169d)</samp>](https://togithub.com/vitest-dev/vitest/commit/a169d25a)
    -   Inline pretty-format and replace picocolors with tinyrainbow  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6077](https://togithub.com/vitest-dev/vitest/issues/6077) [<samp>(80a43)</samp>](https://togithub.com/vitest-dev/vitest/commit/80a43d5c)
    -   Remove `crypto.randomUUID` from the client  -  by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/6079](https://togithub.com/vitest-dev/vitest/issues/6079) [<samp>(04c83)</samp>](https://togithub.com/vitest-dev/vitest/commit/04c83acc)
    -   Correctly overwrite loupe require  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(756ac)</samp>](https://togithub.com/vitest-dev/vitest/commit/756ac2bc)
    -   Dedupe @&#8203;vitest/browser/client  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6081](https://togithub.com/vitest-dev/vitest/issues/6081) [<samp>(ee725)</samp>](https://togithub.com/vitest-dev/vitest/commit/ee725184)
    -   Don't release keyboard automatically  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6083](https://togithub.com/vitest-dev/vitest/issues/6083) [<samp>(58fac)</samp>](https://togithub.com/vitest-dev/vitest/commit/58fac77b)
-   **ui**:
    -   Test files notified only when running  -  by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/6069](https://togithub.com/vitest-dev/vitest/issues/6069) [<samp>(af7fe)</samp>](https://togithub.com/vitest-dev/vitest/commit/af7fec58)
    -   Encode html entities in task name  -  by [@&#8203;userquin](https://togithub.com/userquin) and [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6070](https://togithub.com/vitest-dev/vitest/issues/6070) [<samp>(7f0cc)</samp>](https://togithub.com/vitest-dev/vitest/commit/7f0cc24e)
-   **web-worker**:
    -   Peer dependency version on `vitest`  -  by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6060](https://togithub.com/vitest-dev/vitest/issues/6060) [<samp>(95a2d)</samp>](https://togithub.com/vitest-dev/vitest/commit/95a2d870)

#####    🏎 Performance

-   **browser**: Don't import msw if no modules are mocked  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6073](https://togithub.com/vitest-dev/vitest/issues/6073) [<samp>(aa527)</samp>](https://togithub.com/vitest-dev/vitest/commit/aa52792a)

#####     [View changes on GitHub](https://togithub.com/vitest-dev/vitest/compare/v2.0.1...v2.0.2)

### [`v2.0.1`](https://togithub.com/vitest-dev/vitest/releases/tag/v2.0.1)

[Compare Source](https://togithub.com/vitest-dev/vitest/compare/v2.0.0...v2.0.1)

#####    🐞 Bug Fixes

-   **browser**: Correctly inherit browser config in a workspace  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6054](https://togithub.com/vitest-dev/vitest/issues/6054) [<samp>(4b03e)</samp>](https://togithub.com/vitest-dev/vitest/commit/4b03e72b)
-   **ui**: Move virtual scroller to dev dependencies  -  by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/6053](https://togithub.com/vitest-dev/vitest/issues/6053) [<samp>(f94ed)</samp>](https://togithub.com/vitest-dev/vitest/commit/f94ede02)
-   **vitest**: Print only running files, not every file  -  by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6052](https://togithub.com/vitest-dev/vitest/issues/6052) [<samp>(4d559)</samp>](https://togithub.com/vitest-dev/vitest/commit/4d5597df)

#####     [View changes on GitHub](https://togithub.com/vitest-dev/vitest/compare/v2.0.0...v2.0.1)

### [`v2.0.0`](https://togithub.com/vitest-dev/vitest/releases/tag/v2.0.0)

[Compare Source](https://togithub.com/vitest-dev/vitest/compare/v1.6.0...v2.0.0)

Vitest 2.0 is here! This release page lists all changes made to the project during the beta. For the migration guide, please refer to the [documentation](https://vitest.dev/guide/migration.html#migrating-to-vitest-2-0).

##### 🚨 Breaking Changes

-   Simplify mock function generic types and align with jest - by **[@&#8203;hi-ogawa](https://togithub.com/hi-ogawa)** in [https://github.com/vitest-dev/vitest/pull/4784](https://togithub.com/vitest-dev/vitest/pull/4784) [<samp>(a0c1d37)</samp>](a0c1d371ed)
-   Remove `--segfault-retry` - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5514](https://togithub.com/vitest-dev/vitest/issues/5514) [<samp>(ed60e)</samp>](https://togithub.com/vitest-dev/vitest/commit/ed60e405e)
    -   This flag was introduced to combat `threads` segfaults. Our current recommendation is to use the new default `forks` pool instead.
-   Run suite hooks in a stack - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5609](https://togithub.com/vitest-dev/vitest/issues/5609) [<samp>(1277d)</samp>](https://togithub.com/vitest-dev/vitest/commit/1277dc1e3)
    -   This feels like a more sensible default. Especially with the new [`onTestFinished`](https://vitest.dev/api/#ontestfinished) hook. This can make your tests run a little bit slower.
-   Enable `coverage.ignoreEmptyLines` by default - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5543](https://togithub.com/vitest-dev/vitest/issues/5543) [<samp>(31994)</samp>](https://togithub.com/vitest-dev/vitest/commit/31994942f)
    -   ⚠️ This change may cause significant differences in your coverage results compared to Vitest v1. These changes are expected as coverage reporting is now more accurate. See [https://github.com/vitest-dev/vitest/issues/5423](https://togithub.com/vitest-dev/vitest/issues/5423) for more details.
-   Add correct location and snapshot fields in json reporter - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5434](https://togithub.com/vitest-dev/vitest/issues/5434) [<samp>(bcccc)</samp>](https://togithub.com/vitest-dev/vitest/commit/bcccce6df)
    -   Previously, the `location` field pointed to the error location instead of the test location. Now it is aligned with jest and contains the `line` and `column` of a test function, but requires [`includeTaskLocation`](https://vitest.dev/config/#includeTaskLocation) to be enabled.
-   Update dependency chai to v5 - by **renovate\[bot]** and [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5135](https://togithub.com/vitest-dev/vitest/issues/5135) [<samp>(73646)</samp>](https://togithub.com/vitest-dev/vitest/commit/73646b638)
-   Remove watchExclude - by [@&#8203;patak-dev](https://togithub.com/patak-dev) in [https://github.com/vitest-dev/vitest/issues/5177](https://togithub.com/vitest-dev/vitest/issues/5177) [<samp>(d7371)</samp>](https://togithub.com/vitest-dev/vitest/commit/d7371eae3)
-   Change default `pool` to `'forks'` - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5047](https://togithub.com/vitest-dev/vitest/issues/5047) [<samp>(7f8f9)</samp>](https://togithub.com/vitest-dev/vitest/commit/7f8f9c0c0)
    -   This change is done for compatibility issues
    -   This pool may be slightly slower than previous `threads` pool: https://vitest.dev/guide/improving-performance.html#pool
-   `--merge-reports` to support coverage - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5736](https://togithub.com/vitest-dev/vitest/issues/5736) [<samp>(b7438)</samp>](https://togithub.com/vitest-dev/vitest/commit/b7438b9be)
-   Add promise-based return assertions, do not auto-resolve returned promises - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5749](https://togithub.com/vitest-dev/vitest/issues/5749) [<samp>(5f710)</samp>](https://togithub.com/vitest-dev/vitest/commit/5f710182e)
    -   ⚠️ Vitest no longer unwraps promises in `spy.mock.returns`. If the function is async or returns a promise, it will always succeed and have a `Promise` in `results`. To make migration easier, we introduced `spy.mock.settledResults` that unwraps promises and `expect().toHaveResolved()` matcher that accepts unwrapped value.
-   Do not exit process if global setup has failed - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5726](https://togithub.com/vitest-dev/vitest/issues/5726) [<samp>(ddb09)</samp>](https://togithub.com/vitest-dev/vitest/commit/ddb09eb12)
-   Don't exit process if config failed - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5715](https://togithub.com/vitest-dev/vitest/issues/5715) [<samp>(f232f)</samp>](https://togithub.com/vitest-dev/vitest/commit/f232fdd61)
-   Add meta to `json` output - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5802](https://togithub.com/vitest-dev/vitest/issues/5802) [<samp>(dd754)</samp>](https://togithub.com/vitest-dev/vitest/commit/dd754c103)
-   Rename `indexScripts` to `orchestratorScripts` in the browser config - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5842](https://togithub.com/vitest-dev/vitest/issues/5842) [<samp>(49f34)</samp>](https://togithub.com/vitest-dev/vitest/commit/49f34ec47)
-   Add "vitest list" API to print collected tests without running them - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6013](https://togithub.com/vitest-dev/vitest/issues/6013) [<samp>(583dd)</samp>](https://togithub.com/vitest-dev/vitest/commit/583dd8a98)
    -   ⚠️ This changes the custom `pool` API - now requires `collectTests` method alongside `runTests`.
-   Remove the empty suite from the runner - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5435](https://togithub.com/vitest-dev/vitest/issues/5435) [<samp>(dbbbe)</samp>](https://togithub.com/vitest-dev/vitest/commit/dbbbe4304)
-   Support concurrent suites - by **[@&#8203;hi-ogawa](https://togithub.com/hi-ogawa)** in [https://github.com/vitest-dev/vitest/pull/5491](https://togithub.com/vitest-dev/vitest/pull/5491) [<samp>(222ce44)</samp>](222ce44119)
-   Support overriding `exclude` in coverage - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5997](https://togithub.com/vitest-dev/vitest/issues/5997) [<samp>(169bc)</samp>](https://togithub.com/vitest-dev/vitest/commit/169bc1fde)
    -   ⚠️ Vitest coverage no longer adds test files to `exclude` patterns if `coverage.exclude` was overridden in the config. Add your test patterns manually, or merge your overrides with default ones: `['**/my-pattern.js', ...coverageConfigDefaults.exclude]`. See https://vitest.dev/config/#coverage-exclude for an example.

##### 🚀 Features

<img width="1392" alt="Running tresjs example in Vitest BrowserMode" src="https://github.com/vitest-dev/vitest/assets/16173870/3b6bc721-b194-416d-a685-cf7282ee802a">

-   **browser**:
    -   🌐 This release lays the groundwork for the next iteration of Vitest Browser Mode. You can read more about our future plans at [https://github.com/vitest-dev/vitest/discussions/5828](https://togithub.com/vitest-dev/vitest/discussions/5828)
    -   Add commands to communicate betweens server and the browser - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5097](https://togithub.com/vitest-dev/vitest/issues/5097) [<samp>(aa431)</samp>](https://togithub.com/vitest-dev/vitest/commit/aa431f4db)
    -   Do not reload the page during watch mode - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5810](https://togithub.com/vitest-dev/vitest/issues/5810) [<samp>(e5b9a)</samp>](https://togithub.com/vitest-dev/vitest/commit/e5b9a0be4)
    -   Support changing the viewport - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5811](https://togithub.com/vitest-dev/vitest/issues/5811) [<samp>(71851)</samp>](https://togithub.com/vitest-dev/vitest/commit/718512d80)
    -   Add browser iframe mouse interaction - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5815](https://togithub.com/vitest-dev/vitest/issues/5815) [<samp>(f29b9)</samp>](https://togithub.com/vitest-dev/vitest/commit/f29b9d408)
    -   Support `click` event - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5777](https://togithub.com/vitest-dev/vitest/issues/5777) [<samp>(839c3)</samp>](https://togithub.com/vitest-dev/vitest/commit/839c39f06)
    -   Rename none provider to preview, make it default - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5826](https://togithub.com/vitest-dev/vitest/issues/5826) [<samp>(18310)</samp>](https://togithub.com/vitest-dev/vitest/commit/1831008b1)
    -   Run tests in parallel in headless mode, add `page.screenshot` method - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5853](https://togithub.com/vitest-dev/vitest/issues/5853) [<samp>(81c42)</samp>](https://togithub.com/vitest-dev/vitest/commit/81c42fc8a)
    -   Implement several `userEvent` methods, add `fill` and `dragAndDrop` events - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5882](https://togithub.com/vitest-dev/vitest/issues/5882) [<samp>(4dbea)</samp>](https://togithub.com/vitest-dev/vitest/commit/4dbea4aed)
    -   Introduce `expect.dom` method and bundle `jest-dom` matchers with `@vitest/browser` - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5910](https://togithub.com/vitest-dev/vitest/issues/5910) [<samp>(3a96a)</samp>](https://togithub.com/vitest-dev/vitest/commit/3a96a3d0e)
    -   Expose CDP in the browser - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5938](https://togithub.com/vitest-dev/vitest/issues/5938) [<samp>(bec43)</samp>](https://togithub.com/vitest-dev/vitest/commit/bec434cb6)
    -   Add "init" command for browser tests - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5960](https://togithub.com/vitest-dev/vitest/issues/5960) [<samp>(49e97)</samp>](https://togithub.com/vitest-dev/vitest/commit/49e973cb9)
    -   Add an option to take screenshots if the browser test fails - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5975](https://togithub.com/vitest-dev/vitest/issues/5975) [<samp>(154cb)</samp>](https://togithub.com/vitest-dev/vitest/commit/154cb22de)
    -   Add `tripleClick` to interactive api - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5987](https://togithub.com/vitest-dev/vitest/issues/5987) [<samp>(200a4)</samp>](https://togithub.com/vitest-dev/vitest/commit/200a4349a)
    -   Playwright provider doesn't allow resizing the browser viewport - by [@&#8203;userquin](https://togithub.com/userquin) and [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5984](https://togithub.com/vitest-dev/vitest/issues/5984) [<samp>(ff978)</samp>](https://togithub.com/vitest-dev/vitest/commit/ff978e58d)
-   Pretty print diffs coming from cause - by [@&#8203;dubzzz](https://togithub.com/dubzzz) in [https://github.com/vitest-dev/vitest/issues/5660](https://togithub.com/vitest-dev/vitest/issues/5660) [<samp>(6faf8)</samp>](https://togithub.com/vitest-dev/vitest/commit/6faf8f84b)
-   Allow import statement as vi.mock path for better IDE support - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5690](https://togithub.com/vitest-dev/vitest/issues/5690) [<samp>(a99a1)</samp>](https://togithub.com/vitest-dev/vitest/commit/a99a14c1c)
-   Remove deprecated options - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5696](https://togithub.com/vitest-dev/vitest/issues/5696) [<samp>(5c308)</samp>](https://togithub.com/vitest-dev/vitest/commit/5c308edc6)
-   Add blob reporter - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5663](https://togithub.com/vitest-dev/vitest/issues/5663) [<samp>(e2053)</samp>](https://togithub.com/vitest-dev/vitest/commit/e20538a36)
    -    Run Vitest in separate processes with `--reporter=blob` flag to generate reports and combine them with `vitest --merge-reports` later!
-   Add expect.poll utility - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5708](https://togithub.com/vitest-dev/vitest/issues/5708) [<samp>(e2e0f)</samp>](https://togithub.com/vitest-dev/vitest/commit/e2e0ff46a)
-   Add browser.ui option - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5771](https://togithub.com/vitest-dev/vitest/issues/5771) [<samp>(a5033)</samp>](https://togithub.com/vitest-dev/vitest/commit/a50330eea)
-   Add median to `--output-json` - by [@&#8203;Joristdh](https://togithub.com/Joristdh) in [https://github.com/vitest-dev/vitest/issues/5745](https://togithub.com/vitest-dev/vitest/issues/5745) [<samp>(0766b)</samp>](https://togithub.com/vitest-dev/vitest/commit/0766b7f72)
-   Allow augmenting config.test.env - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5784](https://togithub.com/vitest-dev/vitest/issues/5784) [<samp>(b2469)</samp>](https://togithub.com/vitest-dev/vitest/commit/b24691efd)
-   Implement module mocking in browser mode - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5765](https://togithub.com/vitest-dev/vitest/issues/5765) [<samp>(7b2f6)</samp>](https://togithub.com/vitest-dev/vitest/commit/7b2f64cfa)
-   Allow configuring expect options in the config - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5729](https://togithub.com/vitest-dev/vitest/issues/5729) [<samp>(fc53f)</samp>](https://togithub.com/vitest-dev/vitest/commit/fc53f5634)
-   Add an option to print console stack trace - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5720](https://togithub.com/vitest-dev/vitest/issues/5720) [<samp>(e4fe6)</samp>](https://togithub.com/vitest-dev/vitest/commit/e4fe6f51a)
-   Add browser frame to UI - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5808](https://togithub.com/vitest-dev/vitest/issues/5808) [<samp>(3796d)</samp>](https://togithub.com/vitest-dev/vitest/commit/3796dd7e0)
-   Image type add bmp - by **btea** in [https://github.com/vitest-dev/vitest/issues/5921](https://togithub.com/vitest-dev/vitest/issues/5921) [<samp>(98f9b)</samp>](https://togithub.com/vitest-dev/vitest/commit/98f9b7ab9)
-   Add an option to return base64 from page.screenshot - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5993](https://togithub.com/vitest-dev/vitest/issues/5993) [<samp>(be323)</samp>](https://togithub.com/vitest-dev/vitest/commit/be3231763)
-   Expose `parseAst`, `parseAstAsync` from vite - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(f645e)</samp>](https://togithub.com/vitest-dev/vitest/commit/f645e48c5)
-   **config**:
    -   Allow percentage value for workers option - by [@&#8203;syi0808](https://togithub.com/syi0808) in [https://github.com/vitest-dev/vitest/issues/5982](https://togithub.com/vitest-dev/vitest/issues/5982) [<samp>(b1a27)</samp>](https://togithub.com/vitest-dev/vitest/commit/b1a27d404)
-   **runner**:
    -   Implement `test.for` - by [@&#8203;hi-ogawa](https://togithub.com/hi-ogawa) and [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5861](https://togithub.com/vitest-dev/vitest/issues/5861) [<samp>(c2380)</samp>](https://togithub.com/vitest-dev/vitest/commit/c238072fd)
-   **spy**:
    -   Collect mock.contexts - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5955](https://togithub.com/vitest-dev/vitest/issues/5955) [<samp>(3b31a)</samp>](https://togithub.com/vitest-dev/vitest/commit/3b31a56d5)
-   **ui**:
    -   Render tests in a tree - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5807](https://togithub.com/vitest-dev/vitest/issues/5807) [<samp>(7900f)</samp>](https://togithub.com/vitest-dev/vitest/commit/7900f9f89)
    -   Load module graph on tab selection - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5844](https://togithub.com/vitest-dev/vitest/issues/5844) [<samp>(b117e)</samp>](https://togithub.com/vitest-dev/vitest/commit/b117e8756)
    -   Replace navigation tree with test explorer - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5907](https://togithub.com/vitest-dev/vitest/issues/5907) [<samp>(45dfc)</samp>](https://togithub.com/vitest-dev/vitest/commit/45dfc95ae)
    -   Add initializing explorer logic - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5941](https://togithub.com/vitest-dev/vitest/issues/5941) [<samp>(c31c4)</samp>](https://togithub.com/vitest-dev/vitest/commit/c31c41c72)
    -   Add action to explorer item to show the test/suite line in the source code tab - by [@&#8203;userquin](https://togithub.com/userquin) and **Anjorin Damilare** in [https://github.com/vitest-dev/vitest/issues/5948](https://togithub.com/vitest-dev/vitest/issues/5948) [<samp>(7ec29)</samp>](https://togithub.com/vitest-dev/vitest/commit/7ec298eb3)
-   **ws-client**:
    -   Allow change reactive for state, filesMap and idMap - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5906](https://togithub.com/vitest-dev/vitest/issues/5906) [<samp>(e6020)</samp>](https://togithub.com/vitest-dev/vitest/commit/e6020b9c2)

##### 🐞 Bug Fixes

-   Print console statements in vmThreads - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5678](https://togithub.com/vitest-dev/vitest/issues/5678) [<samp>(34a80)</samp>](https://togithub.com/vitest-dev/vitest/commit/34a80b392)
-   Repeatable `--exclude` option - by [@&#8203;fregante](https://togithub.com/fregante) in [https://github.com/vitest-dev/vitest/issues/5782](https://togithub.com/vitest-dev/vitest/issues/5782) [<samp>(d6700)</samp>](https://togithub.com/vitest-dev/vitest/commit/d6700bbd8)
-   Remove browser.fileParallelism - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5790](https://togithub.com/vitest-dev/vitest/issues/5790) [<samp>(b881e)</samp>](https://togithub.com/vitest-dev/vitest/commit/b881e88b2)
-   Install UI icons - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(b84f1)</samp>](https://togithub.com/vitest-dev/vitest/commit/b84f1721d)
-   Remove process.exit if workspace project failed to be created - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5804](https://togithub.com/vitest-dev/vitest/issues/5804) [<samp>(a820e)</samp>](https://togithub.com/vitest-dev/vitest/commit/a820e7ac6)
-   Vi.waitFor/vi.waitUntil interval is now cleared after it times out - by [@&#8203;pedro00dk](https://togithub.com/pedro00dk) in [https://github.com/vitest-dev/vitest/issues/5875](https://togithub.com/vitest-dev/vitest/issues/5875) [<samp>(04107)</samp>](https://togithub.com/vitest-dev/vitest/commit/041076e7c)
-   ToJSON recursive error serialization - by [@&#8203;eddienubes](https://togithub.com/eddienubes) in [https://github.com/vitest-dev/vitest/issues/5848](https://togithub.com/vitest-dev/vitest/issues/5848) and [https://github.com/vitest-dev/vitest/issues/5884](https://togithub.com/vitest-dev/vitest/issues/5884) [<samp>(8d55d)</samp>](https://togithub.com/vitest-dev/vitest/commit/8d55d6bd4)
-   Print error properties only in verbose reporter - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5917](https://togithub.com/vitest-dev/vitest/issues/5917) [<samp>(2bd8d)</samp>](https://togithub.com/vitest-dev/vitest/commit/2bd8d9d6f)
-   Use TTY reporter when running in Deno - by [@&#8203;marvinhagemeister](https://togithub.com/marvinhagemeister) in [https://github.com/vitest-dev/vitest/issues/5972](https://togithub.com/vitest-dev/vitest/issues/5972) [<samp>(e0f45)</samp>](https://togithub.com/vitest-dev/vitest/commit/e0f45cb57)
-   Don't override uppercase - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(caef4)</samp>](https://togithub.com/vitest-dev/vitest/commit/caef40a0b)
-   Clear screen and scrollback on iTerm2 - by [@&#8203;kxalex](https://togithub.com/kxalex) in [https://github.com/vitest-dev/vitest/issues/5978](https://togithub.com/vitest-dev/vitest/issues/5978) [<samp>(d7f23)</samp>](https://togithub.com/vitest-dev/vitest/commit/d7f23d08c)
-   Include pretty-format in [@&#8203;vitest/runner](https://togithub.com/vitest/runner) for optimization on npm - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(42bd4)</samp>](https://togithub.com/vitest-dev/vitest/commit/42bd4a259)
-   Transpile esnext to node18 to support newest JS and TS features - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/4409](https://togithub.com/vitest-dev/vitest/issues/4409) [<samp>(8f65a)</samp>](https://togithub.com/vitest-dev/vitest/commit/8f65ae906)
-   **api**:
    -   Correct `project.provide` type - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5959](https://togithub.com/vitest-dev/vitest/issues/5959) [<samp>(0eda9)</samp>](https://togithub.com/vitest-dev/vitest/commit/0eda99de9)
    -   Don't call process.exit manually - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5926](https://togithub.com/vitest-dev/vitest/issues/5926) [<samp>(e9b63)</samp>](https://togithub.com/vitest-dev/vitest/commit/e9b638d40)
-   **browser**:
    -   Display UI - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(d41e4)</samp>](https://togithub.com/vitest-dev/vitest/commit/d41e46a81)
    -   Browser actions icons colors - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5816](https://togithub.com/vitest-dev/vitest/issues/5816) [<samp>(f9d9b)</samp>](https://togithub.com/vitest-dev/vitest/commit/f9d9b3bef)
    -   Restore the original viewport when unselecting the preset viewport - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5821](https://togithub.com/vitest-dev/vitest/issues/5821) [<samp>(5ebb3)</samp>](https://togithub.com/vitest-dev/vitest/commit/5ebb3abf5)
    -   Don't get stuck after the manual page refresh - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(2220b)</samp>](https://togithub.com/vitest-dev/vitest/commit/2220bb3fe)
    -   Use iframe id instead of calculating it from filenames - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5823](https://togithub.com/vitest-dev/vitest/issues/5823) [<samp>(34a31)</samp>](https://togithub.com/vitest-dev/vitest/commit/34a310da1)
    -   Always clean up iframes on rerun - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5827](https://togithub.com/vitest-dev/vitest/issues/5827) [<samp>(087fa)</samp>](https://togithub.com/vitest-dev/vitest/commit/087fa87c3)
    -   Support [@&#8203;testing-library/vue](https://togithub.com/testing-library/vue) in browser mode out of the box - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(76b82)</samp>](https://togithub.com/vitest-dev/vitest/commit/76b82e5b9)
    -   Print correct transformed module graph - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5833](https://togithub.com/vitest-dev/vitest/issues/5833) [<samp>(a7581)</samp>](https://togithub.com/vitest-dev/vitest/commit/a75815756)
    -   Use `preview` provider when running in StackBlitz - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5836](https://togithub.com/vitest-dev/vitest/issues/5836) [<samp>(76e13)</samp>](https://togithub.com/vitest-dev/vitest/commit/76e13587c)
    -   Specify entries for correct deps optimization - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5839](https://togithub.com/vitest-dev/vitest/issues/5839) [<samp>(c79b3)</samp>](https://togithub.com/vitest-dev/vitest/commit/c79b3f1f9)
    -   Allow iframe to load even if there is a custom CSP header - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5841](https://togithub.com/vitest-dev/vitest/issues/5841) [<samp>(caaaf)</samp>](https://togithub.com/vitest-dev/vitest/commit/caaafd903)
    -   Don't optimize Vitest dependencies - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5843](https://togithub.com/vitest-dev/vitest/issues/5843) [<samp>(f15b4)</samp>](https://togithub.com/vitest-dev/vitest/commit/f15b4e99d)
    -   Set server.open to false and move error handling after init - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5845](https://togithub.com/vitest-dev/vitest/issues/5845) [<samp>(47003)</samp>](https://togithub.com/vitest-dev/vitest/commit/470036794)
    -   Show correct prepare time - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5852](https://togithub.com/vitest-dev/vitest/issues/5852) [<samp>(52d54)</samp>](https://togithub.com/vitest-dev/vitest/commit/52d545bf9)
    -   Resolve `coverage.reporter` from string values - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5920](https://togithub.com/vitest-dev/vitest/issues/5920) [<samp>(f33da)</samp>](https://togithub.com/vitest-dev/vitest/commit/f33dabbef)
    -   Correctly update inline snapshot if changed - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5925](https://togithub.com/vitest-dev/vitest/issues/5925) [<samp>(2380c)</samp>](https://togithub.com/vitest-dev/vitest/commit/2380cb95e)
    -   Remove "util" warning - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5935](https://togithub.com/vitest-dev/vitest/issues/5935) [<samp>(48f28)</samp>](https://togithub.com/vitest-dev/vitest/commit/48f28f731)
    -   Remove hacky retry - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5971](https://togithub.com/vitest-dev/vitest/issues/5971) [<samp>(2a2c9)</samp>](https://togithub.com/vitest-dev/vitest/commit/2a2c9085a)
    -   Make userEvent more stable when running in parallel - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5974](https://togithub.com/vitest-dev/vitest/issues/5974) [<samp>(14a21)</samp>](https://togithub.com/vitest-dev/vitest/commit/14a217d53)
    -   Print screenshot path alongside the test error message - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5992](https://togithub.com/vitest-dev/vitest/issues/5992) [<samp>(15289)</samp>](https://togithub.com/vitest-dev/vitest/commit/152891b3d)
    -   Print correct stack trace in source files - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6003](https://togithub.com/vitest-dev/vitest/issues/6003) [<samp>(62aa7)</samp>](https://togithub.com/vitest-dev/vitest/commit/62aa72081)
    -   Correctly mock optimized cjs dependencies - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6035](https://togithub.com/vitest-dev/vitest/issues/6035) [<samp>(057b4)</samp>](https://togithub.com/vitest-dev/vitest/commit/057b4f34b)
    -   Support shadow root and svg elements - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6036](https://togithub.com/vitest-dev/vitest/issues/6036) [<samp>(2e3c8)</samp>](https://togithub.com/vitest-dev/vitest/commit/2e3c872ae)
-   **coverage**:
    -   Clean up empty coverage reports directory - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5731](https://togithub.com/vitest-dev/vitest/issues/5731) [<samp>(c469c)</samp>](https://togithub.com/vitest-dev/vitest/commit/c469c74d7)
    -   `thresholds.autoUpdate` to support `mergeConfig` - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5818](https://togithub.com/vitest-dev/vitest/issues/5818) [<samp>(7afb3)</samp>](https://togithub.com/vitest-dev/vitest/commit/7afb3682f)
    -   Pass thresholds errors to `stderr` of `startVitest()` - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5954](https://togithub.com/vitest-dev/vitest/issues/5954) [<samp>(70805)</samp>](https://togithub.com/vitest-dev/vitest/commit/708051319)
    -   Exclude bench files from coverage - by [@&#8203;kouak](https://togithub.com/kouak) in [https://github.com/vitest-dev/vitest/issues/5983](https://togithub.com/vitest-dev/vitest/issues/5983) [<samp>(429e1)</samp>](https://togithub.com/vitest-dev/vitest/commit/429e1a7f8)
    -   Vite to ignore dynamic import of provider - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5998](https://togithub.com/vitest-dev/vitest/issues/5998) [<samp>(6d884)</samp>](https://togithub.com/vitest-dev/vitest/commit/6d8848e86)
    -   Istanbul to support import attributes - by [@&#8203;Gravitonic](https://togithub.com/Gravitonic) in [https://github.com/vitest-dev/vitest/issues/6006](https://togithub.com/vitest-dev/vitest/issues/6006) [<samp>(2898a)</samp>](https://togithub.com/vitest-dev/vitest/commit/2898a525d)
    -   Remove work-around for implicit `else` - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/6014](https://togithub.com/vitest-dev/vitest/issues/6014) [<samp>(368c1)</samp>](https://togithub.com/vitest-dev/vitest/commit/368c13728)
-   **deps**:
    -   Update dependency [@&#8203;testing-library/dom](https://togithub.com/testing-library/dom) to v10 - by **renovate\[bot]** in [https://github.com/vitest-dev/vitest/issues/5866](https://togithub.com/vitest-dev/vitest/issues/5866) [<samp>(e9745)</samp>](https://togithub.com/vitest-dev/vitest/commit/e9745997e)
    -   Update vulnerable `test-exclude` to v7 - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5867](https://togithub.com/vitest-dev/vitest/issues/5867) [<samp>(0a715)</samp>](https://togithub.com/vitest-dev/vitest/commit/0a715946b)
-   **expect**:
    -   Fix immutable.js iterable equality - by [@&#8203;hi-ogawa](https://togithub.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/5692](https://togithub.com/vitest-dev/vitest/issues/5692) [<samp>(1532c)</samp>](https://togithub.com/vitest-dev/vitest/commit/1532c19a0)
-   **forks**:
    -   Resolve `poolOptions.<name>.isolate` from `forks` options - by [@&#8203;AriPerkkio](https://togithub.com/AriPerkkio) in [https://github.com/vitest-dev/vitest/issues/5840](https://togithub.com/vitest-dev/vitest/issues/5840) [<samp>(a60a1)</samp>](https://togithub.com/vitest-dev/vitest/commit/a60a140ef)
-   **runner**:
    -   Ensure inner suite { sequential: true } correctly overrides outer suite { concurrent: true } - by [@&#8203;pengooseDev](https://togithub.com/pengooseDev) in [https://github.com/vitest-dev/vitest/issues/5737](https://togithub.com/vitest-dev/vitest/issues/5737) [<samp>(a20e7)</samp>](https://togithub.com/vitest-dev/vitest/commit/a20e75b89)
    -   Ensure test.each print -0 and -NaN properly - by [@&#8203;pengooseDev](https://togithub.com/pengooseDev) in [https://github.com/vitest-dev/vitest/issues/5806](https://togithub.com/vitest-dev/vitest/issues/5806) [<samp>(9ac8f)</samp>](https://togithub.com/vitest-dev/vitest/commit/9ac8ff9bd)
-   **snapshot**:
    -   Fix `toMatchFileSnapshot` with empty file - by [@&#8203;hi-ogawa](https://togithub.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/5894](https://togithub.com/vitest-dev/vitest/issues/5894) [<samp>(88006)</samp>](https://togithub.com/vitest-dev/vitest/commit/8800601d2)
-   **spy**:
    -   Correctly track constructor's "this" type - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) [<samp>(4776e)</samp>](https://togithub.com/vitest-dev/vitest/commit/4776eca1d)
-   **types**:
    -   Mark pool options as not available in project config - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5934](https://togithub.com/vitest-dev/vitest/issues/5934) [<samp>(486fd)</samp>](https://togithub.com/vitest-dev/vitest/commit/486fd1169)
-   **ui**:
    -   Show correct module graph and project name in a Vitest workspace - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5792](https://togithub.com/vitest-dev/vitest/issues/5792) [<samp>(48c50)</samp>](https://togithub.com/vitest-dev/vitest/commit/48c502fbe)
    -   Update running todo tests inside todo suites (each) - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5939](https://togithub.com/vitest-dev/vitest/issues/5939) [<samp>(63ae1)</samp>](https://togithub.com/vitest-dev/vitest/commit/63ae10bd9)
    -   `FileDetails` title status icon not being updated - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5942](https://togithub.com/vitest-dev/vitest/issues/5942) [<samp>(e9ddf)</samp>](https://togithub.com/vitest-dev/vitest/commit/e9ddf9ce2)
-   **ui, browser**:
    -   Disable mouse events when resizing main navigation panel - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5863](https://togithub.com/vitest-dev/vitest/issues/5863) [<samp>(7cbd9)</samp>](https://togithub.com/vitest-dev/vitest/commit/7cbd943c7)
-   **utils**:
    -   Produce valid snapshot names - by [@&#8203;dubzzz](https://togithub.com/dubzzz) in [https://github.com/vitest-dev/vitest/issues/5724](https://togithub.com/vitest-dev/vitest/issues/5724) [<samp>(1ec61)</samp>](https://togithub.com/vitest-dev/vitest/commit/1ec61ceee)
    -   Fix color util maximum call stack error - by [@&#8203;hi-ogawa](https://togithub.com/hi-ogawa) in [https://github.com/vitest-dev/vitest/issues/5733](https://togithub.com/vitest-dev/vitest/issues/5733) [<samp>(a4ec5)</samp>](https://togithub.com/vitest-dev/vitest/commit/a4ec58319)
    -   Package exports - by [@&#8203;userquin](https://togithub.com/userquin) in [https://github.com/vitest-dev/vitest/issues/5847](https://togithub.com/vitest-dev/vitest/issues/5847) [<samp>(07876)</samp>](https://togithub.com/vitest-dev/vitest/commit/07876b7e0)
-   **vite-node**:
    -   Expose all envs from .env file, not just with a prefix `VITE_` - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6017](https://togithub.com/vitest-dev/vitest/issues/6017) [<samp>(d87be)</samp>](https://togithub.com/vitest-dev/vitest/commit/d87bef961)
-   **vitest**:
    -   Expose `provide` to the public API - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5897](https://togithub.com/vitest-dev/vitest/issues/5897) [<samp>(66e64)</samp>](https://togithub.com/vitest-dev/vitest/commit/66e648ff8)
    -   Cache fs code only for forks pool - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/5909](https://togithub.com/vitest-dev/vitest/issues/5909) [<samp>(e30d9)</samp>](https://togithub.com/vitest-dev/vitest/commit/e30d9b4d5)
    -   Allow testing unandled rejection/exception - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6016](https://togithub.com/vitest-dev/vitest/issues/6016) [<samp>(c8d56)</samp>](https://togithub.com/vitest-dev/vitest/commit/c8d56fe5f)
    -   Show all failed tests when rerunning a test - by [@&#8203;sheremet-va](https://togithub.com/sheremet-va) in [https://github.com/vitest-dev/vitest/issues/6022](https://togithub.com/vitest-dev/vitest/issues/6022) [<samp>(91ba6)</samp>](https://togithub.com/vitest-dev/vitest/commit/91ba6f95e)

##### [View changes on GitHub](6b29f3ddc8...v2.0.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MjUuMSIsInVwZGF0ZWRJblZlciI6IjM4LjU2LjAiLCJ0YXJnZXRCcmFuY2giOiJjYW5hcnkiLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->
2024-09-03 10:02:02 +00:00
fundon
98d9295259 feat(core): support block or element reference links (#7946)
Upstreams: https://github.com/toeverything/blocksuite/pull/8021

* open doc with mode
* monitor mode changes in query string
* scroll anchoring

https://github.com/user-attachments/assets/681abff8-e51b-47ea-bb71-447e8b312142

https://github.com/user-attachments/assets/e73ed4c0-4e33-45f8-9db4-d8eed3525d05
2024-09-03 09:49:15 +00:00
renovate
e7b53641d7 chore: bump up keyv version to v5 (#7936)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [keyv](https://togithub.com/jaredwray/keyv) | [`^4.5.4` -> `^5.0.0`](https://renovatebot.com/diffs/npm/keyv/4.5.4/5.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/keyv/5.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/keyv/5.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/keyv/4.5.4/5.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/keyv/4.5.4/5.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguNTYuMCIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-03 09:37:39 +00:00
darkskygit
41f9149be6 feat(server): support openai compatible stream api (#8065)
fix #8010
2024-09-03 09:25:00 +00:00
darkskygit
935771c8a8 feat(server): make captcha modular (#5961) 2024-09-03 09:03:51 +00:00
forehalo
52c9da67f0 refactor(auth): authenticate user in main window (#8032) 2024-09-03 09:03:47 +00:00
forehalo
e33aa35f7e refactor(core): auth (#7999)
closes AF-753 AF-1227
2024-09-03 09:03:43 +00:00
forehalo
8b0afd6eeb refactor(server): auth (#7994) 2024-09-03 09:03:39 +00:00
Brooooooklyn
821de0a3bb ci: only expose mobile entry on canary (#8064) 2024-09-03 08:48:34 +00:00
SOUMITRA-SAHA
bc306faa2c fix(core): handle text overflow styles for search box (#8054) 2024-09-03 16:47:29 +08:00
renovate
bd8c844e75 chore: bump up figma-squircle version to v1 (#8047)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [figma-squircle](https://redirect.github.com/phamfoo/figma-squircle) | [`^0.3.1` -> `^1.0.0`](https://renovatebot.com/diffs/npm/figma-squircle/0.3.1/1.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/figma-squircle/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/figma-squircle/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/figma-squircle/0.3.1/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/figma-squircle/0.3.1/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>phamfoo/figma-squircle (figma-squircle)</summary>

### [`v1.0.0`](https://redirect.github.com/phamfoo/figma-squircle/releases/tag/v1.0.0)

[Compare Source](https://redirect.github.com/phamfoo/figma-squircle/compare/v0.3.1...v1.0.0)

-   Target es2022  [`700c8f2`](https://redirect.github.com/phamfoo/figma-squircle/commit/700c8f2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41OS4yIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-03 08:28:03 +00:00
renovate
abbc6aef09 chore: bump up oxlint version to v0.9.2 (#8050)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [oxlint](https://oxc.rs) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxlint)) | [`0.9.1` -> `0.9.2`](https://renovatebot.com/diffs/npm/oxlint/0.9.1/0.9.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint/0.9.1/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint/0.9.1/0.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxlint)</summary>

### [`v0.9.2`](https://redirect.github.com/oxc-project/oxc/releases/tag/oxlint_v0.9.2): oxlint v0.9.2

[Compare Source](https://redirect.github.com/oxc-project/oxc/compare/oxlint_v0.9.1...oxlint_v0.9.2)

#### \[0.9.2] - 2024-09-02

##### Features

-   [`f81e8a1`](https://redirect.github.com/oxc-project/oxc/commit/f81e8a1) linter: Add `oxc/no-async-endpoint-handlers` ([#&#8203;5364](https://redirect.github.com/oxc-project/oxc/issues/5364)) (DonIsaac)
-   [`b103737`](https://redirect.github.com/oxc-project/oxc/commit/b103737) linter: Improve no-accumulating-spread ([#&#8203;5302](https://redirect.github.com/oxc-project/oxc/issues/5302)) (camc314)
-   [`9c22ce9`](https://redirect.github.com/oxc-project/oxc/commit/9c22ce9) linter: Add hyperlinks to diagnostic messages ([#&#8203;5318](https://redirect.github.com/oxc-project/oxc/issues/5318)) (DonIsaac)
-   [`1967c67`](https://redirect.github.com/oxc-project/oxc/commit/1967c67) linter/eslint: Implement no-new-func ([#&#8203;5360](https://redirect.github.com/oxc-project/oxc/issues/5360)) (dalaoshu)
-   [`b867e5f`](https://redirect.github.com/oxc-project/oxc/commit/b867e5f) linter/eslint-plugin-promise: Implement catch-or-return ([#&#8203;5121](https://redirect.github.com/oxc-project/oxc/issues/5121)) (Jelle van der Waa)
-   [`8d781e7`](https://redirect.github.com/oxc-project/oxc/commit/8d781e7) linter/oxc: Differentiate between array/object in `no-accumulating-spread` loop diagnostic ([#&#8203;5375](https://redirect.github.com/oxc-project/oxc/issues/5375)) (camc314)
-   [`db55444`](https://redirect.github.com/oxc-project/oxc/commit/db55444) linter/oxc: Add fixer for `double-comparisons` ([#&#8203;5378](https://redirect.github.com/oxc-project/oxc/issues/5378)) (camc314)
-   [`e5c755a`](https://redirect.github.com/oxc-project/oxc/commit/e5c755a) linter/promise: Add `spec-only` rule ([#&#8203;5124](https://redirect.github.com/oxc-project/oxc/issues/5124)) (Jelle van der Waa)
-   [`4c0861f`](https://redirect.github.com/oxc-project/oxc/commit/4c0861f) linter/unicorn: Add fixer for `prefer-type-error` ([#&#8203;5311](https://redirect.github.com/oxc-project/oxc/issues/5311)) (camc314)
-   [`084c2d1`](https://redirect.github.com/oxc-project/oxc/commit/084c2d1) linter/vitest: Implement prefer-to-be-object ([#&#8203;5321](https://redirect.github.com/oxc-project/oxc/issues/5321)) (dalaoshu)

##### Bug Fixes

-   [`11b93af`](https://redirect.github.com/oxc-project/oxc/commit/11b93af) linter/unicorn: Consistent-function-scoping false positive on assignment expression ([#&#8203;5312](https://redirect.github.com/oxc-project/oxc/issues/5312)) (Arian94)

##### Performance

-   [`f052a6d`](https://redirect.github.com/oxc-project/oxc/commit/f052a6d) linter: `react/jsx_no_undef` faster check for unbound references ([#&#8203;5349](https://redirect.github.com/oxc-project/oxc/issues/5349)) (overlookmotel)
-   [`05636b7`](https://redirect.github.com/oxc-project/oxc/commit/05636b7) linter: Avoid unnecessary work in `jsx_a11y/anchor_is_valid` rule ([#&#8203;5341](https://redirect.github.com/oxc-project/oxc/issues/5341)) (overlookmotel)

##### Refactor

-   [`afb038e`](https://redirect.github.com/oxc-project/oxc/commit/afb038e) linter: `react/jsx_no_undef` use loop instead of recursion ([#&#8203;5347](https://redirect.github.com/oxc-project/oxc/issues/5347)) (overlookmotel)
-   [`fe62687`](https://redirect.github.com/oxc-project/oxc/commit/fe62687) linter: Simplify skipping JSX elements in `unicorn/consistent_function_scoping` ([#&#8203;5351](https://redirect.github.com/oxc-project/oxc/issues/5351)) (overlookmotel)
-   [`381d9fe`](https://redirect.github.com/oxc-project/oxc/commit/381d9fe) linter: Shorten code in `react/jsx_no_useless_fragment` ([#&#8203;5350](https://redirect.github.com/oxc-project/oxc/issues/5350)) (overlookmotel)
-   [`83b9a82`](https://redirect.github.com/oxc-project/oxc/commit/83b9a82) linter: Fix indentation in `nextjs/no_script_component_in_head` rule ([#&#8203;5338](https://redirect.github.com/oxc-project/oxc/issues/5338)) (overlookmotel)
-   [`89f0188`](https://redirect.github.com/oxc-project/oxc/commit/89f0188) linter: Improve docs for `react/jsx_no_target_blank` rule ([#&#8203;5342](https://redirect.github.com/oxc-project/oxc/issues/5342)) (overlookmotel)
-   [`57050ab`](https://redirect.github.com/oxc-project/oxc/commit/57050ab) linter: Shorten code in `jsx_a11y/aria_activedescendant_has_tabindex` rule ([#&#8203;5340](https://redirect.github.com/oxc-project/oxc/issues/5340)) (overlookmotel)
-   [`ed31d67`](https://redirect.github.com/oxc-project/oxc/commit/ed31d67) linter/jest: Fix indentation in code comment ([#&#8203;5372](https://redirect.github.com/oxc-project/oxc/issues/5372)) (camc314)
-   [`2499cb9`](https://redirect.github.com/oxc-project/oxc/commit/2499cb9) linter/oxc: Update rule docs for `erasing-op` ([#&#8203;5376](https://redirect.github.com/oxc-project/oxc/issues/5376)) (camc314)
-   [`69493d2`](https://redirect.github.com/oxc-project/oxc/commit/69493d2) linter/oxc: Improve diagnostic for `no-accumulating-spread` in loops ([#&#8203;5374](https://redirect.github.com/oxc-project/oxc/issues/5374)) (camc314)
-   [`024b585`](https://redirect.github.com/oxc-project/oxc/commit/024b585) linter/oxc: Improve code comment for `no-accumulating-spread` ([#&#8203;5373](https://redirect.github.com/oxc-project/oxc/issues/5373)) (camc314)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41OS4yIiwidXBkYXRlZEluVmVyIjoiMzguNTkuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-09-03 08:11:59 +00:00
renovate
3f324a5af9 chore: bump up @types/eslint version to v9 (#7570)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@types/eslint](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/eslint) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint)) | [`^8.56.7` -> `^9.0.0`](https://renovatebot.com/diffs/npm/@types%2feslint/8.56.11/9.6.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2feslint/9.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2feslint/9.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2feslint/8.56.11/9.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2feslint/8.56.11/9.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM4LjU2LjAiLCJ0YXJnZXRCcmFuY2giOiJjYW5hcnkiLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->
2024-09-03 07:56:25 +00:00
renovate
7b9d9a1ca6 chore: Lock file maintenance (#7390)
This PR contains the following updates:

| Update | Change |
|---|---|
| lockFileMaintenance | All locks refreshed |

🔧 This Pull Request updates lock files to use the latest dependency versions.

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MjEuMCIsInVwZGF0ZWRJblZlciI6IjM4LjU5LjIiLCJ0YXJnZXRCcmFuY2giOiJjYW5hcnkiLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->
2024-09-03 07:42:54 +00:00
Brooooooklyn
12d73ee290 ci: handle the blocksuite commit is not found on current branch (#8061) 2024-09-03 07:09:03 +00:00
renovate
d819a26bc1 chore: bump up all non-major dependencies (#7963)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence | Type | Update |
|---|---|---|---|---|---|---|---|
| [@chromatic-com/storybook](https://redirect.github.com/chromaui/addon-visual-tests) | [`1.7.0` -> `1.8.0`](https://renovatebot.com/diffs/npm/@chromatic-com%2fstorybook/1.7.0/1.8.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@chromatic-com%2fstorybook/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@chromatic-com%2fstorybook/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@chromatic-com%2fstorybook/1.7.0/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@chromatic-com%2fstorybook/1.7.0/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@commitlint/cli](https://commitlint.js.org/) ([source](https://redirect.github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli)) | [`19.4.0` -> `19.4.1`](https://renovatebot.com/diffs/npm/@commitlint%2fcli/19.4.0/19.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@commitlint%2fcli/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@commitlint%2fcli/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@commitlint%2fcli/19.4.0/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@commitlint%2fcli/19.4.0/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@commitlint/config-conventional](https://commitlint.js.org/) ([source](https://redirect.github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-conventional)) | [`19.2.2` -> `19.4.1`](https://renovatebot.com/diffs/npm/@commitlint%2fconfig-conventional/19.2.2/19.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@commitlint%2fconfig-conventional/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@commitlint%2fconfig-conventional/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@commitlint%2fconfig-conventional/19.2.2/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@commitlint%2fconfig-conventional/19.2.2/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@marsidev/react-turnstile](https://redirect.github.com/marsidev/react-turnstile) | [`1.0.0` -> `1.0.1`](https://renovatebot.com/diffs/npm/@marsidev%2freact-turnstile/1.0.0/1.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@marsidev%2freact-turnstile/1.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@marsidev%2freact-turnstile/1.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@marsidev%2freact-turnstile/1.0.0/1.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@marsidev%2freact-turnstile/1.0.0/1.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@napi-rs/simple-git](https://redirect.github.com/Brooooooklyn/simple-git) | [`0.1.18` -> `0.1.19`](https://renovatebot.com/diffs/npm/@napi-rs%2fsimple-git/0.1.18/0.1.19) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fsimple-git/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fsimple-git/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fsimple-git/0.1.18/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fsimple-git/0.1.18/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@napi-rs/simple-git](https://redirect.github.com/Brooooooklyn/simple-git) | [`0.1.18` -> `0.1.19`](https://renovatebot.com/diffs/npm/@napi-rs%2fsimple-git/0.1.18/0.1.19) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fsimple-git/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fsimple-git/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fsimple-git/0.1.18/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fsimple-git/0.1.18/0.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@nx/vite](https://nx.dev) ([source](https://redirect.github.com/nrwl/nx/tree/HEAD/packages/vite)) | [`19.6.2` -> `19.6.4`](https://renovatebot.com/diffs/npm/@nx%2fvite/19.6.2/19.6.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nx%2fvite/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nx%2fvite/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nx%2fvite/19.6.2/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nx%2fvite/19.6.2/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@opentelemetry/core](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-core) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`1.25.1` -> `1.26.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fcore/1.25.1/1.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fcore/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fcore/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fcore/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fcore/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/exporter-prometheus](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-prometheus) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.52.0` -> `^0.53.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fexporter-prometheus/0.52.1/0.53.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fexporter-prometheus/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fexporter-prometheus/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fexporter-prometheus/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fexporter-prometheus/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/exporter-zipkin](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-zipkin) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`1.25.1` -> `1.26.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fexporter-zipkin/1.25.1/1.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fexporter-zipkin/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fexporter-zipkin/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fexporter-zipkin/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fexporter-zipkin/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/instrumentation](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.52.0` -> `^0.53.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation/0.52.1/0.53.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/instrumentation-graphql](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-graphql#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib)) | [`^0.42.0` -> `^0.43.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-graphql/0.42.0/0.43.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation-graphql/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation-graphql/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation-graphql/0.42.0/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation-graphql/0.42.0/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/instrumentation-http](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.52.0` -> `^0.53.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-http/0.52.1/0.53.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation-http/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation-http/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation-http/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation-http/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/instrumentation-ioredis](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-ioredis#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib)) | [`^0.42.0` -> `^0.43.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-ioredis/0.42.0/0.43.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation-ioredis/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation-ioredis/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation-ioredis/0.42.0/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation-ioredis/0.42.0/0.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/instrumentation-nestjs-core](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-nestjs-core#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib)) | [`^0.39.0` -> `^0.40.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-nestjs-core/0.39.0/0.40.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation-nestjs-core/0.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation-nestjs-core/0.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation-nestjs-core/0.39.0/0.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation-nestjs-core/0.39.0/0.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/instrumentation-socket.io](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-socket.io#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib)) | [`^0.41.0` -> `^0.42.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-socket.io/0.41.0/0.42.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation-socket.io/0.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation-socket.io/0.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation-socket.io/0.41.0/0.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation-socket.io/0.41.0/0.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/resources](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-resources) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`1.25.1` -> `1.26.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fresources/1.25.1/1.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fresources/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fresources/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fresources/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fresources/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/sdk-metrics](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/sdk-metrics) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`1.25.1` -> `1.26.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsdk-metrics/1.25.1/1.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fsdk-metrics/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fsdk-metrics/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fsdk-metrics/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fsdk-metrics/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/sdk-node](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-node) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.52.0` -> `^0.53.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsdk-node/0.52.1/0.53.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fsdk-node/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fsdk-node/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fsdk-node/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fsdk-node/0.52.1/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/sdk-trace-node](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`1.25.1` -> `1.26.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsdk-trace-node/1.25.1/1.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fsdk-trace-node/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fsdk-trace-node/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fsdk-trace-node/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fsdk-trace-node/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@opentelemetry/semantic-conventions](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`1.26.0` -> `1.27.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsemantic-conventions/1.26.0/1.27.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fsemantic-conventions/1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fsemantic-conventions/1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fsemantic-conventions/1.26.0/1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fsemantic-conventions/1.26.0/1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@prisma/client](https://www.prisma.io) ([source](https://redirect.github.com/prisma/prisma/tree/HEAD/packages/client)) | [`5.18.0` -> `5.19.1`](https://renovatebot.com/diffs/npm/@prisma%2fclient/5.18.0/5.19.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@prisma%2fclient/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@prisma%2fclient/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@prisma%2fclient/5.18.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@prisma%2fclient/5.18.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@prisma/instrumentation](https://www.prisma.io) ([source](https://redirect.github.com/prisma/prisma/tree/HEAD/packages/instrumentation)) | [`5.18.0` -> `5.19.1`](https://renovatebot.com/diffs/npm/@prisma%2finstrumentation/5.18.0/5.19.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@prisma%2finstrumentation/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@prisma%2finstrumentation/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@prisma%2finstrumentation/5.18.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@prisma%2finstrumentation/5.18.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@sentry/electron](https://redirect.github.com/getsentry/sentry-electron) | [`5.3.0` -> `5.4.0`](https://renovatebot.com/diffs/npm/@sentry%2felectron/5.3.0/5.4.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2felectron/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2felectron/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2felectron/5.3.0/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2felectron/5.3.0/5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@sentry/esbuild-plugin](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/tree/main/packages/esbuild-plugin) ([source](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins)) | [`2.22.2` -> `2.22.3`](https://renovatebot.com/diffs/npm/@sentry%2fesbuild-plugin/2.22.2/2.22.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2fesbuild-plugin/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2fesbuild-plugin/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2fesbuild-plugin/2.22.2/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2fesbuild-plugin/2.22.2/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@sentry/react](https://redirect.github.com/getsentry/sentry-javascript/tree/master/packages/react) ([source](https://redirect.github.com/getsentry/sentry-javascript)) | [`8.26.0` -> `8.27.0`](https://renovatebot.com/diffs/npm/@sentry%2freact/8.26.0/8.27.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2freact/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2freact/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2freact/8.26.0/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2freact/8.26.0/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@sentry/react](https://redirect.github.com/getsentry/sentry-javascript/tree/master/packages/react) ([source](https://redirect.github.com/getsentry/sentry-javascript)) | [`8.26.0` -> `8.27.0`](https://renovatebot.com/diffs/npm/@sentry%2freact/8.26.0/8.27.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2freact/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2freact/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2freact/8.26.0/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2freact/8.26.0/8.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@sentry/webpack-plugin](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins/tree/main/packages/webpack-plugin) ([source](https://redirect.github.com/getsentry/sentry-javascript-bundler-plugins)) | [`2.22.2` -> `2.22.3`](https://renovatebot.com/diffs/npm/@sentry%2fwebpack-plugin/2.22.2/2.22.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2fwebpack-plugin/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2fwebpack-plugin/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2fwebpack-plugin/2.22.2/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2fwebpack-plugin/2.22.2/2.22.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@swc/core](https://swc.rs) ([source](https://redirect.github.com/swc-project/swc)) | [`1.7.14` -> `1.7.23`](https://renovatebot.com/diffs/npm/@swc%2fcore/1.7.14/1.7.23) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@swc%2fcore/1.7.23?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@swc%2fcore/1.7.23?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@swc%2fcore/1.7.14/1.7.23?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@swc%2fcore/1.7.14/1.7.23?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@tanstack/react-table](https://tanstack.com/table) ([source](https://redirect.github.com/TanStack/table/tree/HEAD/packages/react-table)) | [`8.20.1` -> `8.20.5`](https://renovatebot.com/diffs/npm/@tanstack%2freact-table/8.20.1/8.20.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@tanstack%2freact-table/8.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@tanstack%2freact-table/8.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@tanstack%2freact-table/8.20.1/8.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@tanstack%2freact-table/8.20.1/8.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@testing-library/react](https://redirect.github.com/testing-library/react-testing-library) | [`16.0.0` -> `16.0.1`](https://renovatebot.com/diffs/npm/@testing-library%2freact/16.0.0/16.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@testing-library%2freact/16.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@testing-library%2freact/16.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@testing-library%2freact/16.0.0/16.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@testing-library%2freact/16.0.0/16.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@types/eslint](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/eslint) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint)) | [`8.56.11` -> `8.56.12`](https://renovatebot.com/diffs/npm/@types%2feslint/8.56.11/8.56.12) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2feslint/8.56.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2feslint/8.56.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2feslint/8.56.11/8.56.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2feslint/8.56.11/8.56.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@types/mixpanel-browser](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mixpanel-browser) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/mixpanel-browser)) | [`2.49.1` -> `2.50.0`](https://renovatebot.com/diffs/npm/@types%2fmixpanel-browser/2.49.1/2.50.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fmixpanel-browser/2.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fmixpanel-browser/2.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fmixpanel-browser/2.49.1/2.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fmixpanel-browser/2.49.1/2.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`20.16.1` -> `20.16.3`](https://renovatebot.com/diffs/npm/@types%2fnode/20.16.1/20.16.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.16.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.16.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.16.1/20.16.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.16.1/20.16.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@types/react](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react)) | [`18.3.4` -> `18.3.5`](https://renovatebot.com/diffs/npm/@types%2freact/18.3.4/18.3.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.3.4/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.3.4/18.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [changelogithub](https://redirect.github.com/antfu/changelogithub) | [`0.13.9` -> `0.13.10`](https://renovatebot.com/diffs/npm/changelogithub/0.13.9/0.13.10) | [![age](https://developer.mend.io/api/mc/badges/age/npm/changelogithub/0.13.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/changelogithub/0.13.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/changelogithub/0.13.9/0.13.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/changelogithub/0.13.9/0.13.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [commitlint](https://commitlint.js.org/) ([source](https://redirect.github.com/conventional-changelog/commitlint/tree/HEAD/@alias/commitlint)) | [`19.4.0` -> `19.4.1`](https://renovatebot.com/diffs/npm/commitlint/19.4.0/19.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/commitlint/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/commitlint/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/commitlint/19.4.0/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/commitlint/19.4.0/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [fast-xml-parser](https://redirect.github.com/NaturalIntelligence/fast-xml-parser) | [`4.4.1` -> `4.5.0`](https://renovatebot.com/diffs/npm/fast-xml-parser/4.4.1/4.5.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/fast-xml-parser/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/fast-xml-parser/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/fast-xml-parser/4.4.1/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/fast-xml-parser/4.4.1/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [happy-dom](https://redirect.github.com/capricorn86/happy-dom) | [`15.0.0` -> `15.7.3`](https://renovatebot.com/diffs/npm/happy-dom/15.0.0/15.7.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/happy-dom/15.7.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/happy-dom/15.7.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/happy-dom/15.0.0/15.7.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/happy-dom/15.0.0/15.7.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [http-proxy-middleware](https://redirect.github.com/chimurai/http-proxy-middleware) | [`3.0.0` -> `3.0.1`](https://renovatebot.com/diffs/npm/http-proxy-middleware/3.0.0/3.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/http-proxy-middleware/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/http-proxy-middleware/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/http-proxy-middleware/3.0.0/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/http-proxy-middleware/3.0.0/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [jotai-effect](https://redirect.github.com/jotaijs/jotai-effect) | [`1.0.2` -> `1.0.3`](https://renovatebot.com/diffs/npm/jotai-effect/1.0.2/1.0.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai-effect/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai-effect/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai-effect/1.0.2/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai-effect/1.0.2/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [lint-staged](https://redirect.github.com/lint-staged/lint-staged) | [`15.2.9` -> `15.2.10`](https://renovatebot.com/diffs/npm/lint-staged/15.2.9/15.2.10) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lint-staged/15.2.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lint-staged/15.2.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lint-staged/15.2.9/15.2.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lint-staged/15.2.9/15.2.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [lucide-react](https://lucide.dev) ([source](https://redirect.github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react)) | [`^0.435.0` -> `^0.438.0`](https://renovatebot.com/diffs/npm/lucide-react/0.435.0/0.438.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lucide-react/0.438.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lucide-react/0.438.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lucide-react/0.435.0/0.438.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lucide-react/0.435.0/0.438.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [marked](https://marked.js.org) ([source](https://redirect.github.com/markedjs/marked)) | [`14.0.0` -> `14.1.0`](https://renovatebot.com/diffs/npm/marked/14.0.0/14.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/marked/14.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/marked/14.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/marked/14.0.0/14.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/marked/14.0.0/14.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [mixpanel-browser](https://redirect.github.com/mixpanel/mixpanel-js) | [`2.55.0` -> `2.55.1`](https://renovatebot.com/diffs/npm/mixpanel-browser/2.55.0/2.55.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/mixpanel-browser/2.55.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/mixpanel-browser/2.55.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/mixpanel-browser/2.55.0/2.55.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/mixpanel-browser/2.55.0/2.55.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [msw](https://mswjs.io) ([source](https://redirect.github.com/mswjs/msw)) | [`2.3.5` -> `2.4.1`](https://renovatebot.com/diffs/npm/msw/2.3.5/2.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/msw/2.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/msw/2.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/msw/2.3.5/2.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/msw/2.3.5/2.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [nestjs-throttler-storage-redis](https://redirect.github.com/kkoomen/nestjs-throttler-storage-redis) | [`0.5.0` -> `0.5.1`](https://renovatebot.com/diffs/npm/nestjs-throttler-storage-redis/0.5.0/0.5.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nestjs-throttler-storage-redis/0.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nestjs-throttler-storage-redis/0.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nestjs-throttler-storage-redis/0.5.0/0.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nestjs-throttler-storage-redis/0.5.0/0.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [nx](https://nx.dev) ([source](https://redirect.github.com/nrwl/nx/tree/HEAD/packages/nx)) | [`19.6.2` -> `19.6.4`](https://renovatebot.com/diffs/npm/nx/19.6.2/19.6.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nx/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nx/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nx/19.6.2/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nx/19.6.2/19.6.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [openai](https://redirect.github.com/openai/openai-node) | [`4.56.0` -> `4.57.0`](https://renovatebot.com/diffs/npm/openai/4.56.0/4.57.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/openai/4.57.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/openai/4.57.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/openai/4.56.0/4.57.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/openai/4.56.0/4.57.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [postcss](https://postcss.org/) ([source](https://redirect.github.com/postcss/postcss)) | [`8.4.41` -> `8.4.44`](https://renovatebot.com/diffs/npm/postcss/8.4.41/8.4.44) | [![age](https://developer.mend.io/api/mc/badges/age/npm/postcss/8.4.44?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/postcss/8.4.44?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/postcss/8.4.41/8.4.44?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/postcss/8.4.41/8.4.44?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [prisma](https://www.prisma.io) ([source](https://redirect.github.com/prisma/prisma/tree/HEAD/packages/cli)) | [`5.18.0` -> `5.19.1`](https://renovatebot.com/diffs/npm/prisma/5.18.0/5.19.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prisma/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prisma/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prisma/5.18.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prisma/5.18.0/5.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [react-hook-form](https://www.react-hook-form.com) ([source](https://redirect.github.com/react-hook-form/react-hook-form)) | [`7.52.2` -> `7.53.0`](https://renovatebot.com/diffs/npm/react-hook-form/7.52.2/7.53.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-hook-form/7.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-hook-form/7.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-hook-form/7.52.2/7.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-hook-form/7.52.2/7.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [react-resizable-panels](https://redirect.github.com/bvaughn/react-resizable-panels) | [`2.1.1` -> `2.1.2`](https://renovatebot.com/diffs/npm/react-resizable-panels/2.1.1/2.1.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-resizable-panels/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-resizable-panels/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-resizable-panels/2.1.1/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-resizable-panels/2.1.1/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [react-virtuoso](https://virtuoso.dev/) ([source](https://redirect.github.com/petyosi/react-virtuoso)) | [`4.10.1` -> `4.10.2`](https://renovatebot.com/diffs/npm/react-virtuoso/4.10.1/4.10.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-virtuoso/4.10.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-virtuoso/4.10.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-virtuoso/4.10.1/4.10.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-virtuoso/4.10.1/4.10.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [serde](https://serde.rs) ([source](https://redirect.github.com/serde-rs/serde)) | `1.0.208` -> `1.0.209` | [![age](https://developer.mend.io/api/mc/badges/age/crate/serde/1.0.209?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/serde/1.0.209?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/serde/1.0.208/1.0.209?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/serde/1.0.208/1.0.209?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [serde_json](https://redirect.github.com/serde-rs/json) | `1.0.125` -> `1.0.127` | [![age](https://developer.mend.io/api/mc/badges/age/crate/serde_json/1.0.127?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/serde_json/1.0.127?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/serde_json/1.0.125/1.0.127?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/serde_json/1.0.125/1.0.127?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [ses](https://redirect.github.com/Agoric/SES-shim/tree/master/packages/ses#readme) ([source](https://redirect.github.com/endojs/endo/tree/HEAD/packages/ses)) | [`1.7.0` -> `1.8.0`](https://renovatebot.com/diffs/npm/ses/1.7.0/1.8.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/ses/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/ses/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/ses/1.7.0/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/ses/1.7.0/1.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [shadcn-ui](https://redirect.github.com/shadcn/ui) ([source](https://redirect.github.com/shadcn/ui/tree/HEAD/packages/cli)) | [`^0.8.0` -> `^0.9.0`](https://renovatebot.com/diffs/npm/shadcn-ui/0.8.0/0.9.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/shadcn-ui/0.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/shadcn-ui/0.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/shadcn-ui/0.8.0/0.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/shadcn-ui/0.8.0/0.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [slackapi/slack-github-action](https://redirect.github.com/slackapi/slack-github-action) | `v1.26.0` -> `v1.27.0` | [![age](https://developer.mend.io/api/mc/badges/age/github-tags/slackapi%2fslack-github-action/v1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/github-tags/slackapi%2fslack-github-action/v1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/github-tags/slackapi%2fslack-github-action/v1.26.0/v1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/slackapi%2fslack-github-action/v1.26.0/v1.27.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | action | minor |
| [storybook-dark-mode](https://redirect.github.com/hipstersmoothie/storybook-dark-mode) | [`4.0.1` -> `4.0.2`](https://renovatebot.com/diffs/npm/storybook-dark-mode/4.0.1/4.0.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/storybook-dark-mode/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/storybook-dark-mode/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/storybook-dark-mode/4.0.1/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/storybook-dark-mode/4.0.1/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [stripe](https://redirect.github.com/stripe/stripe-node) | [`16.8.0` -> `16.9.0`](https://renovatebot.com/diffs/npm/stripe/16.8.0/16.9.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/stripe/16.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/stripe/16.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/stripe/16.8.0/16.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/stripe/16.8.0/16.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [tokio](https://tokio.rs) ([source](https://redirect.github.com/tokio-rs/tokio)) | `1.39.3` -> `1.40.0` | [![age](https://developer.mend.io/api/mc/badges/age/crate/tokio/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/tokio/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/tokio/1.39.3/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/tokio/1.39.3/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dev-dependencies | minor |
| [tokio](https://tokio.rs) ([source](https://redirect.github.com/tokio-rs/tokio)) | `1.39.3` -> `1.40.0` | [![age](https://developer.mend.io/api/mc/badges/age/crate/tokio/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/tokio/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/tokio/1.39.3/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/tokio/1.39.3/1.40.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | minor |
| [vite-plugin-dts](https://redirect.github.com/qmhc/vite-plugin-dts) | [`4.0.3` -> `4.1.0`](https://renovatebot.com/diffs/npm/vite-plugin-dts/4.0.3/4.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite-plugin-dts/4.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite-plugin-dts/4.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite-plugin-dts/4.0.3/4.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite-plugin-dts/4.0.3/4.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [vitest-mock-extended](https://redirect.github.com/eratio08/vitest-mock-extended) | [`2.0.0` -> `2.0.2`](https://renovatebot.com/diffs/npm/vitest-mock-extended/2.0.0/2.0.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vitest-mock-extended/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vitest-mock-extended/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vitest-mock-extended/2.0.0/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest-mock-extended/2.0.0/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [wrangler](https://redirect.github.com/cloudflare/workers-sdk) ([source](https://redirect.github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler)) | [`3.72.2` -> `3.73.0`](https://renovatebot.com/diffs/npm/wrangler/3.72.2/3.73.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.72.2/3.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.72.2/3.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [yarn](https://redirect.github.com/yarnpkg/berry) ([source](https://redirect.github.com/yarnpkg/berry/tree/HEAD/packages/yarnpkg-cli)) | [`4.4.0` -> `4.4.1`](https://renovatebot.com/diffs/npm/yarn/4.4.0/4.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/yarn/4.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/yarn/4.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/yarn/4.4.0/4.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/yarn/4.4.0/4.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | packageManager | patch |

---

### Release Notes

<details>
<summary>chromaui/addon-visual-tests (@&#8203;chromatic-com/storybook)</summary>

### [`v1.8.0`](https://redirect.github.com/chromaui/addon-visual-tests/blob/HEAD/CHANGELOG.md#v180-Thu-Aug-29-2024)

[Compare Source](https://redirect.github.com/chromaui/addon-visual-tests/compare/v1.7.0...v1.8.0)

##### 🚀 Enhancement

-   Add `paramKey: "chromatic"` to allow disabling the VTA panel through story parameters [#&#8203;334](https://redirect.github.com/chromaui/addon-visual-tests/pull/334) ([@&#8203;mellm0](https://redirect.github.com/mellm0))

##### Authors: 1

-   Mell (
2024-09-03 06:55:34 +00:00
EYHN
a6484018ef refactor(core): refactor editor query string selector (#8058)
The editor selector is the information for locating a block, which can automatically focus on a certain content when a user opens a document.

```
export type EditorSelector = {
  blockIds?: string[];
  elementIds?: string[];
};
```

The selector can be set from multiple places, such as passing it in the center peek parameter, or passing it in the query part of the URL.

This pr decoupled the selector from the query string and now available at `editorService.editor.selector$`
2024-09-03 06:37:58 +00:00
fundon
f9d0a348c4 feat(core): add custom configuration to database options (#7933)
Upstreams: https://github.com/toeverything/blocksuite/pull/8022

* add custom configuration to database options
* add `Copy link to block` button to database options

<img width="518" alt="Screenshot 2024-09-03 at 08 57 59" src="https://github.com/user-attachments/assets/a421cd82-abd4-456e-af17-c4db6c4ff3ae">
2024-09-03 03:52:10 +00:00
fundon
c3ae219992 feat(core): add block and element toolbar widget custom config (#7886)
Upstreams: https://github.com/toeverything/blocksuite/pull/8001 https://github.com/toeverything/blocksuite/pull/7964

* add block/element toolbar widget config
* add `Copy link to block` to `more menu` on  block/element toolbar

<img width="376" alt="Screenshot 2024-08-16 at 16 20 08" src="https://github.com/user-attachments/assets/49b41de9-39d1-4f55-ac9b-445fe020187a">
2024-09-03 03:52:08 +00:00
CatsJuice
ad110078ac feat(mobile): setting page ui (#8048)
AF-1275
2024-09-03 03:27:18 +00:00
JimmFly
bea3d42f40 feat(core): add color picker ui to editor settings (#8053)
close AF-1306 AF-1280

![CleanShot 2024-09-03 at 00 23 10@2x](https://github.com/user-attachments/assets/46928c85-45ec-43b1-bbde-24beb7c5c580)
2024-09-03 03:14:50 +00:00
EYHN
02f0d7aa08 feat(component): dropdown menu auto avoid collisions (#8013)
<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/g3jz87HxbjOJpXV3FPT7/7f9d21cc-7b2f-4dc1-801c-e69d5e6d0750.mp4">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/g3jz87HxbjOJpXV3FPT7/7f9d21cc-7b2f-4dc1-801c-e69d5e6d0750.mp4">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/g3jz87HxbjOJpXV3FPT7/7f9d21cc-7b2f-4dc1-801c-e69d5e6d0750.mp4">CleanShot 2024-08-29 at 14.49.58.mp4</video>
2024-09-03 02:12:16 +00:00
pengx17
197996de31 fix(mobile): handle menu ref better (#8051) 2024-09-03 01:59:45 +00:00
L-Sun
392fef663e chore: bump blocksuite (#8052)
## Features
- https://github.com/toeverything/BlockSuite/pull/8115 @EYHN

## Bugfix
- https://github.com/toeverything/BlockSuite/pull/8119 @L-Sun
- https://github.com/toeverything/BlockSuite/pull/8117 @zzj3720
- https://github.com/toeverything/BlockSuite/pull/8114 @donteatfriedrice

## Misc
- https://github.com/toeverything/BlockSuite/pull/8106 @fundon
- https://github.com/toeverything/BlockSuite/pull/8116 @doodlewind
2024-09-02 15:25:26 +00:00
JimmFly
130e6ab4a3 chore: adjust custom font family style (#8040)
close AF-1302 AF-1301
2024-09-02 15:11:58 +00:00
akumatus
2e37ee0e33 feat(core): add actions to editor settings (#8030)
# What Changed?
- Add actions of following edgeless-elements editor settings:
  - note
  - connector
  - edgeless text
  - pen
2024-09-02 14:23:04 +00:00
pengx17
e1310b65cd fix(mobile): change how slider height is calculated (#8049) 2024-09-02 14:10:37 +00:00
Brooooooklyn
87da792c4c ci: deploy the mobile entry (#8028) 2024-09-02 12:59:41 +00:00
Saul-Mirone
56f4634c1f chore: bump bs with new extension api (#8042) 2024-09-02 10:32:22 +00:00
pengx17
61e37d8873 test(mobile): basic e2e tests (#8031)
fix AF-1289

1. tested on 'webkit'
2. a few baseline test cases
2024-09-02 10:20:24 +00:00
Brooooooklyn
41d35fdafd ci: skip generating changelog if prev commit is not found (#8045) 2024-09-02 10:08:16 +00:00
JimmFly
a992376053 chore: modify the text content of share menu (#8026)
![CleanShot 2024-08-30 at 12 18 27@2x](https://github.com/user-attachments/assets/f43a6d31-1bdb-491c-95f6-4609973b84a6)
![CleanShot 2024-08-30 at 12 18 40@2x](https://github.com/user-attachments/assets/387d4523-d5fb-41d4-8b46-c278432db05e)
2024-09-02 09:56:17 +00:00
darkskygit
d93d39e29d feat: add editor record (#7938)
fix CLOUD-58, CLOUD-61, CLOUD-62, PD-1607, PD-1608
2024-09-02 09:37:39 +00:00
forehalo
d9cedf89e1 fix(electron): app updater (#8043) 2024-09-02 07:53:17 +00:00
JimmFly
a802dc4fd6 chore: adjust experimental features text (#8044)
close AF-1313 AF-1312 AF-1311 AF-1310
2024-09-02 07:40:55 +00:00
pengx17
4caf32629a fix(core): slider thumb offset (#8041)
fix AF-1307
2024-09-02 07:19:16 +00:00
pengx17
697f2c6520 fix(core): remove modal default overlay onclick (#8035)
fix AF-1300

overlay click is already handled in `handlePointerDownOutSide`. adding onclick to overlay will cause issues on closing nested menus.
2024-09-02 02:59:18 +00:00
pengx17
df34e2cdf7 fix(mobile): close menu when detail page navigate away (#8027) 2024-08-31 04:42:32 +00:00
renovate
592997b65b chore: bump up oxlint version to v0.9.1 (#7974)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [oxlint](https://oxc.rs) ([source](https://togithub.com/oxc-project/oxc/tree/HEAD/npm/oxlint)) | [`0.8.0` -> `0.9.1`](https://renovatebot.com/diffs/npm/oxlint/0.8.0/0.9.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint/0.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint/0.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint/0.8.0/0.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint/0.8.0/0.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxlint)</summary>

### [`v0.9.1`](https://togithub.com/oxc-project/oxc/releases/tag/oxlint_v0.9.1): oxlint v0.9.1

[Compare Source](https://togithub.com/oxc-project/oxc/compare/oxlint_v0.9.0...oxlint_v0.9.1)

#### \[0.9.1] - 2024-08-29

##### Features

-   [`6633972`](https://togithub.com/oxc-project/oxc/commit/6633972) linter: Add fixer for `no-empty` ([#&#8203;5276](https://togithub.com/oxc-project/oxc/issues/5276)) (camc314)
-   [`a58e448`](https://togithub.com/oxc-project/oxc/commit/a58e448) linter/eslint: Add fixer to `no-var` ([#&#8203;5144](https://togithub.com/oxc-project/oxc/issues/5144)) (camc314)
-   [`a6e9769`](https://togithub.com/oxc-project/oxc/commit/a6e9769) linter/jsx-a11y: Add `label-has-associated-control` ([#&#8203;5163](https://togithub.com/oxc-project/oxc/issues/5163)) (Billy Levin)
-   [`c8e8532`](https://togithub.com/oxc-project/oxc/commit/c8e8532) linter/unicorn: Add fixer to `throw-new-error` ([#&#8203;5275](https://togithub.com/oxc-project/oxc/issues/5275)) (camc314)
-   [`7ccde4b`](https://togithub.com/oxc-project/oxc/commit/7ccde4b) linter/unicorn: Add fixer to `prefer-date-now` ([#&#8203;5147](https://togithub.com/oxc-project/oxc/issues/5147)) (camc314)

##### Bug Fixes

-   [`fdef8ae`](https://togithub.com/oxc-project/oxc/commit/fdef8ae) linter: Jest/vitest rule compat ([#&#8203;4797](https://togithub.com/oxc-project/oxc/issues/4797)) (cinchen)
-   [`76e86f8`](https://togithub.com/oxc-project/oxc/commit/76e86f8) linter: Eslint-plugin-unicorn prefer-spread wrong linter suggestion on variables of type string ([#&#8203;5265](https://togithub.com/oxc-project/oxc/issues/5265)) (Arian94)
-   [`b39544e`](https://togithub.com/oxc-project/oxc/commit/b39544e) linter/jest: Fixer for `prefer-jest-mocked` creates invalid LHS expressions ([#&#8203;5243](https://togithub.com/oxc-project/oxc/issues/5243)) (camc314)
-   [`9953fa5`](https://togithub.com/oxc-project/oxc/commit/9953fa5) linter/no-null: Incorrect fixer for `NullLiteral` within `ReturnStatement` ([#&#8203;5247](https://togithub.com/oxc-project/oxc/issues/5247)) (Dunqing)
-   [`318479e`](https://togithub.com/oxc-project/oxc/commit/318479e) linter/no-unused-vars: Mark the class/function in the new expression as used ([#&#8203;5306](https://togithub.com/oxc-project/oxc/issues/5306)) (magic-akari)

##### Refactor

-   [`fa1d460`](https://togithub.com/oxc-project/oxc/commit/fa1d460) linter: Clean up Fixer and Message ([#&#8203;5308](https://togithub.com/oxc-project/oxc/issues/5308)) (DonIsaac)

### [`v0.9.0`](https://togithub.com/oxc-project/oxc/releases/tag/oxlint_v0.9.0): oxlint v0.9.0

[Compare Source](https://togithub.com/oxc-project/oxc/compare/oxlint_v0.8.0...oxlint_v0.9.0)

#### \[0.9.0] - 2024-08-26

This release introduces `no-unused-vars` as a `correctness` rule and parsing regular expressions for syntax errors, both may produce false positives. Feel free to submit an issue.

-   [`5946748`](https://togithub.com/oxc-project/oxc/commit/5946748) linter: \[**BREAKING**] Parse and display syntax errors for regular expressions ([#&#8203;5214](https://togithub.com/oxc-project/oxc/issues/5214)) (Boshen)

![image](https://togithub.com/user-attachments/assets/7d68ccde-9e04-4ea8-8d0a-edf20e028259)

-   [`b894d3b`](https://togithub.com/oxc-project/oxc/commit/b894d3b) linter: \[**BREAKING**] Make `no-unused-vars` correctness ([#&#8203;5081](https://togithub.com/oxc-project/oxc/issues/5081)) (DonIsaac)

##### Features

-   [`1ce9630`](https://togithub.com/oxc-project/oxc/commit/1ce9630) linter/config: Implement FromIterator for LintPluginOptions ([#&#8203;5102](https://togithub.com/oxc-project/oxc/issues/5102)) (DonIsaac)
-   [`34bfaf6`](https://togithub.com/oxc-project/oxc/commit/34bfaf6) linter/react: Add fixer to `jsx-props-no-spread-multi` ([#&#8203;5145](https://togithub.com/oxc-project/oxc/issues/5145)) (camc314)
-   [`982bd6e`](https://togithub.com/oxc-project/oxc/commit/982bd6e) linter/unicorn: Add fixer to `require-array-join-separator` ([#&#8203;5152](https://togithub.com/oxc-project/oxc/issues/5152)) (camc314)
-   [`a6704bd`](https://togithub.com/oxc-project/oxc/commit/a6704bd) linter/unicorn: Add fixer to `prefer-set-size` ([#&#8203;5149](https://togithub.com/oxc-project/oxc/issues/5149)) (camc314)
-   [`ac7edcc`](https://togithub.com/oxc-project/oxc/commit/ac7edcc) linter/unicorn: Add fixer to `prefer-array-some` ([#&#8203;5153](https://togithub.com/oxc-project/oxc/issues/5153)) (camc314)
-   [`1d01aa3`](https://togithub.com/oxc-project/oxc/commit/1d01aa3) linter/unicorn: Add partial fixer for `prefer-array-flat` ([#&#8203;5143](https://togithub.com/oxc-project/oxc/issues/5143)) (camc314)
-   [`22d57f9`](https://togithub.com/oxc-project/oxc/commit/22d57f9) linter/unicorn: Add fixer to `prefer-string-slice` ([#&#8203;5150](https://togithub.com/oxc-project/oxc/issues/5150)) (Cameron)
-   [`2fe4415`](https://togithub.com/oxc-project/oxc/commit/2fe4415) linter/unicorn: Add fixer to `no-redundant-roles` ([#&#8203;5146](https://togithub.com/oxc-project/oxc/issues/5146)) (Cameron)
-   [`d35c6f5`](https://togithub.com/oxc-project/oxc/commit/d35c6f5) linter/unicorn: Add fixer to `prefer-regexp-test` ([#&#8203;5151](https://togithub.com/oxc-project/oxc/issues/5151)) (Cameron)
-   [`27db769`](https://togithub.com/oxc-project/oxc/commit/27db769) linter/unicorn: Add fixer to `text-encoding-identifier-case` ([#&#8203;5154](https://togithub.com/oxc-project/oxc/issues/5154)) (Cameron)
-   [`f7958c4`](https://togithub.com/oxc-project/oxc/commit/f7958c4) linter/unicorn: Add prefer-structured-clone ([#&#8203;5095](https://togithub.com/oxc-project/oxc/issues/5095)) (Jelle van der Waa)
-   [`004ffa0`](https://togithub.com/oxc-project/oxc/commit/004ffa0) linter/vitest: Implement `prefer-each` ([#&#8203;5203](https://togithub.com/oxc-project/oxc/issues/5203)) (dalaoshu)

##### Bug Fixes

-   [`aaaf26c`](https://togithub.com/oxc-project/oxc/commit/aaaf26c) linter: Error in fixer for prefer-to-have-length ([#&#8203;5197](https://togithub.com/oxc-project/oxc/issues/5197)) (dalaoshu)
-   [`1f5b6b6`](https://togithub.com/oxc-project/oxc/commit/1f5b6b6) linter: Bug in fixer for prefer-to-have-length ([#&#8203;5164](https://togithub.com/oxc-project/oxc/issues/5164)) (dalaoshu)
-   [`7eb052e`](https://togithub.com/oxc-project/oxc/commit/7eb052e) linter: `no-hex-escape` fixer removing regex flags ([#&#8203;5137](https://togithub.com/oxc-project/oxc/issues/5137)) (Cameron)
-   [`76c66b4`](https://togithub.com/oxc-project/oxc/commit/76c66b4) linter/max-lines: Point span to end of file for disable directive to work ([#&#8203;5117](https://togithub.com/oxc-project/oxc/issues/5117)) (Boshen)
-   [`8ff6f2c`](https://togithub.com/oxc-project/oxc/commit/8ff6f2c) linter/no-unused-vars: Panic on UsingDeclarations ([#&#8203;5206](https://togithub.com/oxc-project/oxc/issues/5206)) (DonIsaac)
-   [`d29042e`](https://togithub.com/oxc-project/oxc/commit/d29042e) linter/no-unused-vars: Function expression in implicit arrow function return ([#&#8203;5155](https://togithub.com/oxc-project/oxc/issues/5155)) (DonIsaac)
-   [`36e4a28`](https://togithub.com/oxc-project/oxc/commit/36e4a28) linter/no-unused-vars: Panic in variable declarator usage checks ([#&#8203;5160](https://togithub.com/oxc-project/oxc/issues/5160)) (DonIsaac)
-   [`ba62a71`](https://togithub.com/oxc-project/oxc/commit/ba62a71) linter/react: Fixed false positive with missing key inside React.Children.toArray() for fragments  ([#&#8203;5133](https://togithub.com/oxc-project/oxc/issues/5133)) (Earl Chase)
-   [`fd1031a`](https://togithub.com/oxc-project/oxc/commit/fd1031a) linter/unicorn: Breaking fixer in case statements for `no-null` ([#&#8203;5176](https://togithub.com/oxc-project/oxc/issues/5176)) (DonIsaac)
-   [`7b86ed6`](https://togithub.com/oxc-project/oxc/commit/7b86ed6) linter/unicorn: Handle type casts and parens in `no-null` ([#&#8203;5175](https://togithub.com/oxc-project/oxc/issues/5175)) (Don Isaac)
-   [`b629e16`](https://togithub.com/oxc-project/oxc/commit/b629e16) linter/unicorn: Improve diagnostic message for `no-null` ([#&#8203;5172](https://togithub.com/oxc-project/oxc/issues/5172)) (DonIsaac)

##### Performance

-   [`ce454cf`](https://togithub.com/oxc-project/oxc/commit/ce454cf) Use simdutf8 to validate UTF-8 when reading files  ([#&#8203;5196](https://togithub.com/oxc-project/oxc/issues/5196)) (dalaoshu)

##### Refactor

-   [`543cad6`](https://togithub.com/oxc-project/oxc/commit/543cad6) codegen: Remove some pub APIs (Boshen)
-   [`0d3661a`](https://togithub.com/oxc-project/oxc/commit/0d3661a) linter: Remove meaningless `span0` ([#&#8203;5209](https://togithub.com/oxc-project/oxc/issues/5209)) (dalaoshu)
-   [`2a91ef1`](https://togithub.com/oxc-project/oxc/commit/2a91ef1) linter: `eslint/no_redeclare` rule use `run_on_symbol` not `run_once` ([#&#8203;5201](https://togithub.com/oxc-project/oxc/issues/5201)) (overlookmotel)
-   [`33599b0`](https://togithub.com/oxc-project/oxc/commit/33599b0) linter: Split options into multiple files ([#&#8203;5101](https://togithub.com/oxc-project/oxc/issues/5101)) (DonIsaac)
-   [`7ab6152`](https://togithub.com/oxc-project/oxc/commit/7ab6152) linter/unicorn: Clean up `no-null` ([#&#8203;5174](https://togithub.com/oxc-project/oxc/issues/5174)) (DonIsaac)

##### Testing

-   [`a877e5a`](https://togithub.com/oxc-project/oxc/commit/a877e5a) linter/no-unused-vars: Ensure type annotations on property accessors are considered used ([#&#8203;5183](https://togithub.com/oxc-project/oxc/issues/5183)) (DonIsaac)
-   [`7886618`](https://togithub.com/oxc-project/oxc/commit/7886618) linter/unicorn: Add fixer tests for `no-null` ([#&#8203;5173](https://togithub.com/oxc-project/oxc/issues/5173)) (DonIsaac)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguNTYuMCIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-30 04:46:09 +00:00
renovate
69892655a1 chore: bump up valtio version to v2 (#8025)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [valtio](https://togithub.com/pmndrs/valtio) | [`^1.13.2` -> `^2.0.0`](https://renovatebot.com/diffs/npm/valtio/1.13.2/2.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/valtio/2.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/valtio/2.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/valtio/1.13.2/2.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/valtio/1.13.2/2.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>pmndrs/valtio (valtio)</summary>

### [`v2.0.0`](https://togithub.com/pmndrs/valtio/releases/tag/v2.0.0)

[Compare Source](https://togithub.com/pmndrs/valtio/compare/v1.13.2...v2.0.0)

### 🎉🎉🎉 Valtio v2 is Here! 🍾🍾🍾

#### Small Breaking Changes

Most users won't even notice the differences, but we recommend checking out the [migration guide](https://togithub.com/pmndrs/valtio/blob/main/docs/guides/migrating-to-v2.mdx) to ensure a smooth transition.

#### New Emoji

💊 -> 🧙

Say hello to our new emoji! This change symbolizes the magic of Valtio.

#### Let’s Grow the Ecosystem Together!

We are entering a new era of Valtio development, and we need your help to grow the ecosystem. Whether you are an experienced contributor or just getting started, now is the perfect time to join us!

#### What's Changed

-   v2 by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/valtio/pull/810](https://togithub.com/pmndrs/valtio/pull/810)
-   feat(core): expose internal states and functions by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/valtio/pull/931](https://togithub.com/pmndrs/valtio/pull/931)
-   breaking(vanilla): do not handle promises by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/valtio/pull/934](https://togithub.com/pmndrs/valtio/pull/934)

#### New Contributors

-   [@&#8203;AmirSa12](https://togithub.com/AmirSa12) made their first contribution in [https://github.com/pmndrs/valtio/pull/898](https://togithub.com/pmndrs/valtio/pull/898)
-   [@&#8203;TotallyBiased](https://togithub.com/TotallyBiased) made their first contribution in [https://github.com/pmndrs/valtio/pull/901](https://togithub.com/pmndrs/valtio/pull/901)
-   [@&#8203;L-Qun](https://togithub.com/L-Qun) made their first contribution in [https://github.com/pmndrs/valtio/pull/908](https://togithub.com/pmndrs/valtio/pull/908)
-   [@&#8203;himself65](https://togithub.com/himself65) made their first contribution in [https://github.com/pmndrs/valtio/pull/920](https://togithub.com/pmndrs/valtio/pull/920)
-   [@&#8203;kciter](https://togithub.com/kciter) made their first contribution in [https://github.com/pmndrs/valtio/pull/922](https://togithub.com/pmndrs/valtio/pull/922)

**Full Changelog**: https://github.com/pmndrs/valtio/compare/v1.13.2...v2.0.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC41Ni4wIiwidXBkYXRlZEluVmVyIjoiMzguNTYuMCIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-30 04:34:04 +00:00
JimmFly
f99988afa6 feat(core): bump blocksuite/icons (#8024) 2024-08-30 03:42:52 +00:00
pengx17
4ff6fbd052 fix(core): hairline boarders for divider (#8021) 2024-08-30 02:31:28 +00:00
pengx17
f544e69d02 fix(mobile): modal styles on mobile (#8023)
<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/T2klNLEk0wxLh4NRDzhk/92c0cc55-1f75-42b7-a83f-4ffa6cf205ad.mp4">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/T2klNLEk0wxLh4NRDzhk/92c0cc55-1f75-42b7-a83f-4ffa6cf205ad.mp4">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/92c0cc55-1f75-42b7-a83f-4ffa6cf205ad.mp4">20240829-1420-07.7370936.mp4</video>
2024-08-29 16:45:23 +00:00
pengx17
adf314d594 fix(mobile): adjust peek view style for mobile (#8003)
![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/c3a04128-0309-4df6-ab6d-0a5129483c73.png)
2024-08-29 16:45:22 +00:00
pengx17
7ae141bd9e feat(mobile): add mobile detail page (#7993)
fix AF-1241
2024-08-29 16:45:22 +00:00
pengx17
f8e6f1f2b5 chore: add mobile scope (#8020) 2024-08-29 16:45:21 +00:00
CatsJuice
f1bb1fc9b8 feat(mobile): search page ui (#8012)
feat(mobile): search page ui

fix(core): quick search tags performance issue
2024-08-29 09:05:23 +00:00
JimmFly
5e8683c9be feat(core): add outgoing links to doc info (#7955)
close AF-1270

![CleanShot 2024-08-23 at 13 22 38@2x](https://github.com/user-attachments/assets/7eb21db5-ab33-41ad-a51a-fd2cf46a0e30)
2024-08-29 06:41:41 +00:00
CatsJuice
3ce92f2abc feat(mobile): all docs page ui impl (#7976) 2024-08-29 06:09:48 +00:00
CatsJuice
db76780bc9 feat(mobile): mobile index page UI (#7959) 2024-08-29 06:09:47 +00:00
CatsJuice
f37051dc87 feat(core): mobile renderer for explorer (#7942) 2024-08-29 06:09:45 +00:00
EYHN
b96ad57568 feat(core): import template (#8000) 2024-08-29 04:01:35 +00:00
JimmFly
4ec45a247e feat(core): add sign in button to shared doc (#7952)
![CleanShot 2024-08-23 at 12 05 12@2x](https://github.com/user-attachments/assets/2c146707-9551-4044-b289-0904653f30f2)
2024-08-29 02:44:06 +00:00
darkskygit
dde45748d9 feat: filter out empty workpace in sidebar list (#7960)
fix PD-1567
2024-08-28 08:43:44 +00:00
L-Sun
06685683ae fix(core): add mobile edit button (#7996) 2024-08-28 06:38:45 +00:00
JimmFly
65a87196d5 feat(core): impl the Doc Info and Bi-Directional Links display settings (#7991)
https://github.com/user-attachments/assets/a469254c-a2ea-4cf4-837e-f9a8bbe5b378
2024-08-28 02:35:29 +00:00
JimmFly
09ab922572 feat(core): add new doc default mode setting (#7990)
https://github.com/user-attachments/assets/523b14f3-ee42-4061-8ca2-221e071d5cc9
2024-08-28 02:35:28 +00:00
JimmFly
c53adbc7e8 chore: adjust font menu and slider style (#7989)
![CleanShot 2024-08-27 at 15 52 09@2x](https://github.com/user-attachments/assets/69c8a340-0d59-4d8d-846e-73dc81f2800a)
![CleanShot 2024-08-27 at 15 52 39@2x](https://github.com/user-attachments/assets/2177f267-bdc1-459b-b043-868642b08d9a)
2024-08-28 02:35:26 +00:00
JimmFly
03b2cda845 refactor(core): move fontFamily and fullWidthLayout to editor settings (#7988) 2024-08-28 02:35:24 +00:00
EYHN
3e810eb043 fix(core): no share page in desktop (#7983) 2024-08-27 12:37:30 +00:00
JimmFly
b8f07ce3fc chore(core): disable expand database block (#7984)
close AF-1271
2024-08-27 12:24:48 +00:00
darkskygit
10a066a52a fix(native): return type casts (#7986) 2024-08-27 05:53:05 +00:00
DarkSky
6557b5d4b6 fix: native binding (#7985) 2024-08-27 12:31:25 +08:00
Brooooooklyn
67c9c7bcc5 ci: send slack message to channel after deploy (#7889) 2024-08-27 03:01:55 +00:00
renovate
e44a9483c2 chore: bump up @marsidev/react-turnstile version to v1 (#7940)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@marsidev/react-turnstile](https://togithub.com/marsidev/react-turnstile) | [`^0.7.0` -> `^1.0.0`](https://renovatebot.com/diffs/npm/@marsidev%2freact-turnstile/0.7.2/1.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@marsidev%2freact-turnstile/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@marsidev%2freact-turnstile/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@marsidev%2freact-turnstile/0.7.2/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@marsidev%2freact-turnstile/0.7.2/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>marsidev/react-turnstile (@&#8203;marsidev/react-turnstile)</summary>

### [`v1.0.0`](https://togithub.com/marsidev/react-turnstile/releases/tag/v1.0.0)

[Compare Source](https://togithub.com/marsidev/react-turnstile/compare/v0.7.2...v1.0.0)

##### 🚨 Breaking Changes

-   Now we ship ESM-only code, this will decrease the bundle size significantly.
    If you are a CommonJS user, I suggest you to keep using the version `0.7.2` or upgrade your project to ESM.

-   Removed "auto" widget size due to is not even a valid size for Cloudflare Turnstile.
    We have been sending `undefined` when the size was "auto", so if you were using this size, then you can simply remove it.

-   Peer dependencies for `react` and `react-dom` have been updated to 17.x and above.

##### 🚀 Features

-   Added callback `onTimeout`
-   Added render options `refreshTimeout` and `feedbackEnabled` (Closes [#&#8203;82](https://togithub.com/marsidev/react-turnstile/issues/82))
-   Added new "flexible" widget size (Closes [#&#8203;82](https://togithub.com/marsidev/react-turnstile/issues/82))

##### 🐛 Fixes

-   Updated "compact" widget size to 150x140 (Closes [#&#8203;85](https://togithub.com/marsidev/react-turnstile/issues/85))

##### 🛠 Misc

##### Build

-   We migrated from [unbuild](https://togithub.com/unjs/unbuild) to [tsup](https://togithub.com/egoist/tsup)
-   The generated build is now minified, this will decrease the bundle size significantly.

##### TypeScript

-   Improved type definitions. Now we expose these types: `AppearanceMode`, `ExecutionMode`, `FailureRetryMode`, `RefreshExpiredMode`, `RefreshTimeoutMode`, `WidgetSize`. Inspired by [@&#8203;types/cloudflare-turnstile](https://www.npmjs.com/package/@&#8203;types/cloudflare-turnstile)

##### Other

-   Updated dependencies
-   Updated docs
-   Added issue templates and policies

#####     [View changes on GitHub](https://togithub.com/marsidev/react-turnstile/compare/v0.7.2...v1.0.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-27 02:50:53 +00:00
renovate
ecf50a4dad chore: bump up happy-dom version to v15 (#7941)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [happy-dom](https://togithub.com/capricorn86/happy-dom) | [`^14.7.1` -> `^15.0.0`](https://renovatebot.com/diffs/npm/happy-dom/14.12.3/15.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/happy-dom/15.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/happy-dom/15.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/happy-dom/14.12.3/15.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/happy-dom/14.12.3/15.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>capricorn86/happy-dom (happy-dom)</summary>

### [`v15.0.0`](https://togithub.com/capricorn86/happy-dom/releases/tag/v15.0.0)

[Compare Source](https://togithub.com/capricorn86/happy-dom/compare/v14.12.3...v15.0.0)

##### 💣 Breaking Changes

-   Implements remaining HTML elements - By **[@&#8203;betterqualityassuranceuser](https://togithub.com/betterqualityassuranceuser)** in task [#&#8203;1332](https://togithub.com/capricorn86/happy-dom/issues/1332)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-27 02:40:19 +00:00
forehalo
0209e3fa76 fix(core): avoid expand runtime config everywhere used (#7972) 2024-08-26 12:22:52 +00:00
EYHN
9ea4aaaf37 refactor(infra): remove setimmediate (#7975) 2024-08-26 11:57:24 +00:00
pengx17
611925fa10 fix(electron): adjust app-tabs-header styles (#7961)
![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/6dc54c24-e90f-4c3f-a743-ce7f4512e616.png)

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/3cbfe8f8-d4b8-4167-b557-89184bdcce9c.png)

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/28ba3ad1-22a7-487a-a9a4-d53a658457f9.png)

also fix PD-1631
2024-08-26 09:34:27 +00:00
EYHN
bc86f0a672 feat(core): editor setting service (#7956)
define editor setting schema in `packages/frontend/core/src/modules/editor-settting/schema.ts`

e.g.

```ts
const BSEditorSettingSchema = z.object({
  connector: z.object({
    stroke: z
      .union([
        z.string(),
        z.object({
          dark: z.string(),
          light: z.string(),
        }),
      ])
      .default('#000000'), // default is necessary
  }),
});
```

schema can be defined in a nested way. EditorSetting api is in flat way:

editorSetting api:

```ts
editorSetting.settings$ === {
  'connector.stroke': '#000000'
}
editorSetting.set('connector.stroke', '#000')
```

and use `expandFlattenObject` function can restore the flattened structure to a nested structure. nested structure is required by blocksuite

```ts
editorSetting.settings$.map(expandFlattenObject) === {
  connector: {
    stroke: '#000000'
  }
}
```
2024-08-26 08:19:24 +00:00
JimmFly
3c37006657 chore(core): add Display bi-directional links setting row ui (#7954)
close AF-1269

![CleanShot 2024-08-23 at 12 59 50@2x](https://github.com/user-attachments/assets/bcdc70c4-029e-4254-8367-a390a244e30b)
2024-08-26 06:25:32 +00:00
Don Isaac
dbcfd24ed8 fix: remove unused variables (#7968) 2024-08-26 14:23:56 +08:00
forehalo
14066965fa fix(server): wrong table used for userspace data (#7969) 2024-08-26 06:11:22 +00:00
renovate
01c9d1758e chore: bump up Rust crate sqlx to 0.8 [SECURITY] (#7965)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [sqlx](https://togithub.com/launchbadge/sqlx) | workspace.dependencies | minor | `0.7` -> `0.8` |

### GitHub Vulnerability Alerts

#### [GHSA-xmrp-424f-vfpx](https://togithub.com/launchbadge/sqlx/issues/3440)

The following presentation at this year's DEF CON was brought to our attention on the SQLx Discord:

> SQL Injection isn't Dead: Smuggling Queries at the Protocol Level
> <http://web.archive.org/web/20240812130923/https://media.defcon.org/DEF%20CON%2032/DEF%20CON%2032%20presentations/DEF%20CON%2032%20-%20Paul%20Gerste%20-%20SQL%20Injection%20Isn't%20Dead%20Smuggling%20Queries%20at%20the%20Protocol%20Level.pdf>
> (Archive link for posterity.)

Essentially, encoding a value larger than 4GiB can cause the length prefix in the protocol to overflow,
causing the server to interpret the rest of the string as binary protocol commands or other data.

It appears SQLx _does_ perform truncating casts in a way that could be problematic,
for example: <6f2905695b/sqlx-postgres/src/arguments.rs (L163)>

This code has existed essentially since the beginning,
so it is reasonable to assume that all published versions `<= 0.8.0` are affected.

## Mitigation

As always, you should make sure your application is validating untrustworthy user input.
Reject any input over 4 GiB, or any input that could _encode_ to a string longer than 4 GiB.
Dynamically built queries are also potentially problematic if it pushes the message size over this 4 GiB bound.

[`Encode::size_hint()`](https://docs.rs/sqlx/latest/sqlx/trait.Encode.html#method.size_hint)
can be used for sanity checks, but do not assume that the size returned is accurate.
For example, the `Json<T>` and `Text<T>` adapters have no reasonable way to predict or estimate the final encoded size,
so they just return `size_of::<T>()` instead.

For web application backends, consider adding some middleware that limits the size of request bodies by default.

## Resolution

Work has started on a branch to add `#[deny]` directives for the following Clippy lints:

* [`cast_possible_truncation`](https://rust-lang.github.io/rust-clippy/master/#/cast_possible_truncation)
* [`cast_possible_wrap`](https://rust-lang.github.io/rust-clippy/master/#/cast_possible_wrap)
* [`cast_sign_loss`](https://rust-lang.github.io/rust-clippy/master/#/cast_sign_loss)

and to manually audit the code that they flag.

A fix is expected to be included in the `0.8.1` release (still WIP as of writing).

---

### Release Notes

<details>
<summary>launchbadge/sqlx (sqlx)</summary>

### [`v0.8.1`](https://togithub.com/launchbadge/sqlx/blob/HEAD/CHANGELOG.md#081---2024-08-23)

[Compare Source](https://togithub.com/launchbadge/sqlx/compare/v0.8.0...v0.8.1)

16 pull requests were merged this release cycle.

This release contains a fix for [RUSTSEC-2024-0363].

Postgres users are advised to upgrade ASAP as a possible exploit has been demonstrated:
[#&#8203;3440 (comment)](https://togithub.com/launchbadge/sqlx/issues/3440#issuecomment-2307956901)

MySQL and SQLite do not *appear* to be exploitable, but upgrading is recommended nonetheless.

##### Added

-   \[[#&#8203;3421]]: correct spelling of `MySqlConnectOptions::no_engine_substitution()` \[\[[@&#8203;kolinfluence](https://togithub.com/kolinfluence)]]
    -   Deprecates `MySqlConnectOptions::no_engine_subsitution()` (oops) in favor of the correctly spelled version.

##### Changed

-   \[[#&#8203;3376]]: doc: hide `spec_error` module \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
    -   This is a helper module for the macros and was not meant to be exposed.
    -   It is not expected to receive any breaking changes for the 0.8.x release, but is not designed as a public API.
        Use at your own risk.
-   \[[#&#8203;3382]]: feat: bumped to `libsqlite3-sys=0.30.1` to support sqlite 3.46 \[\[[@&#8203;CommanderStorm](https://togithub.com/CommanderStorm)]]
-   \[[#&#8203;3385]]: chore(examples):Migrated the pg-chat example to ratatui \[\[[@&#8203;CommanderStorm](https://togithub.com/CommanderStorm)]]
-   \[[#&#8203;3399]]: Upgrade to rustls 0.23 \[\[[@&#8203;djc](https://togithub.com/djc)]]
    -   RusTLS now has pluggable cryptography providers: `ring` (the existing implementation),
        and `aws-lc-rs` which has optional FIPS certification.
    -   The existing features activating RusTLS (`runtime-tokio-rustls`, `runtime-async-std-rustls`, `tls-rustls`)
        enable the `ring` provider of RusTLS to match the existing behavior so this *should not* be a breaking change.
    -   Switch to the `tls-rustls-aws-lc-rs` feature to use the `aws-lc-rs` provider.
        -   If using `runtime-tokio-rustls` or `runtime-async-std-rustls`,
            this will necessitate switching to the appropriate non-legacy runtime feature:
            `runtime-tokio` or `runtime-async-std`
    -   See the RusTLS README for more details: <https://github.com/rustls/rustls?tab=readme-ov-file#cryptography-providers>

##### Fixed

-   \[[#&#8203;2786]]: fix(sqlx-cli): do not clean sqlx during prepare \[\[[@&#8203;cycraig](https://togithub.com/cycraig)]]
-   \[[#&#8203;3354]]: sqlite: fix inconsistent read-after-write \[\[[@&#8203;ckampfe](https://togithub.com/ckampfe)]]
-   \[[#&#8203;3371]]: Fix encoding and decoding of MySQL enums in `sqlx::Type` \[\[[@&#8203;alu](https://togithub.com/alu)]]
-   \[[#&#8203;3374]]: fix: usage of `node12` in `SQLx` action \[\[[@&#8203;hamirmahal](https://togithub.com/hamirmahal)]]
-   \[[#&#8203;3380]]: chore: replace structopt with clap in examples \[\[[@&#8203;tottoto](https://togithub.com/tottoto)]]
-   \[[#&#8203;3381]]: Fix CI after Rust 1.80, remove dead feature references \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
-   \[[#&#8203;3384]]: chore(tests): fixed deprecation warnings \[\[[@&#8203;CommanderStorm](https://togithub.com/CommanderStorm)]]
-   \[[#&#8203;3386]]: fix(dependencys):bumped cargo_metadata to `v0.18.1` to avoid yanked `v0.14.3` \[\[[@&#8203;CommanderStorm](https://togithub.com/CommanderStorm)]]
-   \[[#&#8203;3389]]: fix(cli): typo in error for required DB URL \[\[[@&#8203;ods](https://togithub.com/ods)]]
-   \[[#&#8203;3417]]: Update version to 0.8 in README \[\[[@&#8203;soucosmo](https://togithub.com/soucosmo)]]
-   \[[#&#8203;3441]]: fix: audit protocol handling \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
    -   This addresses [RUSTSEC-2024-0363] and includes regression tests for MySQL, Postgres and SQLite.

[#&#8203;2786]: https://togithub.com/launchbadge/sqlx/pull/2786

[#&#8203;3354]: https://togithub.com/launchbadge/sqlx/pull/3354

[#&#8203;3371]: https://togithub.com/launchbadge/sqlx/pull/3371

[#&#8203;3374]: https://togithub.com/launchbadge/sqlx/pull/3374

[#&#8203;3376]: https://togithub.com/launchbadge/sqlx/pull/3376

[#&#8203;3380]: https://togithub.com/launchbadge/sqlx/pull/3380

[#&#8203;3381]: https://togithub.com/launchbadge/sqlx/pull/3381

[#&#8203;3382]: https://togithub.com/launchbadge/sqlx/pull/3382

[#&#8203;3384]: https://togithub.com/launchbadge/sqlx/pull/3384

[#&#8203;3385]: https://togithub.com/launchbadge/sqlx/pull/3385

[#&#8203;3386]: https://togithub.com/launchbadge/sqlx/pull/3386

[#&#8203;3389]: https://togithub.com/launchbadge/sqlx/pull/3389

[#&#8203;3399]: https://togithub.com/launchbadge/sqlx/pull/3399

[#&#8203;3417]: https://togithub.com/launchbadge/sqlx/pull/3417

[#&#8203;3421]: https://togithub.com/launchbadge/sqlx/pull/3421

[#&#8203;3441]: https://togithub.com/launchbadge/sqlx/pull/3441

[RUSTSEC-2024-0363]: https://rustsec.org/advisories/RUSTSEC-2024-0363.html

### [`v0.8.0`](https://togithub.com/launchbadge/sqlx/blob/HEAD/CHANGELOG.md#080---2024-07-22)

[Compare Source](https://togithub.com/launchbadge/sqlx/compare/v0.7.4...v0.8.0)

70 pull requests were merged this release cycle.

[#&#8203;2697] was merged the same day as release 0.7.4 and so was missed by the automatic CHANGELOG generation.

##### Breaking

-   \[[#&#8203;2697]]: fix(macros): only enable chrono when time is disabled \[\[[@&#8203;saiintbrisson](https://togithub.com/saiintbrisson)]]
-   \[[#&#8203;2973]]: Generic Associated Types in Database, replacing HasValueRef, HasArguments, HasStatement \[\[[@&#8203;nitn3lav](https://togithub.com/nitn3lav)]]
-   \[[#&#8203;2482]]: chore: bump syn to 2.0 \[\[[@&#8203;saiintbrisson](https://togithub.com/saiintbrisson)]]
    -   Deprecated type ascription syntax in the query macros was removed.
-   \[[#&#8203;2736]]: Fix describe on PostgreSQL views with rules \[\[[@&#8203;tsing](https://togithub.com/tsing)]]
    -   Potentially breaking: nullability inference changes for Postgres.
-   \[[#&#8203;2869]]: Implement PgHasArrayType for all references \[\[[@&#8203;tylerhawkes](https://togithub.com/tylerhawkes)]]
    -   Conflicts with existing manual implementations.
-   \[[#&#8203;2940]]: fix: Decode and Encode derives ([#&#8203;1031](https://togithub.com/launchbadge/sqlx/issues/1031)) \[\[[@&#8203;benluelo](https://togithub.com/benluelo)]]
    -   Changes lifetime obligations for field types.
-   \[[#&#8203;3064]]: Sqlite explain graph \[\[[@&#8203;tyrelr](https://togithub.com/tyrelr)]]
    -   Potentially breaking: nullability inference changes for SQLite.
-   \[[#&#8203;3123]]: Reorder attrs in sqlx::test macro \[\[[@&#8203;bobozaur](https://togithub.com/bobozaur)]]
    -   Potentially breaking: attributes on `#[sqlx::test]` usages are applied in the correct order now.
-   \[[#&#8203;3126]]: Make Encode return a result \[\[[@&#8203;FSMaxB](https://togithub.com/FSMaxB)]]
-   \[[#&#8203;3130]]: Add version information for failed cli migration ([#&#8203;3129](https://togithub.com/launchbadge/sqlx/issues/3129)) \[\[[@&#8203;FlakM](https://togithub.com/FlakM)]]
    -   Breaking changes to `MigrateError`.
-   \[[#&#8203;3181]]: feat: no tx migration \[\[[@&#8203;cleverjam](https://togithub.com/cleverjam)]]
    -   (Postgres only) migrations that should not run in a transaction can be flagged by adding `-- no-transaction` to the beginning.
    -   Breaking change: added field to `Migration`
-   \[[#&#8203;3184]]: \[BREAKING} fix(sqlite): always use `i64` as intermediate when decoding \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
    -   integer decoding will now loudly error on overflow instead of silently truncating.
    -   some usages of the query!() macros might change an i32 to an i64.
-   \[[#&#8203;3252]]: fix `#[derive(sqlx::Type)]` in Postgres \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
    -   Manual implementations of PgHasArrayType for enums will conflict with the generated one. Delete the manual impl or add `#[sqlx(no_pg_array)]` where conflicts occur.
    -   Type equality for PgTypeInfo is now schema-aware.
-   \[[#&#8203;3329]]: fix: correct handling of arrays of custom types in Postgres \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
    -   Potential breaking change: `PgTypeInfo::with_name()` infers types that start with `_` to be arrays of the un-prefixed type. Wrap type names in quotes to bypass this behavior.
-   \[[#&#8203;3356]]: breaking: fix name collision in `FromRow`, return `Error::ColumnDecode` for `TryFrom` errors \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
    -   Breaking behavior change: errors with `#[sqlx(try_from = "T")]` now return `Error::ColumnDecode` instead of `Error::ColumnNotFound`.
    -   Breaking because `#[sqlx(default)]` on an individual field or the struct itself would have previously suppressed the error.
        This doesn't seem like good behavior as it could result in some potentially very difficult bugs.
        -   Instead, create a wrapper implementing `From` and apply the default explicitly.
-   \[[#&#8203;3337]]: allow rename with rename_all (close [#&#8203;2896](https://togithub.com/launchbadge/sqlx/issues/2896)) \[\[[@&#8203;DirectorX](https://togithub.com/DirectorX)]]
    -   Changes the precedence of `#[sqlx(rename)]` and `#[sqlx(rename_all)]` to match the expected behavior (`rename` wins).
-   \[[#&#8203;3285]]: fix: use correct names for sslmode options \[\[[@&#8203;lily-mosquitoes](https://togithub.com/lily-mosquitoes)]]
    -   Changes the output of `ConnectOptions::to_url_lossy()` to match what parsing expects.

##### Added

-   \[[#&#8203;2917]]: Add Debug impl for PgRow \[\[[@&#8203;g-bartoszek](https://togithub.com/g-bartoszek)]]
-   \[[#&#8203;3113]]: feat: new derive feature flag \[\[[@&#8203;saiintbrisson](https://togithub.com/saiintbrisson)]]
-   \[[#&#8203;3154]]: feat: add `MySqlTime`, audit `mysql::types` for panics \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
-   \[[#&#8203;3188]]: feat(cube): support postgres cube \[\[[@&#8203;jayy-lmao](https://togithub.com/jayy-lmao)]]
-   \[[#&#8203;3244]]: feat: support `NonZero*` scalar types \[\[[@&#8203;AlphaKeks](https://togithub.com/AlphaKeks)]]
-   \[[#&#8203;3260]]: feat: Add set_update_hook on SqliteConnection \[\[[@&#8203;gridbox](https://togithub.com/gridbox)]]
-   \[[#&#8203;3291]]: feat: support the Postgres Bool type for the Any driver \[\[[@&#8203;etorreborre](https://togithub.com/etorreborre)]]
-   \[[#&#8203;3293]]: Add LICENSE-\* files to crates \[\[[@&#8203;LecrisUT](https://togithub.com/LecrisUT)]]
-   \[[#&#8203;3303]]: add array support for NonZeroI\* in postgres \[\[[@&#8203;JohannesIBK](https://togithub.com/JohannesIBK)]]
-   \[[#&#8203;3311]]: Add example on how to use Transaction as Executor \[\[[@&#8203;Lachstec](https://togithub.com/Lachstec)]]
-   \[[#&#8203;3343]]: Add support for PostgreSQL HSTORE data type \[\[[@&#8203;KobusEllis](https://togithub.com/KobusEllis)]]

##### Changed

-   \[[#&#8203;2652]]: MySQL: Remove collation compatibility check for strings \[\[[@&#8203;alu](https://togithub.com/alu)]]
-   \[[#&#8203;2960]]: Removed `Send` trait bound from argument binding \[\[[@&#8203;bobozaur](https://togithub.com/bobozaur)]]
-   \[[#&#8203;2970]]: refactor: lift type mappings into driver crates \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
-   \[[#&#8203;3148]]: Bump libsqlite3-sys to v0.28 \[\[[@&#8203;NfNitLoop](https://togithub.com/NfNitLoop)]]
    -   Note: version bumps to `libsqlite3-sys` are not considered breaking changes as per our semver guarantees.
-   \[[#&#8203;3265]]: perf: box `MySqlConnection` to reduce sizes of futures \[\[[@&#8203;stepantubanov](https://togithub.com/stepantubanov)]]
-   \[[#&#8203;3352]]: chore:added a testcase for `sqlx migrate add ...` \[\[[@&#8203;CommanderStorm](https://togithub.com/CommanderStorm)]]
-   \[[#&#8203;3340]]: ci: Add job to check that sqlx builds with its declared minimum dependencies \[\[[@&#8203;iamjpotts](https://togithub.com/iamjpotts)]]

##### Fixed

-   \[[#&#8203;2702]]: Constrain cyclic associated types to themselves \[\[[@&#8203;BadBastion](https://togithub.com/BadBastion)]]
-   \[[#&#8203;2954]]: Fix several inter doc links \[\[[@&#8203;ralpha](https://togithub.com/ralpha)]]
-   \[[#&#8203;3073]]: feat(logging): Log slow acquires from connection pool \[\[[@&#8203;iamjpotts](https://togithub.com/iamjpotts)]]
-   \[[#&#8203;3137]]: SqliteConnectOptions::filename() memory fix ([#&#8203;3136](https://togithub.com/launchbadge/sqlx/issues/3136)) \[\[[@&#8203;hoxxep](https://togithub.com/hoxxep)]]
-   \[[#&#8203;3138]]: PostgreSQL Bugfix: Ensure connection is usable after failed COPY inside a transaction \[\[[@&#8203;feikesteenbergen](https://togithub.com/feikesteenbergen)]]
-   \[[#&#8203;3146]]: fix(sqlite): delete unused `ConnectionHandleRaw` type \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
-   \[[#&#8203;3162]]: Drop urlencoding dependency \[\[[@&#8203;paolobarbolini](https://togithub.com/paolobarbolini)]]
-   \[[#&#8203;3165]]: Bump deps that do not need code changes \[\[[@&#8203;GnomedDev](https://togithub.com/GnomedDev)]]
-   \[[#&#8203;3167]]: fix(ci): use `docker compose` instead of `docker-compose` \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
-   \[[#&#8203;3172]]: fix: Option decoding in any driver \[\[[@&#8203;pxp9](https://togithub.com/pxp9)]]
-   \[[#&#8203;3173]]: fix(postgres) : int type conversion while decoding \[\[[@&#8203;RaghavRox](https://togithub.com/RaghavRox)]]
-   \[[#&#8203;3190]]: Update time to 0.3.36 \[\[[@&#8203;BlackSoulHub](https://togithub.com/BlackSoulHub)]]
-   \[[#&#8203;3191]]: Fix unclean TLS shutdown \[\[[@&#8203;levkk](https://togithub.com/levkk)]]
-   \[[#&#8203;3194]]: Fix leaking connections in fetch_optional ([#&#8203;2647](https://togithub.com/launchbadge/sqlx/issues/2647)) \[\[[@&#8203;danjpgriffin](https://togithub.com/danjpgriffin)]]
-   \[[#&#8203;3216]]: security: bump rustls to 0.21.11 \[\[[@&#8203;toxeus](https://togithub.com/toxeus)]]
-   \[[#&#8203;3230]]: fix: sqlite pragma order for auto_vacuum \[\[[@&#8203;jasonish](https://togithub.com/jasonish)]]
-   \[[#&#8203;3233]]: fix: get_filename should not consume self \[\[[@&#8203;jasonish](https://togithub.com/jasonish)]]
-   \[[#&#8203;3234]]: fix(ci): pin Rust version, ditch unmaintained actions \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
-   \[[#&#8203;3236]]: fix: resolve `path` ownership problems when using `sqlx_macros_unstable` \[\[[@&#8203;lily-mosquitoes](https://togithub.com/lily-mosquitoes)]]
-   \[[#&#8203;3254]]: fix: hide `sqlx_postgres::any` \[\[[@&#8203;Zarathustra2](https://togithub.com/Zarathustra2)]]
-   \[[#&#8203;3266]]: ci: MariaDB - add back 11.4 and add 11.5 \[\[[@&#8203;grooverdan](https://togithub.com/grooverdan)]]
-   \[[#&#8203;3267]]: ci: syntax fix \[\[[@&#8203;grooverdan](https://togithub.com/grooverdan)]]
-   \[[#&#8203;3271]]: docs(sqlite): fix typo - unixtime() -> unixepoch() \[\[[@&#8203;joelkoen](https://togithub.com/joelkoen)]]
-   \[[#&#8203;3276]]: Invert boolean for `migrate` error message. ([#&#8203;3275](https://togithub.com/launchbadge/sqlx/issues/3275)) \[\[[@&#8203;nk9](https://togithub.com/nk9)]]
-   \[[#&#8203;3279]]: fix Clippy errors \[\[[@&#8203;abonander](https://togithub.com/abonander)]]
-   \[[#&#8203;3288]]: fix: sqlite update_hook char types \[\[[@&#8203;jasonish](https://togithub.com/jasonish)]]
-   \[[#&#8203;3297]]: Pass the `persistent` query setting when preparing queries with the `Any` driver \[\[[@&#8203;etorreborre](https://togithub.com/etorreborre)]]
-   \[[#&#8203;3298]]: Track null arguments in order to provide the appropriate type when converting them. \[\[[@&#8203;etorreborre](https://togithub.com/etorreborre)]]
-   \[[#&#8203;3312]]: doc: Minor rust docs fixes \[\[[@&#8203;SrGesus](https://togithub.com/SrGesus)]]
-   \[[#&#8203;3327]]: chore: fixed one usage of `select_input_type!()` being unhygenic \[\[[@&#8203;CommanderStorm](https://togithub.com/CommanderStorm)]]
-   \[[#&#8203;3328]]: fix(ci): comment not separated from other characters \[\[[@&#8203;hamirmahal](https://togithub.com/hamirmahal)]]
-   \[[#&#8203;3341]]: refactor: Resolve cargo check warnings in postgres examples \[\[[@&#8203;iamjpotts](https://togithub.com/iamjpotts)]]
-   \[[#&#8203;3346]]: fix(postgres): don't panic if `M` or `C` Notice fields are not UTF-8 \[\[[@&#8203;YgorSouza](https://togithub.com/YgorSouza)]]
-   \[[#&#8203;3350]]: fix:the `json`-feature should activate `sqlx-postgres?/json` as well \[\[[@&#8203;CommanderStorm](https://togithub.com/CommanderStorm)]]
-   \[[#&#8203;3353]]: fix: build script new line at eof \[\[[@&#8203;Zarthus](https://togithub.com/Zarthus)]]
-   (no PR): activate `clock` and `std` features of `workspace.dependencies.chrono`.

[#&#8203;2482]: https://togithub.com/launchbadge/sqlx/pull/2482

[#&#8203;2652]: https://togithub.com/launchbadge/sqlx/pull/2652

[#&#8203;2697]: https://togithub.com/launchbadge/sqlx/pull/2697

[#&#8203;2702]: https://togithub.com/launchbadge/sqlx/pull/2702

[#&#8203;2736]: https://togithub.com/launchbadge/sqlx/pull/2736

[#&#8203;2869]: https://togithub.com/launchbadge/sqlx/pull/2869

[#&#8203;2917]: https://togithub.com/launchbadge/sqlx/pull/2917

[#&#8203;2940]: https://togithub.com/launchbadge/sqlx/pull/2940

[#&#8203;2954]: https://togithub.com/launchbadge/sqlx/pull/2954

[#&#8203;2960]: https://togithub.com/launchbadge/sqlx/pull/2960

[#&#8203;2970]: https://togithub.com/launchbadge/sqlx/pull/2970

[#&#8203;2973]: https://togithub.com/launchbadge/sqlx/pull/2973

[#&#8203;3064]: https://togithub.com/launchbadge/sqlx/pull/3064

[#&#8203;3073]: https://togithub.com/launchbadge/sqlx/pull/3073

[#&#8203;3113]: https://togithub.com/launchbadge/sqlx/pull/3113

[#&#8203;3123]: https://togithub.com/launchbadge/sqlx/pull/3123

[#&#8203;3126]: https://togithub.com/launchbadge/sqlx/pull/3126

[#&#8203;3130]: https://togithub.com/launchbadge/sqlx/pull/3130

[#&#8203;3137]: https://togithub.com/launchbadge/sqlx/pull/3137

[#&#8203;3138]: https://togithub.com/launchbadge/sqlx/pull/3138

[#&#8203;3146]: https://togithub.com/launchbadge/sqlx/pull/3146

[#&#8203;3148]: https://togithub.com/launchbadge/sqlx/pull/3148

[#&#8203;3154]: https://togithub.com/launchbadge/sqlx/pull/3154

[#&#8203;3162]: https://togithub.com/launchbadge/sqlx/pull/3162

[#&#8203;3165]: https://togithub.com/launchbadge/sqlx/pull/3165

[#&#8203;3167]: https://togithub.com/launchbadge/sqlx/pull/3167

[#&#8203;3172]: https://togithub.com/launchbadge/sqlx/pull/3172

[#&#8203;3173]: https://togithub.com/launchbadge/sqlx/pull/3173

[#&#8203;3181]: https://togithub.com/launchbadge/sqlx/pull/3181

[#&#8203;3184]: https://togithub.com/launchbadge/sqlx/pull/3184

[#&#8203;3188]: https://togithub.com/launchbadge/sqlx/pull/3188

[#&#8203;3190]: https://togithub.com/launchbadge/sqlx/pull/3190

[#&#8203;3191]: https://togithub.com/launchbadge/sqlx/pull/3191

[#&#8203;3194]: https://togithub.com/launchbadge/sqlx/pull/3194

[#&#8203;3216]: https://togithub.com/launchbadge/sqlx/pull/3216

[#&#8203;3230]: https://togithub.com/launchbadge/sqlx/pull/3230

[#&#8203;3233]: https://togithub.com/launchbadge/sqlx/pull/3233

[#&#8203;3234]: https://togithub.com/launchbadge/sqlx/pull/3234

[#&#8203;3236]: https://togithub.com/launchbadge/sqlx/pull/3236

[#&#8203;3244]: https://togithub.com/launchbadge/sqlx/pull/3244

[#&#8203;3252]: https://togithub.com/launchbadge/sqlx/pull/3252

[#&#8203;3254]: https://togithub.com/launchbadge/sqlx/pull/3254

[#&#8203;3260]: https://togithub.com/launchbadge/sqlx/pull/3260

[#&#8203;3265]: https://togithub.com/launchbadge/sqlx/pull/3265

[#&#8203;3266]: https://togithub.com/launchbadge/sqlx/pull/3266

[#&#8203;3267]: https://togithub.com/launchbadge/sqlx/pull/3267

[#&#8203;3271]: https://togithub.com/launchbadge/sqlx/pull/3271

[#&#8203;3276]: https://togithub.com/launchbadge/sqlx/pull/3276

[#&#8203;3279]: https://togithub.com/launchbadge/sqlx/pull/3279

[#&#8203;3285]: https://togithub.com/launchbadge/sqlx/pull/3285

[#&#8203;3288]: https://togithub.com/launchbadge/sqlx/pull/3288

[#&#8203;3291]: https://togithub.com/launchbadge/sqlx/pull/3291

[#&#8203;3293]: https://togithub.com/launchbadge/sqlx/pull/3293

[#&#8203;3297]: https://togithub.com/launchbadge/sqlx/pull/3297

[#&#8203;3298]: https://togithub.com/launchbadge/sqlx/pull/3298

[#&#8203;3303]: https://togithub.com/launchbadge/sqlx/pull/3303

[#&#8203;3311]: https://togithub.com/launchbadge/sqlx/pull/3311

[#&#8203;3312]: https://togithub.com/launchbadge/sqlx/pull/3312

[#&#8203;3327]: https://togithub.com/launchbadge/sqlx/pull/3327

[#&#8203;3328]: https://togithub.com/launchbadge/sqlx/pull/3328

[#&#8203;3329]: https://togithub.com/launchbadge/sqlx/pull/3329

[#&#8203;3337]: https://togithub.com/launchbadge/sqlx/pull/3337

[#&#8203;3340]: https://togithub.com/launchbadge/sqlx/pull/3340

[#&#8203;3341]: https://togithub.com/launchbadge/sqlx/pull/3341

[#&#8203;3343]: https://togithub.com/launchbadge/sqlx/pull/3343

[#&#8203;3346]: https://togithub.com/launchbadge/sqlx/pull/3346

[#&#8203;3350]: https://togithub.com/launchbadge/sqlx/pull/3350

[#&#8203;3352]: https://togithub.com/launchbadge/sqlx/pull/3352

[#&#8203;3353]: https://togithub.com/launchbadge/sqlx/pull/3353

[#&#8203;3356]: https://togithub.com/launchbadge/sqlx/pull/3356

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-24 12:47:32 +00:00
renovate
130dc2bd8b chore: bump up oxlint version to v0.8.0 (#7962)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [oxlint](https://oxc.rs) ([source](https://togithub.com/oxc-project/oxc/tree/HEAD/npm/oxlint)) | [`0.7.2` -> `0.8.0`](https://renovatebot.com/diffs/npm/oxlint/0.7.2/0.8.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint/0.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint/0.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint/0.7.2/0.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint/0.7.2/0.8.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxlint)</summary>

### [`v0.8.0`](https://togithub.com/oxc-project/oxc/blob/HEAD/npm/oxlint/CHANGELOG.md#080---2024-08-23)

[Compare Source](b3e189764f...8ef85a43c0)

##### Features

-   [`a0effab`](https://togithub.com/oxc-project/oxc/commit/a0effab) linter: Support more flexible config.globals values ([#&#8203;4990](https://togithub.com/oxc-project/oxc/issues/4990)) (Don Isaac)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-23 16:19:40 +00:00
renovate
442a843257 chore: bump up all non-major dependencies (#7953)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence | Type | Update |
|---|---|---|---|---|---|---|---|
| [@aws-sdk/client-s3](https://togithub.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://togithub.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.635.0` -> `3.637.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.635.0/3.637.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.635.0/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.635.0/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@aws-sdk/client-s3](https://togithub.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://togithub.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.635.0` -> `3.637.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.635.0/3.637.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.635.0/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.635.0/3.637.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@keyv/redis](https://togithub.com/jaredwray/keyv) | [`3.0.0` -> `3.0.1`](https://renovatebot.com/diffs/npm/@keyv%2fredis/3.0.0/3.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@keyv%2fredis/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@keyv%2fredis/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@keyv%2fredis/3.0.0/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@keyv%2fredis/3.0.0/3.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@napi-rs/simple-git](https://togithub.com/Brooooooklyn/simple-git) | [`0.1.17` -> `0.1.18`](https://renovatebot.com/diffs/npm/@napi-rs%2fsimple-git/0.1.17/0.1.18) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fsimple-git/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fsimple-git/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fsimple-git/0.1.17/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fsimple-git/0.1.17/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@napi-rs/simple-git](https://togithub.com/Brooooooklyn/simple-git) | [`0.1.17` -> `0.1.18`](https://renovatebot.com/diffs/npm/@napi-rs%2fsimple-git/0.1.17/0.1.18) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fsimple-git/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fsimple-git/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fsimple-git/0.1.17/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fsimple-git/0.1.17/0.1.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@nx/vite](https://nx.dev) ([source](https://togithub.com/nrwl/nx/tree/HEAD/packages/vite)) | [`19.6.1` -> `19.6.2`](https://renovatebot.com/diffs/npm/@nx%2fvite/19.6.1/19.6.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nx%2fvite/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nx%2fvite/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nx%2fvite/19.6.1/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nx%2fvite/19.6.1/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@opentelemetry/semantic-conventions](https://togithub.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions) ([source](https://togithub.com/open-telemetry/opentelemetry-js)) | [`1.25.1` -> `1.26.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsemantic-conventions/1.25.1/1.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fsemantic-conventions/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fsemantic-conventions/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fsemantic-conventions/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fsemantic-conventions/1.25.1/1.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [foxact](https://foxact.skk.moe) ([source](https://togithub.com/SukkaW/foxact)) | [`0.2.36` -> `0.2.37`](https://renovatebot.com/diffs/npm/foxact/0.2.36/0.2.37) | [![age](https://developer.mend.io/api/mc/badges/age/npm/foxact/0.2.37?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/foxact/0.2.37?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/foxact/0.2.36/0.2.37?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/foxact/0.2.36/0.2.37?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [lucide-react](https://lucide.dev) ([source](https://togithub.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react)) | [`^0.429.0` -> `^0.435.0`](https://renovatebot.com/diffs/npm/lucide-react/0.429.0/0.435.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lucide-react/0.435.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lucide-react/0.435.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lucide-react/0.429.0/0.435.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lucide-react/0.429.0/0.435.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [node](https://nodejs.org) ([source](https://togithub.com/nodejs/node)) | `20.16.0` -> `20.17.0` | [![age](https://developer.mend.io/api/mc/badges/age/node-version/node/v20.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/node-version/node/v20.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/node-version/node/v20.16.0/v20.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/node-version/node/v20.16.0/v20.17.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |  | minor |
| [nx](https://nx.dev) ([source](https://togithub.com/nrwl/nx/tree/HEAD/packages/nx)) | [`19.6.1` -> `19.6.2`](https://renovatebot.com/diffs/npm/nx/19.6.1/19.6.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nx/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nx/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nx/19.6.1/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nx/19.6.1/19.6.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [react-resizable-panels](https://togithub.com/bvaughn/react-resizable-panels) | [`2.1.0` -> `2.1.1`](https://renovatebot.com/diffs/npm/react-resizable-panels/2.1.0/2.1.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-resizable-panels/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-resizable-panels/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-resizable-panels/2.1.0/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-resizable-panels/2.1.0/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [react-transition-state](https://szhsin.github.io/react-transition-state/) ([source](https://togithub.com/szhsin/react-transition-state)) | [`2.1.1` -> `2.1.2`](https://renovatebot.com/diffs/npm/react-transition-state/2.1.1/2.1.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-transition-state/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-transition-state/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-transition-state/2.1.1/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-transition-state/2.1.1/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [webpack](https://togithub.com/webpack/webpack) | [`5.93.0` -> `5.94.0`](https://renovatebot.com/diffs/npm/webpack/5.93.0/5.94.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/webpack/5.94.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/webpack/5.94.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/webpack/5.93.0/5.94.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/webpack/5.93.0/5.94.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [wrangler](https://togithub.com/cloudflare/workers-sdk) ([source](https://togithub.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler)) | [`3.72.1` -> `3.72.2`](https://renovatebot.com/diffs/npm/wrangler/3.72.1/3.72.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.72.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.72.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.72.1/3.72.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.72.1/3.72.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |

---

### Release Notes

<details>
<summary>aws/aws-sdk-js-v3 (@&#8203;aws-sdk/client-s3)</summary>

### [`v3.637.0`](https://togithub.com/aws/aws-sdk-js-v3/blob/HEAD/clients/client-s3/CHANGELOG.md#36370-2024-08-22)

[Compare Source](https://togithub.com/aws/aws-sdk-js-v3/compare/v3.635.0...v3.637.0)

**Note:** Version bump only for package [@&#8203;aws-sdk/client-s3](https://togithub.com/aws-sdk/client-s3)

</details>

<details>
<summary>Brooooooklyn/simple-git (@&#8203;napi-rs/simple-git)</summary>

### [`v0.1.18`](https://togithub.com/Brooooooklyn/simple-git/releases/tag/v0.1.18)

[Compare Source](https://togithub.com/Brooooooklyn/simple-git/compare/v0.1.17...v0.1.18)

##### Core features:

##### Blob API

```js
import { Repository } from "@&#8203;napi-rs/simple-git";

const repo = new Repository(".");

const blob = repo.head().peelToTree()
    .getPath("__test__/repo.spec.mjs")
    .toObject(repo)
    .peelToBlob();

const fileContent = Buffer.from(blob.content()).toString("utf8");
```

##### What's Changed

-   chore(deps): update yarn to v4.4.0 by [@&#8203;renovate](https://togithub.com/renovate) in [https://github.com/Brooooooklyn/simple-git/pull/58](https://togithub.com/Brooooooklyn/simple-git/pull/58)
-   chore(deps): lock file maintenance by [@&#8203;renovate](https://togithub.com/renovate) in [https://github.com/Brooooooklyn/simple-git/pull/57](https://togithub.com/Brooooooklyn/simple-git/pull/57)
-   feat: implment blob and related features by [@&#8203;Brooooooklyn](https://togithub.com/Brooooooklyn) in [https://github.com/Brooooooklyn/simple-git/pull/59](https://togithub.com/Brooooooklyn/simple-git/pull/59)

**Full Changelog**: https://github.com/Brooooooklyn/simple-git/compare/v0.1.17...v0.1.18

</details>

<details>
<summary>nrwl/nx (@&#8203;nx/vite)</summary>

### [`v19.6.2`](https://togithub.com/nrwl/nx/releases/tag/19.6.2)

[Compare Source](https://togithub.com/nrwl/nx/compare/19.6.1...19.6.2)

##### 19.6.2 (2024-08-21)

##### 🚀 Features

-   **bundling:** add option to generate sourcemaps for Rollup build ([#&#8203;27539](https://togithub.com/nrwl/nx/pull/27539))
-   **devkit:** prefer strings over Linter enum ([#&#8203;27209](https://togithub.com/nrwl/nx/pull/27209))
-   **graph:** add expandedTargets to project details on nx dev ([#&#8203;26911](https://togithub.com/nrwl/nx/pull/26911))
-   **js:** add skipPackageManager option to build executors in order to skip generating "packageManager" entry in package.json ([#&#8203;27518](https://togithub.com/nrwl/nx/pull/27518))
-   **nx-dev:** honor prefers-reduced-motion ([#&#8203;27541](https://togithub.com/nrwl/nx/pull/27541))

##### 🩹 Fixes

-   missing export for setRemoteDefinition ([#&#8203;27491](https://togithub.com/nrwl/nx/pull/27491))
-   **core:** fix importing files with special characters ([#&#8203;27484](https://togithub.com/nrwl/nx/pull/27484))
-   **core:** use withVerbose util ([#&#8203;27553](https://togithub.com/nrwl/nx/pull/27553))
-   **core:** support import detection of packages installed from git remote URL ([#&#8203;27569](https://togithub.com/nrwl/nx/pull/27569))
-   **esbuild:** declaration:true should find the correct package root regardless of cwd [#&#8203;26261](https://togithub.com/nrwl/nx/issues/26261) ([#&#8203;27560](https://togithub.com/nrwl/nx/pull/27560), [#&#8203;26261](https://togithub.com/nrwl/nx/issues/26261))
-   **gradle:** track childProjects in properties report ([#&#8203;27488](https://togithub.com/nrwl/nx/pull/27488))
-   **gradle:** fix tasksFileLines might be undefined ([#&#8203;27548](https://togithub.com/nrwl/nx/pull/27548))
-   **js:** only sync references when composite is true, preserve comments in other parts of file ([#&#8203;27530](https://togithub.com/nrwl/nx/pull/27530))
-   **js:** ensure assets option in tsc executor defaults to empty array for programmatic usage ([#&#8203;27565](https://togithub.com/nrwl/nx/pull/27565))
-   **module-federation:** ensure shared packages can be shared from host [#&#8203;27162](https://togithub.com/nrwl/nx/issues/27162) ([#&#8203;27513](https://togithub.com/nrwl/nx/pull/27513), [#&#8203;27162](https://togithub.com/nrwl/nx/issues/27162))
-   **nextjs:** should not fail when running outside of nx cli ([#&#8203;27523](https://togithub.com/nrwl/nx/pull/27523))
-   **nextjs:** Should be able to run custom server targets with swc ([#&#8203;27526](https://togithub.com/nrwl/nx/pull/27526))
-   **nextjs:** schema type for unitTestRunner for library ([#&#8203;26824](https://togithub.com/nrwl/nx/pull/26824))
-   **node:** generate webpack server apps with generatePackageJson:true by default ([#&#8203;27570](https://togithub.com/nrwl/nx/pull/27570))
-   **nx-dev:** modify prompt ([#&#8203;27536](https://togithub.com/nrwl/nx/pull/27536))
-   **nx-plugin:** allow create-package without e2eProject ([#&#8203;27572](https://togithub.com/nrwl/nx/pull/27572))
-   **react:** handle more scenarios when collecting component props for generating stories ([#&#8203;27528](https://togithub.com/nrwl/nx/pull/27528))
-   **storybook:** should generate correct config for nextjs apps [#&#8203;27233](https://togithub.com/nrwl/nx/issues/27233) ([#&#8203;27510](https://togithub.com/nrwl/nx/pull/27510), [#&#8203;27233](https://togithub.com/nrwl/nx/issues/27233))
-   **testing:** fix issues in static server target migrations ([#&#8203;27547](https://togithub.com/nrwl/nx/pull/27547))
-   **vite:** plugin should infer serve target if server config defined [#&#8203;27370](https://togithub.com/nrwl/nx/issues/27370) ([#&#8203;27507](https://togithub.com/nrwl/nx/pull/27507), [#&#8203;27370](https://togithub.com/nrwl/nx/issues/27370))
-   **vite:** load the correct config file from [@&#8203;nx/vite](https://togithub.com/nx/vite):test executor ([#&#8203;27514](https://togithub.com/nrwl/nx/pull/27514))
-   **vite:** add typecheck inferred target for vite plugin [#&#8203;27501](https://togithub.com/nrwl/nx/issues/27501) ([#&#8203;27531](https://togithub.com/nrwl/nx/pull/27531), [#&#8203;27501](https://togithub.com/nrwl/nx/issues/27501))

##### ❤️  Thank You

-   Colum Ferry [@&#8203;Coly010](https://togithub.com/Coly010)
-   Emily Xiong [@&#8203;xiongemi](https://togithub.com/xiongemi)
-   Feliche-Demian Netliukh
-   Guilherme Prezzi [@&#8203;menosprezzi](https://togithub.com/menosprezzi)
-   Isaac Mann [@&#8203;isaacplmann](https://togithub.com/isaacplmann)
-   Jack Hsu [@&#8203;jaysoo](https://togithub.com/jaysoo)
-   James Henry [@&#8203;JamesHenry](https://togithub.com/JamesHenry)
-   Jason Jean [@&#8203;FrozenPandaz](https://togithub.com/FrozenPandaz)
-   Leosvel Pérez Espinosa [@&#8203;leosvelperez](https://togithub.com/leosvelperez)
-   Nicholas Cunningham [@&#8203;ndcunningham](https://togithub.com/ndcunningham)

</details>

<details>
<summary>open-telemetry/opentelemetry-js (@&#8203;opentelemetry/semantic-conventions)</summary>

### [`v1.26.0`](https://togithub.com/open-telemetry/opentelemetry-js/compare/v1.25.1...3cf1c5215f2656ccb82e6a73cd9e6f2782f8d1cc)

[Compare Source](https://togithub.com/open-telemetry/opentelemetry-js/compare/v1.25.1...3cf1c5215f2656ccb82e6a73cd9e6f2782f8d1cc)

</details>

<details>
<summary>SukkaW/foxact (foxact)</summary>

### [`v0.2.37`](https://togithub.com/SukkaW/foxact/blob/HEAD/CHANGELOG.md#0237)

[Compare Source](https://togithub.com/SukkaW/foxact/compare/0.2.36...0.2.37)

**Core Changes**

-   `foxact/rem` now also exports converter factory function
-   `foxact/rem` now supports customize html font size

</details>

<details>
<summary>lucide-icons/lucide (lucide-react)</summary>

### [`v0.435.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.435.0): New icons 0.435.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.434.0...0.435.0)

#### Modified Icons 🔨

-   `milestone` ([#&#8203;2281](https://togithub.com/lucide-icons/lucide/issues/2281)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `signpost` ([#&#8203;2281](https://togithub.com/lucide-icons/lucide/issues/2281)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.434.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.434.0): New icons 0.434.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.433.0...0.434.0)

#### New icons 🎨

-   `volume-off` ([#&#8203;2378](https://togithub.com/lucide-icons/lucide/issues/2378)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `file-volume` ([#&#8203;2378](https://togithub.com/lucide-icons/lucide/issues/2378)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `volume-1` ([#&#8203;2378](https://togithub.com/lucide-icons/lucide/issues/2378)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `volume-2` ([#&#8203;2378](https://togithub.com/lucide-icons/lucide/issues/2378)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `volume-x` ([#&#8203;2378](https://togithub.com/lucide-icons/lucide/issues/2378)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `volume` ([#&#8203;2378](https://togithub.com/lucide-icons/lucide/issues/2378)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.433.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.433.0): New icons 0.433.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.432.0...0.433.0)

#### New icons 🎨

-   `trending-up-down` ([#&#8203;2372](https://togithub.com/lucide-icons/lucide/issues/2372)) by [@&#8203;Alportan](https://togithub.com/Alportan)

#### Fixes Lucide Solid

-   Fixed compilation issues when starting up Vite Dev server by [@&#8203;ericfennis](https://togithub.com/ericfennis) in [https://github.com/lucide-icons/lucide/pull/2375](https://togithub.com/lucide-icons/lucide/pull/2375)

### [`v0.432.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.432.0): New icons 0.432.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.429.0...0.432.0)

#### New icons 🎨

-   `chart-gantt` ([#&#8203;2392](https://togithub.com/lucide-icons/lucide/issues/2392)) by [@&#8203;jguddas](https://togithub.com/jguddas)

#### Modified Icons 🔨

-   `contact-round` ([#&#8203;2391](https://togithub.com/lucide-icons/lucide/issues/2391)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `contact` ([#&#8203;2391](https://togithub.com/lucide-icons/lucide/issues/2391)) by [@&#8203;jguddas](https://togithub.com/jguddas)

</details>

<details>
<summary>nodejs/node (node)</summary>

### [`v20.17.0`](https://togithub.com/nodejs/node/compare/v20.16.0...v20.17.0)

[Compare Source](https://togithub.com/nodejs/node/compare/v20.16.0...v20.17.0)

</details>

<details>
<summary>bvaughn/react-resizable-panels (react-resizable-panels)</summary>

### [`v2.1.1`](https://togithub.com/bvaughn/react-resizable-panels/compare/2.1.0...2.1.1)

[Compare Source](https://togithub.com/bvaughn/react-resizable-panels/compare/2.1.0...2.1.1)

</details>

<details>
<summary>szhsin/react-transition-state (react-transition-state)</summary>

### [`v2.1.2`](https://togithub.com/szhsin/react-transition-state/releases/tag/v2.1.2)

[Compare Source](https://togithub.com/szhsin/react-transition-state/compare/v2.1.1...v2.1.2)

-   Add switch transition examples in README [#&#8203;639](https://togithub.com/szhsin/react-transition-state/issues/639)

</details>

<details>
<summary>webpack/webpack (webpack)</summary>

### [`v5.94.0`](https://togithub.com/webpack/webpack/compare/v5.93.0...eabf85d8580dfcb876b56957ba5488222a4f7873)

[Compare Source](https://togithub.com/webpack/webpack/compare/v5.93.0...v5.94.0)

</details>

<details>
<summary>cloudflare/workers-sdk (wrangler)</summary>

### [`v3.72.2`](https://togithub.com/cloudflare/workers-sdk/blob/HEAD/packages/wrangler/CHANGELOG.md#3722)

[Compare Source](https://togithub.com/cloudflare/workers-sdk/compare/wrangler@3.72.1...wrangler@3.72.2)

##### Patch Changes

-   [#&#8203;6511](https://togithub.com/cloudflare/workers-sdk/pull/6511) [`e75c581`](e75c5812f5) Thanks [@&#8203;petebacondarwin](https://togithub.com/petebacondarwin)! - fix: allow Pages projects to use \`experimental:nodejs_compat_v2" flag

    Fixes [#&#8203;6288](https://togithub.com/cloudflare/workers-sdk/issues/6288)

-   Updated dependencies \[[`b0e2f0b`](b0e2f0bfc6), [`f5bde66`](f5bde66914)]:
    -   miniflare@3.20240821.0
    -   [@&#8203;cloudflare/workers-shared](https://togithub.com/cloudflare/workers-shared)[@&#8203;0](https://togithub.com/0).3.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-23 14:42:36 +00:00
darkskygit
0b3c7d1407 feat: update throttler (#7957) 2024-08-23 13:52:47 +00:00
renovate[bot]
49c8a25fce chore: bump up @blocksuite/icons version to v2.1.64 (#7945)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 12:22:06 +08:00
JimmFly
920afa7bf1 feat(core): adjust share menu ui (#7931)
https://github.com/user-attachments/assets/6538c046-3872-4c98-a389-81b86a2978a4
2024-08-23 02:07:51 +00:00
darkskygit
b57388fd85 feat: block slides insert before image load finished (#7948) 2024-08-22 17:46:06 +00:00
pengx17
5e555b3807 fix(electron): adjust app-tabs-header styles (#7947)
fix AF-1171
2024-08-22 13:10:27 +00:00
darkskygit
3b727ef40a chore: revert breaking change deps (#7949) 2024-08-22 12:08:07 +00:00
EYHN
4bc4a58a30 feat(infra): add convenience api to get workspace from doc (#7934) 2024-08-22 11:22:04 +00:00
pengx17
2f02f0da2b fix(electron): should not send switchSplitView event when clicking on the active view (#7944) 2024-08-22 05:26:29 +00:00
pengx17
592150638e feat(electron): switch to next/previous tab with Ctrl+Tab/Ctrl+Shift+Tab (#7943)
fix PD-1569
2024-08-22 04:46:25 +00:00
JimmFly
20174b9cbe feat(core): add custom font family setting (#7924)
close AF-1255

https://github.com/user-attachments/assets/d44359b6-b75c-4883-a57b-1f226586feec
2024-08-22 04:24:44 +00:00
JimmFly
b333cde336 feat(core): init editor setting ui (#7878)
- init editor setting ui

https://github.com/user-attachments/assets/c54f5816-ef05-4ac0-b11a-8ab7159f928c
2024-08-22 04:24:41 +00:00
JimmFly
03c4d56a91 feat(component): add slider ui component (#7879)
![CleanShot 2024-08-15 at 14 27 07@2x](https://github.com/user-attachments/assets/50299f44-6446-4ec8-a097-7d456ff67f46)
2024-08-22 04:24:37 +00:00
renovate
2e2a3af967 chore: bump up all non-major dependencies (#7925)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence | Type | Update |
|---|---|---|---|---|---|---|---|
| [@aws-sdk/client-s3](https://togithub.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://togithub.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.633.0` -> `3.635.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.633.0/3.635.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.633.0/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.633.0/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@aws-sdk/client-s3](https://togithub.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://togithub.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.633.0` -> `3.635.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.633.0/3.635.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.633.0/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.633.0/3.635.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@chromatic-com/storybook](https://togithub.com/chromaui/addon-visual-tests) | [`1.6.1` -> `1.7.0`](https://renovatebot.com/diffs/npm/@chromatic-com%2fstorybook/1.6.1/1.7.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@chromatic-com%2fstorybook/1.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@chromatic-com%2fstorybook/1.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@chromatic-com%2fstorybook/1.6.1/1.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@chromatic-com%2fstorybook/1.6.1/1.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@emotion/react](https://togithub.com/emotion-js/emotion/tree/main#readme) ([source](https://togithub.com/emotion-js/emotion)) | [`11.13.0` -> `11.13.3`](https://renovatebot.com/diffs/npm/@emotion%2freact/11.13.0/11.13.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@emotion%2freact/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@emotion%2freact/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@emotion%2freact/11.13.0/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@emotion%2freact/11.13.0/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@emotion/react](https://togithub.com/emotion-js/emotion/tree/main#readme) ([source](https://togithub.com/emotion-js/emotion)) | [`11.13.0` -> `11.13.3`](https://renovatebot.com/diffs/npm/@emotion%2freact/11.13.0/11.13.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@emotion%2freact/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@emotion%2freact/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@emotion%2freact/11.13.0/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@emotion%2freact/11.13.0/11.13.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@fal-ai/serverless-client](https://togithub.com/fal-ai/fal-js) ([source](https://togithub.com/fal-ai/fal-js/tree/HEAD/libs/client)) | [`^0.13.0` -> `^0.14.0`](https://renovatebot.com/diffs/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@fal-ai%2fserverless-client/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@fal-ai%2fserverless-client/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@napi-rs/cli](https://togithub.com/napi-rs/napi-rs) | [`3.0.0-alpha.60` -> `3.0.0-alpha.62`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@playwright/test](https://playwright.dev) ([source](https://togithub.com/microsoft/playwright)) | [`=1.44.1` -> `=1.46.1`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.44.1/1.46.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@playwright%2ftest/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@playwright%2ftest/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@types/react](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react)) | [`18.3.3` -> `18.3.4`](https://renovatebot.com/diffs/npm/@types%2freact/18.3.3/18.3.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.3.3/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.3.3/18.3.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@vanilla-extract/css](https://togithub.com/vanilla-extract-css/vanilla-extract) ([source](https://togithub.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/css)) | [`1.15.4` -> `1.15.5`](https://renovatebot.com/diffs/npm/@vanilla-extract%2fcss/1.15.4/1.15.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vanilla-extract%2fcss/1.15.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vanilla-extract%2fcss/1.15.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vanilla-extract%2fcss/1.15.4/1.15.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vanilla-extract%2fcss/1.15.4/1.15.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@vanilla-extract/vite-plugin](https://togithub.com/vanilla-extract-css/vanilla-extract) ([source](https://togithub.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/vite-plugin)) | [`4.0.14` -> `4.0.15`](https://renovatebot.com/diffs/npm/@vanilla-extract%2fvite-plugin/4.0.14/4.0.15) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vanilla-extract%2fvite-plugin/4.0.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vanilla-extract%2fvite-plugin/4.0.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vanilla-extract%2fvite-plugin/4.0.14/4.0.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vanilla-extract%2fvite-plugin/4.0.14/4.0.15?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@vanilla-extract/webpack-plugin](https://togithub.com/vanilla-extract-css/vanilla-extract) ([source](https://togithub.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/webpack-plugin)) | [`2.3.12` -> `2.3.13`](https://renovatebot.com/diffs/npm/@vanilla-extract%2fwebpack-plugin/2.3.12/2.3.13) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vanilla-extract%2fwebpack-plugin/2.3.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vanilla-extract%2fwebpack-plugin/2.3.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vanilla-extract%2fwebpack-plugin/2.3.12/2.3.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vanilla-extract%2fwebpack-plugin/2.3.12/2.3.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [core-js](https://togithub.com/zloirock/core-js) ([source](https://togithub.com/zloirock/core-js/tree/HEAD/packages/core-js)) | [`3.38.0` -> `3.38.1`](https://renovatebot.com/diffs/npm/core-js/3.38.0/3.38.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/core-js/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/core-js/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/core-js/3.38.0/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/core-js/3.38.0/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [core-js](https://togithub.com/zloirock/core-js) ([source](https://togithub.com/zloirock/core-js/tree/HEAD/packages/core-js)) | [`3.38.0` -> `3.38.1`](https://renovatebot.com/diffs/npm/core-js/3.38.0/3.38.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/core-js/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/core-js/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/core-js/3.38.0/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/core-js/3.38.0/3.38.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [dayjs](https://day.js.org) ([source](https://togithub.com/iamkun/dayjs)) | [`1.11.12` -> `1.11.13`](https://renovatebot.com/diffs/npm/dayjs/1.11.12/1.11.13) | [![age](https://developer.mend.io/api/mc/badges/age/npm/dayjs/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/dayjs/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/dayjs/1.11.12/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/dayjs/1.11.12/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [electron](https://togithub.com/electron/electron) | [`32.0.0` -> `32.0.1`](https://renovatebot.com/diffs/npm/electron/32.0.0/32.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/electron/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/electron/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/electron/32.0.0/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/electron/32.0.0/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [embla-carousel-react](https://www.embla-carousel.com) ([source](https://togithub.com/davidjerleke/embla-carousel)) | [`8.1.8` -> `8.2.0`](https://renovatebot.com/diffs/npm/embla-carousel-react/8.1.8/8.2.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/embla-carousel-react/8.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/embla-carousel-react/8.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/embla-carousel-react/8.1.8/8.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/embla-carousel-react/8.1.8/8.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [husky](https://togithub.com/typicode/husky) | [`9.1.4` -> `9.1.5`](https://renovatebot.com/diffs/npm/husky/9.1.4/9.1.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/husky/9.1.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/husky/9.1.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/husky/9.1.4/9.1.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/husky/9.1.4/9.1.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [jotai-scope](https://togithub.com/jotaijs/jotai-scope) | [`0.7.1` -> `0.7.2`](https://renovatebot.com/diffs/npm/jotai-scope/0.7.1/0.7.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai-scope/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai-scope/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai-scope/0.7.1/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai-scope/0.7.1/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [lucide-react](https://lucide.dev) ([source](https://togithub.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react)) | [`^0.408.0` -> `^0.429.0`](https://renovatebot.com/diffs/npm/lucide-react/0.408.0/0.429.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lucide-react/0.429.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lucide-react/0.429.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lucide-react/0.408.0/0.429.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lucide-react/0.408.0/0.429.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [napi](https://togithub.com/napi-rs/napi-rs) | `3.0.0-alpha.7` -> `3.0.0-alpha.8` | [![age](https://developer.mend.io/api/mc/badges/age/crate/napi/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi/3.0.0-alpha.7/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi/3.0.0-alpha.7/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [napi-derive](https://togithub.com/napi-rs/napi-rs) | `3.0.0-alpha.6` -> `3.0.0-alpha.7` | [![age](https://developer.mend.io/api/mc/badges/age/crate/napi-derive/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-derive/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-derive/3.0.0-alpha.6/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-derive/3.0.0-alpha.6/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [nestjs-throttler-storage-redis](https://togithub.com/kkoomen/nestjs-throttler-storage-redis) | [`^0.4.1` -> `^0.5.0`](https://renovatebot.com/diffs/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nestjs-throttler-storage-redis/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nestjs-throttler-storage-redis/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [node](https://nodejs.org) ([source](https://togithub.com/nodejs/node)) | `20.15.1` -> `20.16.0` | [![age](https://developer.mend.io/api/mc/badges/age/node-version/node/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/node-version/node/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/node-version/node/v20.15.1/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/node-version/node/v20.15.1/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |  | minor |
| openresty/openresty | `1.25.3.1-0-buster` -> `1.25.3.2-0-buster` | [![age](https://developer.mend.io/api/mc/badges/age/docker/openresty%2fopenresty/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/docker/openresty%2fopenresty/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/docker/openresty%2fopenresty/1.25.3.1/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/openresty%2fopenresty/1.25.3.1/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | final | patch |
| [playwright](https://playwright.dev) ([source](https://togithub.com/microsoft/playwright)) | [`=1.44.1` -> `=1.46.1`](https://renovatebot.com/diffs/npm/playwright/1.44.1/1.46.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/playwright/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/playwright/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/playwright/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/playwright/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [react-refresh](https://reactjs.org/) ([source](https://togithub.com/facebook/react/tree/HEAD/packages/react)) | [`^0.10.0` -> `^0.14.0`](https://renovatebot.com/diffs/npm/react-refresh/0.10.0/0.14.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-refresh/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-refresh/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-refresh/0.10.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-refresh/0.10.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [serde](https://serde.rs) ([source](https://togithub.com/serde-rs/serde)) | `1.0.204` -> `1.0.208` | [![age](https://developer.mend.io/api/mc/badges/age/crate/serde/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/serde/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/serde/1.0.204/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/serde/1.0.204/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [serde_json](https://togithub.com/serde-rs/json) | `1.0.120` -> `1.0.125` | [![age](https://developer.mend.io/api/mc/badges/age/crate/serde_json/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/serde_json/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/serde_json/1.0.120/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/serde_json/1.0.120/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [storybook-dark-mode](https://togithub.com/hipstersmoothie/storybook-dark-mode) | [`4.0.1` -> `4.0.2`](https://renovatebot.com/diffs/npm/storybook-dark-mode/4.0.1/4.0.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/storybook-dark-mode/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/storybook-dark-mode/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/storybook-dark-mode/4.0.1/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/storybook-dark-mode/4.0.1/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | `1.38.0` -> `1.39.3` | [![age](https://developer.mend.io/api/mc/badges/age/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dev-dependencies | minor |
| [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | `1.38.0` -> `1.39.3` | [![age](https://developer.mend.io/api/mc/badges/age/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | minor |
| [vite](https://vitejs.dev) ([source](https://togithub.com/vitejs/vite/tree/HEAD/packages/vite)) | [`5.4.1` -> `5.4.2`](https://renovatebot.com/diffs/npm/vite/5.4.1/5.4.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite/5.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/5.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/5.4.1/5.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/5.4.1/5.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [vite-plugin-dts](https://togithub.com/qmhc/vite-plugin-dts) | [`4.0.2` -> `4.0.3`](https://renovatebot.com/diffs/npm/vite-plugin-dts/4.0.2/4.0.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite-plugin-dts/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite-plugin-dts/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite-plugin-dts/4.0.2/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite-plugin-dts/4.0.2/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [wrangler](https://togithub.com/cloudflare/workers-sdk) ([source](https://togithub.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler)) | [`3.72.0` -> `3.72.1`](https://renovatebot.com/diffs/npm/wrangler/3.72.0/3.72.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.72.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.72.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.72.0/3.72.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.72.0/3.72.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |

---

### Release Notes

<details>
<summary>aws/aws-sdk-js-v3 (@&#8203;aws-sdk/client-s3)</summary>

### [`v3.635.0`](https://togithub.com/aws/aws-sdk-js-v3/blob/HEAD/clients/client-s3/CHANGELOG.md#36350-2024-08-20)

[Compare Source](https://togithub.com/aws/aws-sdk-js-v3/compare/v3.633.0...v3.635.0)

##### Features

-   **client-s3:** Amazon Simple Storage Service / Features : Add support for conditional writes for PutObject and CompleteMultipartUpload APIs. ([b474584](b474584f2c))
-   **codegen:** add Smithy RPCv2 CBOR to list of protocols ([#&#8203;6096](https://togithub.com/aws/aws-sdk-js-v3/issues/6096)) ([5154d4f](5154d4f19b))

</details>

<details>
<summary>chromaui/addon-visual-tests (@&#8203;chromatic-com/storybook)</summary>

### [`v1.7.0`](https://togithub.com/chromaui/addon-visual-tests/blob/HEAD/CHANGELOG.md#v170-Tue-Aug-20-2024)

[Compare Source](https://togithub.com/chromaui/addon-visual-tests/compare/v1.6.1...v1.7.0)

##### 🚀 Enhancement

-   Update story status reporting for Storybook 8.3 and use new `SET_FILTER` event [#&#8203;332](https://togithub.com/chromaui/addon-visual-tests/pull/332) ([@&#8203;ghengeveld](https://togithub.com/ghengeveld))

##### Authors: 1

-   Gert Hengeveld ([@&#8203;ghengeveld](https://togithub.com/ghengeveld))

***

</details>

<details>
<summary>emotion-js/emotion (@&#8203;emotion/react)</summary>

### [`v11.13.3`](https://togithub.com/emotion-js/emotion/compare/@emotion/react@11.13.0...3f468846855ed1c6092922a6317a6f5df0ba8dcc)

[Compare Source](https://togithub.com/emotion-js/emotion/compare/@emotion/react@11.13.0...@emotion/react@11.13.3)

</details>

<details>
<summary>fal-ai/fal-js (@&#8203;fal-ai/serverless-client)</summary>

### [`v0.14.2`](c3a3c3d21a...b3ab5f0e15)

[Compare Source](c3a3c3d21a...b3ab5f0e15)

### [`v0.14.1`](6edbf2948d...c3a3c3d21a)

[Compare Source](6edbf2948d...c3a3c3d21a)

### [`v0.14.0`](cf300e9cc0...6edbf2948d)

[Compare Source](cf300e9cc0...6edbf2948d)

</details>

<details>
<summary>napi-rs/napi-rs (@&#8203;napi-rs/cli)</summary>

### [`v3.0.0-alpha.62`](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.61...@napi-rs/cli@3.0.0-alpha.62)

[Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.61...@napi-rs/cli@3.0.0-alpha.62)

### [`v3.0.0-alpha.61`](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.60...@napi-rs/cli@3.0.0-alpha.61)

[Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.60...@napi-rs/cli@3.0.0-alpha.61)

</details>

<details>
<summary>microsoft/playwright (@&#8203;playwright/test)</summary>

### [`v1.46.1`](https://togithub.com/microsoft/playwright/compare/v1.46.0...e1c861cfa7a6caf3c5b798786b1e6298c4f3cf31)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.46.0...v1.46.1)

### [`v1.46.0`](https://togithub.com/microsoft/playwright/compare/v1.45.3...99a36310570617222290c09b96a2026beb8b00f9)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.3...v1.46.0)

### [`v1.45.3`](https://togithub.com/microsoft/playwright/compare/v1.45.2...0e130fa8edaf85765c4a5a86bded0e6d33bfd7c2)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.2...v1.45.3)

### [`v1.45.2`](https://togithub.com/microsoft/playwright/compare/v1.45.1...d8a5f3b33193e413b404ff4aa1f71e859d8f1b6b)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.1...v1.45.2)

### [`v1.45.1`](https://togithub.com/microsoft/playwright/compare/v1.45.0...e8989f83d9801cdaadc3803b5341c601c9593947)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.0...v1.45.1)

### [`v1.45.0`](https://togithub.com/microsoft/playwright/compare/v1.44.1...4f3f6eecae490af444dd9298c9eaeb0c596915b7)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.44.1...v1.45.0)

</details>

<details>
<summary>vanilla-extract-css/vanilla-extract (@&#8203;vanilla-extract/css)</summary>

### [`v1.15.5`](https://togithub.com/vanilla-extract-css/vanilla-extract/blob/HEAD/packages/css/CHANGELOG.md#1155)

[Compare Source](https://togithub.com/vanilla-extract-css/vanilla-extract/compare/@vanilla-extract/css@1.15.4...@vanilla-extract/css@1.15.5)

##### Patch Changes

-   [#&#8203;1466](https://togithub.com/vanilla-extract-css/vanilla-extract/pull/1466) [`6432199fa0717f424fb3f45fbe36410b03b01c1c`](6432199fa0) Thanks [@&#8203;askoufis](https://togithub.com/askoufis)! - Speed up dev prefix generation for long file paths

</details>

<details>
<summary>vanilla-extract-css/vanilla-extract (@&#8203;vanilla-extract/vite-plugin)</summary>

### [`v4.0.15`](https://togithub.com/vanilla-extract-css/vanilla-extract/blob/HEAD/packages/vite-plugin/CHANGELOG.md#4015)

[Compare Source](https://togithub.com/vanilla-extract-css/vanilla-extract/compare/@vanilla-extract/vite-plugin@4.0.14...@vanilla-extract/vite-plugin@4.0.15)

##### Patch Changes

-   Updated dependencies \[[`96dd466127374b21ad7e48e5dd168a03a96af047`](96dd466127)]:
    -   [@&#8203;vanilla-extract/integration](https://togithub.com/vanilla-extract/integration)[@&#8203;7](https://togithub.com/7).1.9

</details>

<details>
<summary>vanilla-extract-css/vanilla-extract (@&#8203;vanilla-extract/webpack-plugin)</summary>

### [`v2.3.13`](https://togithub.com/vanilla-extract-css/vanilla-extract/blob/HEAD/packages/webpack-plugin/CHANGELOG.md#2313)

[Compare Source](https://togithub.com/vanilla-extract-css/vanilla-extract/compare/@vanilla-extract/webpack-plugin@2.3.12...@vanilla-extract/webpack-plugin@2.3.13)

##### Patch Changes

-   Updated dependencies \[[`96dd466127374b21ad7e48e5dd168a03a96af047`](96dd466127)]:
    -   [@&#8203;vanilla-extract/integration](https://togithub.com/vanilla-extract/integration)[@&#8203;7](https://togithub.com/7).1.9

</details>

<details>
<summary>zloirock/core-js (core-js)</summary>

### [`v3.38.1`](https://togithub.com/zloirock/core-js/blob/HEAD/CHANGELOG.md#3381---20240820)

[Compare Source](https://togithub.com/zloirock/core-js/compare/v3.38.0...v3.38.1)

-   Changes [v3.38.0...v3.38.1](https://togithub.com/zloirock/core-js/compare/v3.38.0...v3.38.1)
-   Fixed some cases of `URLSearchParams` percent decoding, [#&#8203;1357](https://togithub.com/zloirock/core-js/issues/1357), [#&#8203;1361](https://togithub.com/zloirock/core-js/pull/1361), thanks [**@&#8203;slowcheetah**](https://togithub.com/slowcheetah)
-   Some stylistic changes and minor optimizations
-   Compat data improvements:
    -   [`Iterator` helpers proposal](https://togithub.com/tc39/proposal-iterator-helpers) methods marked as [shipped from FF131](https://bugzilla.mozilla.org/show_bug.cgi?id=1896390)
    -   [`Math.f16round` and `DataView.prototype.{ getFloat16, setFloat16 }`](https://togithub.com/tc39/proposal-float16array) marked as shipped from Bun 1.1.23
    -   [`RegExp.escape`](https://togithub.com/tc39/proposal-regex-escaping) marked as shipped from Bun 1.1.22
    -   [`Promise.try`](https://togithub.com/tc39/proposal-promise-try) marked as shipped from Bun 1.1.22
    -   [`Uint8Array` to / from base64 and hex proposal](https://togithub.com/tc39/proposal-arraybuffer-base64) methods marked as shipped from Bun 1.1.22
    -   Added Hermes 0.13 compat data, similar to React Native 0.75 Hermes
    -   Added Opera Android 84 compat data mapping

</details>

<details>
<summary>iamkun/dayjs (dayjs)</summary>

### [`v1.11.13`](https://togithub.com/iamkun/dayjs/compare/v1.11.12...93c8fd0f807b8a8252f4cd65083bb1d6a49b90e7)

[Compare Source](https://togithub.com/iamkun/dayjs/compare/v1.11.12...v1.11.13)

</details>

<details>
<summary>electron/electron (electron)</summary>

### [`v32.0.1`](https://togithub.com/electron/electron/compare/v32.0.0...v32.0.1)

[Compare Source](https://togithub.com/electron/electron/compare/v32.0.0...v32.0.1)

</details>

<details>
<summary>davidjerleke/embla-carousel (embla-carousel-react)</summary>

### [`v8.2.0`](https://togithub.com/davidjerleke/embla-carousel/compare/v8.1.8...6baf1555c6f68e88a7f785213ecf363f447a8b2f)

[Compare Source](https://togithub.com/davidjerleke/embla-carousel/compare/v8.1.8...v8.2.0)

</details>

<details>
<summary>typicode/husky (husky)</summary>

### [`v9.1.5`](https://togithub.com/typicode/husky/compare/v9.1.4...2fee8d212c601942ad146ea9209f15c20a07fb6d)

[Compare Source](https://togithub.com/typicode/husky/compare/v9.1.4...v9.1.5)

</details>

<details>
<summary>jotaijs/jotai-scope (jotai-scope)</summary>

### [`v0.7.2`](https://togithub.com/jotaijs/jotai-scope/compare/v0.7.1...v0.7.2)

[Compare Source](https://togithub.com/jotaijs/jotai-scope/compare/v0.7.1...v0.7.2)

</details>

<details>
<summary>lucide-icons/lucide (lucide-react)</summary>

### [`v0.429.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.429.0): New icons 0.429.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.428.0...0.429.0)

#### Modified Icons 🔨

-   `message-square-dashed` ([#&#8203;2374](https://togithub.com/lucide-icons/lucide/issues/2374)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `stethoscope` ([#&#8203;2379](https://togithub.com/lucide-icons/lucide/issues/2379)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.428.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.428.0): New icons 0.428.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.427.0...0.428.0)

#### New icons 🎨

-   `tickets-plane` ([#&#8203;2196](https://togithub.com/lucide-icons/lucide/issues/2196)) by [@&#8203;jguddas](https://togithub.com/jguddas)

#### Modified Icons 🔨

-   `folder-search` ([#&#8203;2354](https://togithub.com/lucide-icons/lucide/issues/2354)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.427.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.427.0): New icons 0.427.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.426.0...0.427.0)

#### New icons 🎨

-   `binoculars` ([#&#8203;2207](https://togithub.com/lucide-icons/lucide/issues/2207)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `tickets` ([#&#8203;2335](https://togithub.com/lucide-icons/lucide/issues/2335)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.426.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.426.0): New icons 0.426.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.425.0...0.426.0)

#### New icons 🎨

-   `chevrons-left-right-ellipsis` ([#&#8203;2120](https://togithub.com/lucide-icons/lucide/issues/2120)) by [@&#8203;ericfennis](https://togithub.com/ericfennis)
-   `ethernet-port` ([#&#8203;2120](https://togithub.com/lucide-icons/lucide/issues/2120)) by [@&#8203;ericfennis](https://togithub.com/ericfennis)

#### Modified Icons 🔨

-   `cigarette-off` ([#&#8203;2282](https://togithub.com/lucide-icons/lucide/issues/2282)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `cigarette` ([#&#8203;2282](https://togithub.com/lucide-icons/lucide/issues/2282)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.425.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.425.0): New icons 0.425.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.424.0...0.425.0)

#### New icons 🎨

-   `bandage` ([#&#8203;2341](https://togithub.com/lucide-icons/lucide/issues/2341)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `table-of-contents` ([#&#8203;2348](https://togithub.com/lucide-icons/lucide/issues/2348)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `mouse-pointer-2` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `mouse-pointer-ban` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `mouse-pointer-click` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `mouse-pointer` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `square-dashed-mouse-pointer` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `square-mouse-pointer` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.424.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.424.0): New icons 0.424.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.423.0...0.424.0)

#### New icons 🎨

-   `map-pin-house` ([#&#8203;2337](https://togithub.com/lucide-icons/lucide/issues/2337)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `replace-all` ([#&#8203;2333](https://togithub.com/lucide-icons/lucide/issues/2333)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `replace` ([#&#8203;2333](https://togithub.com/lucide-icons/lucide/issues/2333)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.423.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.423.0): New icons 0.423.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.422.0...0.423.0)

#### New icons 🎨

-   `amphora` ([#&#8203;1926](https://togithub.com/lucide-icons/lucide/issues/1926)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.422.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.422.0): New icons 0.422.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.421.0...0.422.0)

#### Modified Icons 🔨

-   `skull` ([#&#8203;2197](https://togithub.com/lucide-icons/lucide/issues/2197)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.421.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.421.0): New icons 0.421.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.420.0...0.421.0)

#### New icons 🎨

-   `microchip` ([#&#8203;1982](https://togithub.com/lucide-icons/lucide/issues/1982)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `circle-check-big` ([#&#8203;2330](https://togithub.com/lucide-icons/lucide/issues/2330)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `cloud-download` ([#&#8203;2355](https://togithub.com/lucide-icons/lucide/issues/2355)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `pentagon` ([#&#8203;1918](https://togithub.com/lucide-icons/lucide/issues/1918)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `square-check-big` ([#&#8203;2331](https://togithub.com/lucide-icons/lucide/issues/2331)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.420.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.420.0): New icons 0.420.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.419.0...0.420.0)

#### New icons 🎨

-   `omega` ([#&#8203;2347](https://togithub.com/lucide-icons/lucide/issues/2347)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `calendar-search` ([#&#8203;2351](https://togithub.com/lucide-icons/lucide/issues/2351)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `cloud-upload` ([#&#8203;2352](https://togithub.com/lucide-icons/lucide/issues/2352)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.419.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.419.0): New icons 0.419.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.418.0...0.419.0)

#### New icons 🎨

-   `circle-fading-arrow-up` ([#&#8203;2287](https://togithub.com/lucide-icons/lucide/issues/2287)) by [@&#8203;mosch](https://togithub.com/mosch)

### [`v0.418.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.418.0): New icons 0.418.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.417.0...0.418.0)

#### New icons 🎨

-   `id-card` ([#&#8203;1296](https://togithub.com/lucide-icons/lucide/issues/1296)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.417.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.417.0): New icons 0.417.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.416.0...0.417.0)

#### Modified Icons 🔨

-   `chart-column-increasing` ([#&#8203;2334](https://togithub.com/lucide-icons/lucide/issues/2334)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.416.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.416.0): New icons 0.416.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.415.0...0.416.0)

#### New icons 🎨

-   `map-pin-check-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-check` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-minus-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-minus` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-plus-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-plus` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-x-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-x` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `map-pin-off` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pinned` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.415.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.415.0): New icons 0.415.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.414.0...0.415.0)

#### New icons 🎨

-   `square-square` ([#&#8203;2241](https://togithub.com/lucide-icons/lucide/issues/2241)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.414.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.414.0): New icons 0.414.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.413.0...0.414.0)

#### New icons 🎨

-   `chart-area` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-bar-decreasing` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-bar-increasing` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-bar-stacked` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-column-big` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-column-increasing` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-column-stacked` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-network` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-no-axes-combined` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-spline` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.413.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.413.0): New icons 0.413.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.412.0...0.413.0)

#### New icons 🎨

-   `dam` ([#&#8203;2233](https://togithub.com/lucide-icons/lucide/issues/2233)) by [@&#8203;AndreasSas](https://togithub.com/AndreasSas)

#### Modified Icons 🔨

-   `dog` ([#&#8203;2249](https://togithub.com/lucide-icons/lucide/issues/2249)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `key-square` ([#&#8203;2277](https://togithub.com/lucide-icons/lucide/issues/2277)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.412.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.412.0): New icons 0.412.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.411.0...0.412.0)

#### New icons 🎨

-   `letter-text` ([#&#8203;2252](https://togithub.com/lucide-icons/lucide/issues/2252)) by [@&#8203;GRA0007](https://togithub.com/GRA0007)

### [`v0.411.0`](https://togithub.com/lucide-icons/lucide/compare/0.410.0...0.411.0)

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.410.0...0.411.0)

### [`v0.410.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.410.0): New icons 0.410.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.409.0...0.410.0)

#### New icons 🎨

-   `philippine-peso` ([#&#8203;2231](https://togithub.com/lucide-icons/lucide/issues/2231)) by [@&#8203;kasutu](https://togithub.com/kasutu)

#### Modified Icons 🔨

-   `ribbon` ([#&#8203;2271](https://togithub.com/lucide-icons/lucide/issues/2271)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.409.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.409.0): New icons 0.409.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.408.0...0.409.0)

#### Modified Icons 🔨

-   `calendar-minus` ([#&#8203;2265](https://togithub.com/lucide-icons/lucide/issues/2265)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `eye-off` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `eye` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `image-plus` ([#&#8203;2321](https://togithub.com/lucide-icons/lucide/issues/2321)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `scan-eye` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `view` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

</details>

<details>
<summary>nodejs/node (node)</summary>

### [`v20.16.0`](https://togithub.com/nodejs/node/compare/v20.15.1...v20.16.0)

[Compare Source](https://togithub.com/nodejs/node/compare/v20.15.1...v20.16.0)

</details>

<details>
<summary>facebook/react (react-refresh)</summary>

### [`v0.14.2`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#0142-November-2-2015)

[Compare Source](https://togithub.com/facebook/react/compare/v0.14.1...v0.14.2)

##### React DOM

-   Fixed bug with development build preventing events from firing in some versions of Internet Explorer & Edge
-   Fixed bug with development build when using es5-sham in older versions of Internet Explorer
-   Added support for `integrity` attribute
-   Fixed bug resulting in `children` prop being coerced to a string for custom elements, which was not the desired behavior
-   Moved `react` from `dependencies` to `peerDependencies` to match expectations and align with `react-addons-*` packages

### [`v0.14.1`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#01410-October-14-2020)

[Compare Source](https://togithub.com/facebook/react/compare/v0.14.0...v0.14.1)

##### React

-   Backport support for the [new JSX transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) to 0.14.x. ([@&#8203;lunaruan](https://togithub.com/lunaruan) in [#&#8203;18299](https://togithub.com/facebook/react/pull/18299) and [@&#8203;gaearon](https://togithub.com/gaearon) in [#&#8203;20024](https://togithub.com/facebook/react/pull/20024))

### [`v0.14.0`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#0140-October-7-2015)

[Compare Source](https://togithub.com/facebook/react/compare/v0.13.0...v0.14.0)

##### Major changes

-   Split the main `react` package into two: `react` and `react-dom`.  This paves the way to writing components that can be shared between the web version of React and React Native.  This means you will need to include both files and some functions have been moved from `React` to `ReactDOM`.
-   Addons have been moved to separate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).
-   Stateless functional components - React components were previously created using React.createClass or using ES6 classes.  This release adds a [new syntax](https://reactjs.org/docs/reusable-components.html#stateless-functions) where a user defines a single [stateless render function](https://reactjs.org/docs/reusable-components.html#stateless-functions) (with one parameter: `props`) which returns a JSX element, and this function may be used as a component.
-   Refs to DOM components as the DOM node itself. Previously the only useful thing you can do with a DOM component is call `getDOMNode()` to get the underlying DOM node. Starting with this release, a ref to a DOM component *is* the actual DOM node. **Note that refs to custom (user-defined) components work exactly as before; only the built-in DOM components are affected by this change.**

##### Breaking changes

-   `React.initializeTouchEvents` is no longer necessary and has been removed completely. Touch events now work automatically.
-   Add-Ons: Due to the DOM node refs change mentioned above, `TestUtils.findAllInRenderedTree` and related helpers are no longer able to take a DOM component, only a custom component.
-   The `props` object is now frozen, so mutating props after creating a component element is no longer supported. In most cases, [`React.cloneElement`](https://reactjs.org/docs/react-api.html#cloneelement) should be used instead. This change makes your components easier to reason about and enables the compiler optimizations mentioned above.
-   Plain objects are no longer supported as React children; arrays should be used instead. You can use the [`createFragment`](https://reactjs.org/docs/create-fragment.html) helper to migrate, which now returns an array.
-   Add-Ons: `classSet` has been removed. Use [classnames](https://togithub.com/JedWatson/classnames) instead.
-   Web components (custom elements) now use native property names.  Eg: `class` instead of `className`.

##### Deprecations

-   `this.getDOMNode()` is now deprecated and `ReactDOM.findDOMNode(this)` can be used instead. Note that in the common case, `findDOMNode` is now unnecessary since a ref to the DOM component is now the actual DOM node.
-   `setProps` and `replaceProps` are now deprecated. Instead, call ReactDOM.render again at the top level with the new props.
-   ES6 component classes must now extend `React.Component` in order to enable stateless function components. The [ES3 module pattern](https://reactjs.org/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages) will continue to work.
-   Reusing and mutating a `style` object between renders has been deprecated. This mirrors our change to freeze the `props` object.
-   Add-Ons: `cloneWithProps` is now deprecated. Use [`React.cloneElement`](https://reactjs.org/docs/react-api.html#cloneelement) instead (unlike `cloneW

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-22 04:12:23 +00:00
pengx17
5acf1b5309 feat: init mobile entry (#7905) 2024-08-21 13:17:35 +00:00
EYHN
3db95bafa2 feat(core): use new print pdf api (#7932) 2024-08-21 10:06:22 +00:00
renovate
cf086e4018 chore: bump up @keyv/redis version to v3 (#7935)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@keyv/redis](https://togithub.com/jaredwray/keyv) | [`^2.8.4` -> `^3.0.0`](https://renovatebot.com/diffs/npm/@keyv%2fredis/2.8.5/3.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@keyv%2fredis/3.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@keyv%2fredis/3.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@keyv%2fredis/2.8.5/3.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@keyv%2fredis/2.8.5/3.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-21 09:37:17 +00:00
renovate
483fcfb2c7 chore: bump up @blocksuite/icons version to v2.1.63 (#7845)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@blocksuite/icons](https://togithub.com/toeverything/icons) | [`2.1.62` -> `2.1.63`](https://renovatebot.com/diffs/npm/@blocksuite%2ficons/2.1.62/2.1.63) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@blocksuite%2ficons/2.1.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@blocksuite%2ficons/2.1.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@blocksuite%2ficons/2.1.62/2.1.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@blocksuite%2ficons/2.1.62/2.1.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>toeverything/icons (@&#8203;blocksuite/icons)</summary>

### [`v2.1.63`](dce7e696b3...d63ff94c9f)

[Compare Source](dce7e696b3...d63ff94c9f)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yMC4xIiwidXBkYXRlZEluVmVyIjoiMzguMjAuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-21 09:20:14 +00:00
renovate
b6a3697793 chore: bump up oxlint version to v0.7.2 (#7885)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [oxlint](https://oxc.rs) ([source](https://togithub.com/oxc-project/oxc/tree/HEAD/npm/oxlint)) | [`0.7.1` -> `0.7.2`](https://renovatebot.com/diffs/npm/oxlint/0.7.1/0.7.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint/0.7.1/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint/0.7.1/0.7.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxlint)</summary>

### [`v0.7.2`](https://togithub.com/oxc-project/oxc/blob/HEAD/npm/oxlint/CHANGELOG.md#072---2024-08-15)

[Compare Source](972492cc4d...b3e189764f)

##### Features

-   [`4d28d03`](https://togithub.com/oxc-project/oxc/commit/4d28d03) task/website: Support render `subschemas.all_of` ([#&#8203;4800](https://togithub.com/oxc-project/oxc/issues/4800)) (mysteryven)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-21 09:05:36 +00:00
Cats Juice
23b0db36b9 feat(component): mobile menu support (#7892) 2024-08-21 09:05:05 +00:00
renovate
182b2fd62d chore: bump up electron version to v32 (#7927)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [electron](https://togithub.com/electron/electron) | [`^31.0.0` -> `^32.0.0`](https://renovatebot.com/diffs/npm/electron/31.4.0/32.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/electron/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/electron/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/electron/31.4.0/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/electron/31.4.0/32.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>electron/electron (electron)</summary>

### [`v32.0.1`](https://togithub.com/electron/electron/compare/v32.0.0...v32.0.1)

[Compare Source](https://togithub.com/electron/electron/compare/v32.0.0...v32.0.1)

### [`v32.0.0`](https://togithub.com/electron/electron/releases/tag/v32.0.0): electron v32.0.0

[Compare Source](https://togithub.com/electron/electron/compare/v31.4.0...v32.0.0)

### Release Notes for v32.0.0

#### Features

-   Added support for responding to auth requests initiated from utility process via `app#login` event. [#&#8203;43317](https://togithub.com/electron/electron/pull/43317)
-   Enabled zstd compression in net http requests. [#&#8203;43300](https://togithub.com/electron/electron/pull/43300) <span style="font-size:small;">(Also in [31](https://togithub.com/electron/electron/pull/43301))</span>

#### Other Changes

-   Updated Chromium to 128.0.6613.36. [#&#8203;43328](https://togithub.com/electron/electron/pull/43328)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-21 08:38:21 +00:00
CatsJuice
a43c34feec fix(core): onboarding switch active state is invisible (#7928)
close AF-1262
2024-08-21 06:17:31 +00:00
CatsJuice
c9a1a8c3b2 feat(component): access enviroment in components storybook (#7891)
close AF-1247
2024-08-21 06:04:39 +00:00
CatsJuice
a49b92e4c8 feat(core): adjust sidebar style, add github & learn more (#7864)
close AF-1202
2024-08-21 05:48:04 +00:00
EYHN
cfe0677b84 refactor(core): adapt to new sync api (#7929) 2024-08-21 05:30:34 +00:00
forehalo
b6f46e01c5 test(server): space adapters (#7903) 2024-08-21 05:30:30 +00:00
forehalo
e20bdbf925 feat(server): make server storage adapters (#7902) 2024-08-21 05:30:26 +00:00
forehalo
6f9f579e5d feat(server): make an abstraction for ydoc storage (#7901) 2024-08-21 05:30:23 +00:00
forehalo
682a01e441 feat(server): make a singleton global mutex service (#7900) 2024-08-21 05:30:19 +00:00
Saul-Mirone
6b0c398ae5 chore: bump bs (#7914) 2024-08-20 00:24:01 +00:00
renovate
152815c175 chore: bump up all non-major dependencies (#7921)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence | Type | Update |
|---|---|---|---|---|---|---|---|
| [@fal-ai/serverless-client](https://togithub.com/fal-ai/fal-js) ([source](https://togithub.com/fal-ai/fal-js/tree/HEAD/libs/client)) | [`^0.13.0` -> `^0.14.0`](https://renovatebot.com/diffs/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@fal-ai%2fserverless-client/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@fal-ai%2fserverless-client/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@napi-rs/cli](https://togithub.com/napi-rs/napi-rs) | [`3.0.0-alpha.60` -> `3.0.0-alpha.62`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@nx/vite](https://nx.dev) ([source](https://togithub.com/nrwl/nx/tree/HEAD/packages/vite)) | [`19.6.0` -> `19.6.1`](https://renovatebot.com/diffs/npm/@nx%2fvite/19.6.0/19.6.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nx%2fvite/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nx%2fvite/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nx%2fvite/19.6.0/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nx%2fvite/19.6.0/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@playwright/test](https://playwright.dev) ([source](https://togithub.com/microsoft/playwright)) | [`=1.44.1` -> `=1.46.1`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.44.1/1.46.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@playwright%2ftest/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@playwright%2ftest/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@swc/core](https://swc.rs) ([source](https://togithub.com/swc-project/swc)) | [`1.7.12` -> `1.7.14`](https://renovatebot.com/diffs/npm/@swc%2fcore/1.7.12/1.7.14) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@swc%2fcore/1.7.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@swc%2fcore/1.7.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@swc%2fcore/1.7.12/1.7.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@swc%2fcore/1.7.12/1.7.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [i18next](https://www.i18next.com) ([source](https://togithub.com/i18next/i18next)) | [`23.13.0` -> `23.14.0`](https://renovatebot.com/diffs/npm/i18next/23.13.0/23.14.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/i18next/23.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/i18next/23.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/i18next/23.13.0/23.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/i18next/23.13.0/23.14.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [lucide-react](https://lucide.dev) ([source](https://togithub.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react)) | [`^0.408.0` -> `^0.428.0`](https://renovatebot.com/diffs/npm/lucide-react/0.408.0/0.428.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lucide-react/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lucide-react/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lucide-react/0.408.0/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lucide-react/0.408.0/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [mini-css-extract-plugin](https://togithub.com/webpack-contrib/mini-css-extract-plugin) | [`2.9.0` -> `2.9.1`](https://renovatebot.com/diffs/npm/mini-css-extract-plugin/2.9.0/2.9.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/mini-css-extract-plugin/2.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/mini-css-extract-plugin/2.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/mini-css-extract-plugin/2.9.0/2.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/mini-css-extract-plugin/2.9.0/2.9.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [napi](https://togithub.com/napi-rs/napi-rs) | `3.0.0-alpha.7` -> `3.0.0-alpha.8` | [![age](https://developer.mend.io/api/mc/badges/age/crate/napi/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi/3.0.0-alpha.7/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi/3.0.0-alpha.7/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [napi-derive](https://togithub.com/napi-rs/napi-rs) | `3.0.0-alpha.6` -> `3.0.0-alpha.7` | [![age](https://developer.mend.io/api/mc/badges/age/crate/napi-derive/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-derive/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-derive/3.0.0-alpha.6/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-derive/3.0.0-alpha.6/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [nestjs-throttler-storage-redis](https://togithub.com/kkoomen/nestjs-throttler-storage-redis) | [`^0.4.1` -> `^0.5.0`](https://renovatebot.com/diffs/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nestjs-throttler-storage-redis/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nestjs-throttler-storage-redis/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [node](https://nodejs.org) ([source](https://togithub.com/nodejs/node)) | `20.15.1` -> `20.16.0` | [![age](https://developer.mend.io/api/mc/badges/age/node-version/node/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/node-version/node/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/node-version/node/v20.15.1/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/node-version/node/v20.15.1/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |  | minor |
| [nx](https://nx.dev) ([source](https://togithub.com/nrwl/nx/tree/HEAD/packages/nx)) | [`19.6.0` -> `19.6.1`](https://renovatebot.com/diffs/npm/nx/19.6.0/19.6.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nx/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nx/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nx/19.6.0/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nx/19.6.0/19.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| openresty/openresty | `1.25.3.1-0-buster` -> `1.25.3.2-0-buster` | [![age](https://developer.mend.io/api/mc/badges/age/docker/openresty%2fopenresty/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/docker/openresty%2fopenresty/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/docker/openresty%2fopenresty/1.25.3.1/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/openresty%2fopenresty/1.25.3.1/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | final | patch |
| [playwright](https://playwright.dev) ([source](https://togithub.com/microsoft/playwright)) | [`=1.44.1` -> `=1.46.1`](https://renovatebot.com/diffs/npm/playwright/1.44.1/1.46.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/playwright/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/playwright/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/playwright/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/playwright/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [react-refresh](https://reactjs.org/) ([source](https://togithub.com/facebook/react/tree/HEAD/packages/react)) | [`^0.10.0` -> `^0.14.0`](https://renovatebot.com/diffs/npm/react-refresh/0.10.0/0.14.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-refresh/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-refresh/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-refresh/0.10.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-refresh/0.10.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [serde](https://serde.rs) ([source](https://togithub.com/serde-rs/serde)) | `1.0.204` -> `1.0.208` | [![age](https://developer.mend.io/api/mc/badges/age/crate/serde/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/serde/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/serde/1.0.204/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/serde/1.0.204/1.0.208?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [serde_json](https://togithub.com/serde-rs/json) | `1.0.120` -> `1.0.125` | [![age](https://developer.mend.io/api/mc/badges/age/crate/serde_json/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/serde_json/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/serde_json/1.0.120/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/serde_json/1.0.120/1.0.125?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [storybook-dark-mode](https://togithub.com/hipstersmoothie/storybook-dark-mode) | [`4.0.1` -> `4.0.2`](https://renovatebot.com/diffs/npm/storybook-dark-mode/4.0.1/4.0.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/storybook-dark-mode/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/storybook-dark-mode/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/storybook-dark-mode/4.0.1/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/storybook-dark-mode/4.0.1/4.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | `1.38.0` -> `1.39.3` | [![age](https://developer.mend.io/api/mc/badges/age/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dev-dependencies | minor |
| [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | `1.38.0` -> `1.39.3` | [![age](https://developer.mend.io/api/mc/badges/age/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/tokio/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/tokio/1.38.0/1.39.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | minor |
| [undici](https://undici.nodejs.org) ([source](https://togithub.com/nodejs/undici)) | [`6.19.7` -> `6.19.8`](https://renovatebot.com/diffs/npm/undici/6.19.7/6.19.8) | [![age](https://developer.mend.io/api/mc/badges/age/npm/undici/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/undici/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/undici/6.19.7/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/undici/6.19.7/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [undici](https://undici.nodejs.org) ([source](https://togithub.com/nodejs/undici)) | [`6.19.7` -> `6.19.8`](https://renovatebot.com/diffs/npm/undici/6.19.7/6.19.8) | [![age](https://developer.mend.io/api/mc/badges/age/npm/undici/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/undici/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/undici/6.19.7/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/undici/6.19.7/6.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [vite-plugin-dts](https://togithub.com/qmhc/vite-plugin-dts) | [`4.0.2` -> `4.0.3`](https://renovatebot.com/diffs/npm/vite-plugin-dts/4.0.2/4.0.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite-plugin-dts/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite-plugin-dts/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite-plugin-dts/4.0.2/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite-plugin-dts/4.0.2/4.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |

---

### Release Notes

<details>
<summary>fal-ai/fal-js (@&#8203;fal-ai/serverless-client)</summary>

### [`v0.14.2`](c3a3c3d21a...b3ab5f0e15)

[Compare Source](c3a3c3d21a...b3ab5f0e15)

### [`v0.14.1`](6edbf2948d...c3a3c3d21a)

[Compare Source](6edbf2948d...c3a3c3d21a)

### [`v0.14.0`](cf300e9cc0...6edbf2948d)

[Compare Source](cf300e9cc0...6edbf2948d)

</details>

<details>
<summary>napi-rs/napi-rs (@&#8203;napi-rs/cli)</summary>

### [`v3.0.0-alpha.62`](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.61...@napi-rs/cli@3.0.0-alpha.62)

[Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.61...@napi-rs/cli@3.0.0-alpha.62)

### [`v3.0.0-alpha.61`](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.60...@napi-rs/cli@3.0.0-alpha.61)

[Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.0.0-alpha.60...@napi-rs/cli@3.0.0-alpha.61)

</details>

<details>
<summary>nrwl/nx (@&#8203;nx/vite)</summary>

### [`v19.6.1`](https://togithub.com/nrwl/nx/releases/tag/19.6.1)

[Compare Source](https://togithub.com/nrwl/nx/compare/19.6.0...19.6.1)

##### 19.6.1 (2024-08-19)

##### 🚀 Features

-   **core:** add shutdown lifecycle hook to node executor ([#&#8203;27354](https://togithub.com/nrwl/nx/pull/27354))
-   **docs:** update OpenAI model to use gpt-4o-mini ([#&#8203;27434](https://togithub.com/nrwl/nx/pull/27434))
-   **nx-dev:** add Explain with AI to Enterprise and Pro Plans ([#&#8203;27455](https://togithub.com/nrwl/nx/pull/27455))
-   **nx-dev:** add Monorepo World banner to hero ([#&#8203;27482](https://togithub.com/nrwl/nx/pull/27482))

##### 🩹 Fixes

-   **angular:** generate [@&#8203;nx/angular](https://togithub.com/nx/angular) in devDependencies and move to dependencies when using runtime helpers ([#&#8203;27405](https://togithub.com/nrwl/nx/pull/27405))
-   **angular:** module-federation-ssr-dev-server should call correct builder ([#&#8203;27477](https://togithub.com/nrwl/nx/pull/27477))
-   **angular:** bump ngrx version to 18.0.2 ([#&#8203;27506](https://togithub.com/nrwl/nx/pull/27506))
-   **js:** handle arbitrary nested ts path mappings when re-mapping them to the outputs ([#&#8203;27429](https://togithub.com/nrwl/nx/pull/27429))
-   **linter:** update the [@&#8203;nx/dependency-checks](https://togithub.com/nx/dependency-checks) rule to read the package.json content from the rule context ([#&#8203;27476](https://togithub.com/nrwl/nx/pull/27476))
-   **misc:** ensure custom reporters are usable with [@&#8203;nx/playwright](https://togithub.com/nx/playwright):playwright ([#&#8203;27443](https://togithub.com/nrwl/nx/pull/27443))
-   **module-federation:** ensure target defaults are set correctly [#&#8203;27448](https://togithub.com/nrwl/nx/issues/27448) ([#&#8203;27472](https://togithub.com/nrwl/nx/pull/27472), [#&#8203;27448](https://togithub.com/nrwl/nx/issues/27448))
-   **node:** build-esbuild-options.ts browser user define envs by config ([#&#8203;27480](https://togithub.com/nrwl/nx/pull/27480))
-   **nx-dev:** Og image path generation ([#&#8203;27456](https://togithub.com/nrwl/nx/pull/27456))
-   **nx-dev:** bad link from home page ([#&#8203;27475](https://togithub.com/nrwl/nx/pull/27475))
-   **nx-dev:** fix use `key` instead of `env` to reference cache key in… ([#&#8203;26644](https://togithub.com/nrwl/nx/pull/26644))
-   **react:** ensure [@&#8203;vitejs/plugin-react](https://togithub.com/vitejs/plugin-react) is installed for storybook ([#&#8203;27463](https://togithub.com/nrwl/nx/pull/27463))
-   **react:** enable vitejs-plugin-react-swc for swc compiler ([#&#8203;27457](https://togithub.com/nrwl/nx/pull/27457))
-   **repo:** add dependsOn to native build ([#&#8203;27446](https://togithub.com/nrwl/nx/pull/27446))
-   **testing:** fix misc issues in migrations ([#&#8203;27471](https://togithub.com/nrwl/nx/pull/27471))

##### ❤️  Thank You

-   [@&#8203;NgDaddy](https://togithub.com/NgDaddy) [@&#8203;NgDaddy](https://togithub.com/NgDaddy)
-   Benjamin Cabanes [@&#8203;bcabanes](https://togithub.com/bcabanes)
-   Colum Ferry [@&#8203;Coly010](https://togithub.com/Coly010)
-   EGonz1PCTY
-   Isaac Mann [@&#8203;isaacplmann](https://togithub.com/isaacplmann)
-   Jason Jean [@&#8203;FrozenPandaz](https://togithub.com/FrozenPandaz)
-   Jonathan Cammisuli
-   Kamenskih Dmitriy
-   Leosvel Pérez Espinosa [@&#8203;leosvelperez](https://togithub.com/leosvelperez)
-   Nicholas Cunningham [@&#8203;ndcunningham](https://togithub.com/ndcunningham)
-   Tine Kondo [@&#8203;tinesoft](https://togithub.com/tinesoft)
-   Wei Liang [@&#8203;weiliang79](https://togithub.com/weiliang79)

</details>

<details>
<summary>microsoft/playwright (@&#8203;playwright/test)</summary>

### [`v1.46.1`](https://togithub.com/microsoft/playwright/compare/v1.46.0...e1c861cfa7a6caf3c5b798786b1e6298c4f3cf31)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.46.0...v1.46.1)

### [`v1.46.0`](https://togithub.com/microsoft/playwright/compare/v1.45.3...99a36310570617222290c09b96a2026beb8b00f9)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.3...v1.46.0)

### [`v1.45.3`](https://togithub.com/microsoft/playwright/compare/v1.45.2...0e130fa8edaf85765c4a5a86bded0e6d33bfd7c2)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.2...v1.45.3)

### [`v1.45.2`](https://togithub.com/microsoft/playwright/compare/v1.45.1...d8a5f3b33193e413b404ff4aa1f71e859d8f1b6b)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.1...v1.45.2)

### [`v1.45.1`](https://togithub.com/microsoft/playwright/compare/v1.45.0...e8989f83d9801cdaadc3803b5341c601c9593947)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.45.0...v1.45.1)

### [`v1.45.0`](https://togithub.com/microsoft/playwright/compare/v1.44.1...4f3f6eecae490af444dd9298c9eaeb0c596915b7)

[Compare Source](https://togithub.com/microsoft/playwright/compare/v1.44.1...v1.45.0)

</details>

<details>
<summary>swc-project/swc (@&#8203;swc/core)</summary>

### [`v1.7.14`](https://togithub.com/swc-project/swc/blob/HEAD/CHANGELOG.md#1714---2024-08-19)

[Compare Source](https://togithub.com/swc-project/swc/compare/v1.7.12...v1.7.14)

##### Bug Fixes

-   **(common)** Use `SourceMap::adjust_mappings` in correct order ([#&#8203;9447](https://togithub.com/swc-project/swc/issues/9447)) ([05961eb](05961eb018))

-   **(es)** Preserve more comments ([#&#8203;9449](https://togithub.com/swc-project/swc/issues/9449)) ([673655c](673655c169))

##### Features

-   **(es/decorators)** Groundwork for stage 3 decorator ([#&#8203;9450](https://togithub.com/swc-project/swc/issues/9450)) ([238ba8b](238ba8b1d2))

##### Refactor

-   **(visit)** Remove `VisitAll` ([#&#8203;9448](https://togithub.com/swc-project/swc/issues/9448)) ([8845b76](8845b76ac4))

</details>

<details>
<summary>i18next/i18next (i18next)</summary>

### [`v23.14.0`](https://togithub.com/i18next/i18next/blob/HEAD/CHANGELOG.md#23140)

[Compare Source](https://togithub.com/i18next/i18next/compare/v23.13.0...v23.14.0)

-   If backend errors with retry flag, set internal state to 0, so reloadingResources should work [147](https://togithub.com/i18next/i18next-http-backend/issues/147)

</details>

<details>
<summary>lucide-icons/lucide (lucide-react)</summary>

### [`v0.428.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.428.0): New icons 0.428.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.427.0...0.428.0)

#### New icons 🎨

-   `tickets-plane` ([#&#8203;2196](https://togithub.com/lucide-icons/lucide/issues/2196)) by [@&#8203;jguddas](https://togithub.com/jguddas)

#### Modified Icons 🔨

-   `folder-search` ([#&#8203;2354](https://togithub.com/lucide-icons/lucide/issues/2354)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.427.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.427.0): New icons 0.427.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.426.0...0.427.0)

#### New icons 🎨

-   `binoculars` ([#&#8203;2207](https://togithub.com/lucide-icons/lucide/issues/2207)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `tickets` ([#&#8203;2335](https://togithub.com/lucide-icons/lucide/issues/2335)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.426.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.426.0): New icons 0.426.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.425.0...0.426.0)

#### New icons 🎨

-   `chevrons-left-right-ellipsis` ([#&#8203;2120](https://togithub.com/lucide-icons/lucide/issues/2120)) by [@&#8203;ericfennis](https://togithub.com/ericfennis)
-   `ethernet-port` ([#&#8203;2120](https://togithub.com/lucide-icons/lucide/issues/2120)) by [@&#8203;ericfennis](https://togithub.com/ericfennis)

#### Modified Icons 🔨

-   `cigarette-off` ([#&#8203;2282](https://togithub.com/lucide-icons/lucide/issues/2282)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `cigarette` ([#&#8203;2282](https://togithub.com/lucide-icons/lucide/issues/2282)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.425.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.425.0): New icons 0.425.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.424.0...0.425.0)

#### New icons 🎨

-   `bandage` ([#&#8203;2341](https://togithub.com/lucide-icons/lucide/issues/2341)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `table-of-contents` ([#&#8203;2348](https://togithub.com/lucide-icons/lucide/issues/2348)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `mouse-pointer-2` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `mouse-pointer-ban` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `mouse-pointer-click` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `mouse-pointer` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `square-dashed-mouse-pointer` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `square-mouse-pointer` ([#&#8203;2350](https://togithub.com/lucide-icons/lucide/issues/2350)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.424.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.424.0): New icons 0.424.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.423.0...0.424.0)

#### New icons 🎨

-   `map-pin-house` ([#&#8203;2337](https://togithub.com/lucide-icons/lucide/issues/2337)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `replace-all` ([#&#8203;2333](https://togithub.com/lucide-icons/lucide/issues/2333)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `replace` ([#&#8203;2333](https://togithub.com/lucide-icons/lucide/issues/2333)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.423.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.423.0): New icons 0.423.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.422.0...0.423.0)

#### New icons 🎨

-   `amphora` ([#&#8203;1926](https://togithub.com/lucide-icons/lucide/issues/1926)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.422.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.422.0): New icons 0.422.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.421.0...0.422.0)

#### Modified Icons 🔨

-   `skull` ([#&#8203;2197](https://togithub.com/lucide-icons/lucide/issues/2197)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.421.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.421.0): New icons 0.421.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.420.0...0.421.0)

#### New icons 🎨

-   `microchip` ([#&#8203;1982](https://togithub.com/lucide-icons/lucide/issues/1982)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `circle-check-big` ([#&#8203;2330](https://togithub.com/lucide-icons/lucide/issues/2330)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `cloud-download` ([#&#8203;2355](https://togithub.com/lucide-icons/lucide/issues/2355)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `pentagon` ([#&#8203;1918](https://togithub.com/lucide-icons/lucide/issues/1918)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `square-check-big` ([#&#8203;2331](https://togithub.com/lucide-icons/lucide/issues/2331)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.420.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.420.0): New icons 0.420.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.419.0...0.420.0)

#### New icons 🎨

-   `omega` ([#&#8203;2347](https://togithub.com/lucide-icons/lucide/issues/2347)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `calendar-search` ([#&#8203;2351](https://togithub.com/lucide-icons/lucide/issues/2351)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `cloud-upload` ([#&#8203;2352](https://togithub.com/lucide-icons/lucide/issues/2352)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.419.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.419.0): New icons 0.419.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.418.0...0.419.0)

#### New icons 🎨

-   `circle-fading-arrow-up` ([#&#8203;2287](https://togithub.com/lucide-icons/lucide/issues/2287)) by [@&#8203;mosch](https://togithub.com/mosch)

### [`v0.418.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.418.0): New icons 0.418.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.417.0...0.418.0)

#### New icons 🎨

-   `id-card` ([#&#8203;1296](https://togithub.com/lucide-icons/lucide/issues/1296)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.417.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.417.0): New icons 0.417.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.416.0...0.417.0)

#### Modified Icons 🔨

-   `chart-column-increasing` ([#&#8203;2334](https://togithub.com/lucide-icons/lucide/issues/2334)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.416.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.416.0): New icons 0.416.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.415.0...0.416.0)

#### New icons 🎨

-   `map-pin-check-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-check` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-minus-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-minus` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-plus-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-plus` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-x-inside` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin-x` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

#### Modified Icons 🔨

-   `map-pin-off` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pin` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `map-pinned` ([#&#8203;2301](https://togithub.com/lucide-icons/lucide/issues/2301)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.415.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.415.0): New icons 0.415.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.414.0...0.415.0)

#### New icons 🎨

-   `square-square` ([#&#8203;2241](https://togithub.com/lucide-icons/lucide/issues/2241)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.414.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.414.0): New icons 0.414.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.413.0...0.414.0)

#### New icons 🎨

-   `chart-area` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-bar-decreasing` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-bar-increasing` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-bar-stacked` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-column-big` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-column-increasing` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-column-stacked` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-network` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-no-axes-combined` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `chart-spline` ([#&#8203;2219](https://togithub.com/lucide-icons/lucide/issues/2219)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

### [`v0.413.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.413.0): New icons 0.413.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.412.0...0.413.0)

#### New icons 🎨

-   `dam` ([#&#8203;2233](https://togithub.com/lucide-icons/lucide/issues/2233)) by [@&#8203;AndreasSas](https://togithub.com/AndreasSas)

#### Modified Icons 🔨

-   `dog` ([#&#8203;2249](https://togithub.com/lucide-icons/lucide/issues/2249)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `key-square` ([#&#8203;2277](https://togithub.com/lucide-icons/lucide/issues/2277)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.412.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.412.0): New icons 0.412.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.411.0...0.412.0)

#### New icons 🎨

-   `letter-text` ([#&#8203;2252](https://togithub.com/lucide-icons/lucide/issues/2252)) by [@&#8203;GRA0007](https://togithub.com/GRA0007)

### [`v0.411.0`](https://togithub.com/lucide-icons/lucide/compare/0.410.0...0.411.0)

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.410.0...0.411.0)

### [`v0.410.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.410.0): New icons 0.410.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.409.0...0.410.0)

#### New icons 🎨

-   `philippine-peso` ([#&#8203;2231](https://togithub.com/lucide-icons/lucide/issues/2231)) by [@&#8203;kasutu](https://togithub.com/kasutu)

#### Modified Icons 🔨

-   `ribbon` ([#&#8203;2271](https://togithub.com/lucide-icons/lucide/issues/2271)) by [@&#8203;jguddas](https://togithub.com/jguddas)

### [`v0.409.0`](https://togithub.com/lucide-icons/lucide/releases/tag/0.409.0): New icons 0.409.0

[Compare Source](https://togithub.com/lucide-icons/lucide/compare/0.408.0...0.409.0)

#### Modified Icons 🔨

-   `calendar-minus` ([#&#8203;2265](https://togithub.com/lucide-icons/lucide/issues/2265)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `eye-off` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `eye` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `image-plus` ([#&#8203;2321](https://togithub.com/lucide-icons/lucide/issues/2321)) by [@&#8203;jguddas](https://togithub.com/jguddas)
-   `scan-eye` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)
-   `view` ([#&#8203;2317](https://togithub.com/lucide-icons/lucide/issues/2317)) by [@&#8203;karsa-mistmere](https://togithub.com/karsa-mistmere)

</details>

<details>
<summary>webpack-contrib/mini-css-extract-plugin (mini-css-extract-plugin)</summary>

### [`v2.9.1`](https://togithub.com/webpack-contrib/mini-css-extract-plugin/blob/HEAD/CHANGELOG.md#291-2024-08-19)

[Compare Source](https://togithub.com/webpack-contrib/mini-css-extract-plugin/compare/v2.9.0...v2.9.1)

</details>

<details>
<summary>nodejs/node (node)</summary>

### [`v20.16.0`](https://togithub.com/nodejs/node/compare/v20.15.1...v20.16.0)

[Compare Source](https://togithub.com/nodejs/node/compare/v20.15.1...v20.16.0)

</details>

<details>
<summary>facebook/react (react-refresh)</summary>

### [`v0.14.2`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#0142-November-2-2015)

[Compare Source](https://togithub.com/facebook/react/compare/v0.14.1...v0.14.2)

##### React DOM

-   Fixed bug with development build preventing events from firing in some versions of Internet Explorer & Edge
-   Fixed bug with development build when using es5-sham in older versions of Internet Explorer
-   Added support for `integrity` attribute
-   Fixed bug resulting in `children` prop being coerced to a string for custom elements, which was not the desired behavior
-   Moved `react` from `dependencies` to `peerDependencies` to match expectations and align with `react-addons-*` packages

### [`v0.14.1`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#01410-October-14-2020)

[Compare Source](https://togithub.com/facebook/react/compare/v0.14.0...v0.14.1)

##### React

-   Backport support for the [new JSX transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) to 0.14.x. ([@&#8203;lunaruan](https://togithub.com/lunaruan) in [#&#8203;18299](https://togithub.com/facebook/react/pull/18299) and [@&#8203;gaearon](https://togithub.com/gaearon) in [#&#8203;20024](https://togithub.com/facebook/react/pull/20024))

### [`v0.14.0`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#0140-October-7-2015)

[Compare Source](https://togithub.com/facebook/react/compare/v0.13.0...v0.14.0)

##### Major changes

-   Split the main `react` package into two: `react` and `react-dom`.  This paves the way to writing components that can be shared between the web version of React and React Native.  This means you will need to include both files and some functions have been moved from `React` to `ReactDOM`.
-   Addons have been moved to separate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).
-   Stateless functional components - React components were previously created using React.createClass or using ES6 classes.  This release adds a [new syntax](https://reactjs.org/docs/reusable-components.html#stateless-functions) where a user defines a single [stateless render function](https://reactjs.org/docs/reusable-components.html#stateless-functions) (with one parameter: `props`) which returns a JSX element, and this function may be used as a component.
-   Refs to DOM components as the DOM node itself. Previously the only useful thing you can do with a DOM component is call `getDOMNode()` to get the underlying DOM node. Starting with this release, a ref to a DOM component *is* the actual DOM node. **Note that refs to custom (user-defined) components work exactly as before; only the built-in DOM components are affected by this change.**

##### Breaking changes

-   `React.initializeTouchEvents` is no longer necessary and has been removed completely. Touch events now work automatically.
-   Add-Ons: Due to the DOM node refs change mentioned above, `TestUtils.findAllInRenderedTree` and related helpers are no longer able to take a DOM component, only a custom component.
-   The `props` object is now frozen, so mutating props after creating a component element is no longer supported. In most cases, [`React.cloneElement`](https://reactjs.org/docs/react-api.html#cloneelement) should be used instead. This change makes your components easier to reason about and enables the compiler optimizations mentioned above.
-   Plain objects are no longer supported as React children; arrays should be used instead. You can use the [`createFragment`](https://reactjs.org/docs/create-fragment.html) helper to migrate, which now returns an array.
-   Add-Ons: `classSet` has been removed. Use [classnames](https://togithub.com/JedWatson/classnames) instead.
-   Web components (custom elements) now use native property names.  Eg: `class` instead of `className`.

##### Deprecations

-   `this.getDOMNode()` is now deprecated and `ReactDOM.findDOMNode(this)` can be used instead. Note that in the common case, `findDOMNode` is now unnecessary since a ref to the DOM component is now the actual DOM node.
-   `setProps` and `replaceProps` are now deprecated. Instead, call ReactDOM.render again at the top level with the new props.
-   ES6 component classes must now extend `React.Component` in order to enable stateless function components. The [ES3 module pattern](https://reactjs.org/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages) will continue to work.
-   Reusing and mutating a `style` object between renders has been deprecated. This mirrors our change to freeze the `props` object.
-   Add-Ons: `cloneWithProps` is now deprecated. Use [`React.cloneElement`](https://reactjs.org/docs/react-api.html#cloneelement) instead (unlike `cloneWithProps`, `cloneElement` does not merge `className` or `style` automatically; you can merge them manually if needed).
-   Add-Ons: To improve reliability, `CSSTransitionGroup` will no longer listen to transition events. Instead, you should specify transition durations manually using props such as `transitionEnterTimeout={500}`.

##### Notable enhancements

-   Added `React.Children.toArray` which takes a nested children object and returns a flat array with keys assigned to each child. This helper makes it easier to manipulate collections of children in your `render` methods, especially if you want to reorder or slice `this.props.children` before passing it down. In addition, `React.Children.map` now returns plain arrays too.
-   React uses `console.error` instead of `console.warn` for warnings so that browsers show a full stack trace in the console. (Our warnings appear when you use patterns that will break in future releases and for code that is likely to behave unexpectedly, so we do consider our warnings to be “must-fix” errors.)
-   Previously, including untrusted objects as React children [could result in an XSS security vulnerability](http://danlec.com/blog/xss-via-a-spoofed-react-element). This problem should be avoided by properly validating input at the application layer and by never passing untrusted objects around your application code. As an additional layer of protection, [React now tags elements](https://togithub.com/facebook/react/pull/4832) with a specific [ES2015 (ES6) `Symbol`](http://www.2ality.com/2014/12/es6-symbols.html) in browsers that support it, in order to ensure that React never considers untrusted JSON to be a valid element. If this extra security protection is important to you, you should add a `Symbol` polyfill for older browsers, such as the one included by [Babel’s polyfill](https://babeljs.io/docs/usage/polyfill/).
-   When possible, React DOM now generates XHTML-compatible markup.
-   React DOM now supports these standard HTML attributes: `capture`, `challenge`, `inputMode`, `is`, `keyParams`, `keyType`, `minLength`, `summary`, `wrap`. It also now supports these non-standard attributes: `autoSave`, `results`, `security`.
-   React DOM now supports these SVG attributes, which render into namespaced attributes: `xlinkActuate`, `xlinkArcrole`, `xlinkHref`, `xlinkRole`, `xlinkShow`, `xlinkTitle`, `xlinkType`, `xmlBase`, `xmlLang`, `xmlSpace`.
-   The `image` SVG tag is now supported by React DOM.
-   In React DOM, arbitrary attributes are supported on custom elements (those with a hyphen in the tag name or an `is="..."` attribute).
-   React DOM now supports these media events on `audio` and `video` tags: `onAbort`, `onCanPlay`, `onCanPlayThrough`, `onDurationChange`, `onEmptied`, `onEncrypted`, `onEnded`, `onError`, `onLoadedData`, `onLoadedMetadata`, `onLoadStart`, `onPause`, `onPlay`, `onPlaying`, `onProgress`, `onRateChange`, `onSeeked`, `onSeeking`, `onStalled`, `onSuspend`, `onTimeUpdate`, `onVolumeChange`, `onWaiting`.
-   Many small performance improvements have been made.
-   Many warnings show more context than before.
-   Add-Ons: A [`shallowCompare`](https://togithub.com/facebook/react/pull/3355) add-on has been added as a migration path for `PureRenderMixin` in ES6 classes.
-   Add-Ons: `CSSTransitionGroup` can now use [custom class names](https://togithub.com/facebook/react/blob/48942b85/docs/docs/10.1-animation.md#custom-classes) instead of appending `-enter-active` or similar to the transition name.

##### New helpful warnings

-   React DOM now warns you when nesting HTML elements invalidly, which helps you avoid surprising errors during updates.
-   Passing `document.body` directly as the container to `ReactDOM.render` now gives a warning as doing so can cause problems with browser extensions that modify the DOM.
-   Using multiple instances of React together is not supported, so we now warn when we detect this case to help you avoid running into the resulting problems.

##### Notable bug fixes

-   Click events are handled by React DOM more reliably in mobile browsers, particularly in Mobile Safari.
-   SVG elements are created with the correct namespace in more cases.
-   React DOM now renders `<option>` elements with multiple text children properly and renders `<select>` elements on the server with the correct option selected.
-   When two separate copies of React add nodes to the same document (including when a browser extension uses React), React DOM tries harder not to throw exceptions during event handling.
-   Using non-lowercase HTML tag names in React DOM (e.g., `React.createElement('DIV')`) no longer causes problems, though we continue to recommend lowercase for consistency with the JSX tag name convention (lowercase names refer to built-in components, capitalized names refer to custom components).
-   React DOM understands that these CSS properties are unitless and does not append “px” to their values: `animationIterationCount`, `boxOrdinalGroup`, `flexOrder`, `tabSize`, `stopOpacity`.
-   Add-Ons: When using the test utils, `Simulate.mouseEnter` and `Simulate.mouseLeave` now work.
-   Add-Ons: ReactTransitionGroup now correctly handles multiple nodes being removed simultaneously.

##### React Tools / Babel

##### Breaking Changes

-   The `react-tools` package and `JSXTransformer.js` browser file [have been deprecated](https://reactjs.org/blog/2015/06/12/deprecating-jstransform-and-react-tools.html). You can continue using version `0.13.3` of both, but we no longer support them and recommend migrating to [Babel](https://babeljs.io), which has built-in support for React and JSX.

##### New Features

-   Babel 5.8.24 introduces **Inlining React elements:** The `optimisation.react.inlineElements` transform converts JSX elements to object literals like `{type: 'div', props: ...}` instead of calls to `React.createElement`.  This should only be enabled in production, since it disables some development warnings/checks.
-   Babel 5.8.24 introduces **Constant hoisting for React elements:** The `optimisation.react.constantElements` transform hoists element creation to the top level for subtrees that are fully static, which reduces calls to `React.createElement` and the resulting allocations. More importantly, it tells React that the subtree hasn’t changed so React can completely skip it when reconciling.  This should only be enabled in production, since it disables some development warnings/checks.

### [`v0.13.0`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#0130-March-10-2015)

[Compare Source](https://togithub.com/facebook/react/compare/v0.12.0...v0.13.0)

##### React Core

##### Breaking Changes

-   Deprecated patterns that warned in 0.12 no longer work: most prominently, calling component classes without using JSX or React.createElement and using non-component functions with JSX or createElement
-   Mutating `props` after an element is created is deprecated and will cause warnings in development mode; future versions of React will incorporate performance optimizations assuming that props aren't mutated
-   Static methods (defined in `statics`) are no longer autobound to the component class
-   `ref` resolution order has changed slightly such that a ref to a component is available immediately after its `componentDidMount` method is called; this change should be observable only if your component calls a parent component's callback within your `componentDidMount`, which is an anti-pattern and should be avoided regardless
-   Calls to `setState` in life-cycle methods are now always batched and therefore asynchronous. Previously the first call on the first mount was synchronous.
-   `setState` and `forceUpdate` on an unmounted component now warns instead of throwing. That avoids a possible race condition with Promises.
-   Access to most internal properties has been completely removed, including `this._pendingState` and `this._rootNodeID`.

##### New Features

-   Support for using ES6 classes to build React components; see the [v0.13.0 beta 1 notes](https://reactjs.org/blog/2015/01/27/react-v0.13.0-beta-1.html) for details.
-   Added new top-level API `React.findDOMNode(component)`, which should be used in place of `component.getDOMNode()`. The base class for ES6-based components will not have `getDOMNode`. This change will enable some more patterns moving forward.
-   Added a new top-level API `React.cloneElement(el, props)` for making copies of React elements – see the [v0.13 RC2 notes](https://reactjs.org/blog/2015/03/03/react-v0.13-rc2.html#react.cloneelement) for more details.
-   New `ref` style, allowing a callback to be used in place of a name: `<Photo ref={(c) => this._photo = c} />` allows you to reference the component with `this._photo` (as opposed to `ref="photo"` which gives `this.refs.photo`).
-   `this.setState()` can now take a function as the first argument for transactional state updates, such as `this.setState((state, props) => ({count: state.count + 1}));` – this means that you no longer need to use `this._pendingState`, which is now gone.
-   Support for iterators and immutable-js sequences as children.

##### Deprecations

-   `ComponentClass.type` is deprecated. Just use `ComponentClass` (usually as `element.type === ComponentClass`).
-   Some methods that are available on `createClass`-based components are removed or deprecated from ES6 classes (`getDOMNode`, `replaceState`, `isMounted`, `setProps`, `replaceProps`).

##### React with Add-Ons

##### New Features

-   [`React.addons.createFragment` was added](https://reactjs.org/docs/create-fragment.html) for adding keys to entire sets of children.

##### Deprecations

-   `React.addons.classSet` is now deprecated. This functionality can be replaced with several freely available modules. [classnames](https://www.npmjs.com/package/classnames) is one such module.
-   Calls to `React.addons.cloneWithProps` can be migrated to use `React.cloneElement` instead – make sure to merge `style` and `className` manually if desired.

##### React Tools

##### Breaking Changes

-   When transforming ES6 syntax, `class` methods are no longer enumerable by default, which requires `Object.defineProperty`; if you support browsers such as IE8, you can pass `--target es3` to mirror the old behavior

##### New Features

-   `--target` option is available on the jsx command, allowing users to specify and ECMAScript version to target.
    -   `es5` is the default.
    -   `es3` restores the previous default behavior. An additional transform is added here to ensure the use of reserved words as properties is safe (eg `this.static` will become `this['static']` for IE8 compatibility).
-   The transform for the call spread operator has also been enabled.

##### JSXTransformer

##### Breaking Changes

-   The return value of `transform` now contains `sourceMap` as a JS object already, not an instance of `SourceMapGenerator`.

##### JSX

##### Breaking Changes

-   A change was made to how some JSX was parsed, specifically around the use of `>` or `}` when inside an element. Previously it would be treated as a string but now it will be treated as a parse error. The [`jsx_orphaned_brackets_transformer`](https://www.npmjs.com/package/jsx_orphaned_brackets_transformer) package on npm can be used to find and fix potential issues in your JSX code.

### [`v0.12.0`](https://togithub.com/facebook/react/blob/HEAD/CHANGELOG.md#0120-October-28-2014)

[Compare Source](https://togithub.com/facebook/react/compare/v0.11.0...v0.12.0)

##### React Core

##### Breaking Changes

-   `key` and `ref` moved off props object, now

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yNi4xIiwidXBkYXRlZEluVmVyIjoiMzguMjYuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-19 18:34:45 +00:00
pengx17
9d42db56ca chore: bump electron version (#7922) 2024-08-19 14:24:34 +00:00
pengx17
f3930a9262 chore(core): remove @storybook/test dep (#7923)
we no longer need  "@storybook/test" and it indirectly has an incompatible prettier version 3.3.2 which differs from what we are using "3.3.3".

removing it to resolve this issue
2024-08-19 13:50:06 +00:00
renovate
10bea3922e chore: bump up all non-major dependencies (#7615)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence | Type | Update |
|---|---|---|---|---|---|---|---|
| [@apollo/server](https://togithub.com/apollographql/apollo-server) ([source](https://togithub.com/apollographql/apollo-server/tree/HEAD/packages/server)) | [`4.10.5` -> `4.11.0`](https://renovatebot.com/diffs/npm/@apollo%2fserver/4.10.5/4.11.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@apollo%2fserver/4.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@apollo%2fserver/4.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@apollo%2fserver/4.10.5/4.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@apollo%2fserver/4.10.5/4.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@atlaskit/pragmatic-drag-and-drop](https://atlassian.design/components/pragmatic-drag-and-drop/) ([source](https://togithub.com/atlassian/pragmatic-drag-and-drop)) | [`1.2.1` -> `1.3.0`](https://renovatebot.com/diffs/npm/@atlaskit%2fpragmatic-drag-and-drop/1.2.1/1.3.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@atlaskit%2fpragmatic-drag-and-drop/1.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@atlaskit%2fpragmatic-drag-and-drop/1.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@atlaskit%2fpragmatic-drag-and-drop/1.2.1/1.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@atlaskit%2fpragmatic-drag-and-drop/1.2.1/1.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@aws-sdk/client-s3](https://togithub.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://togithub.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.620.0` -> `3.633.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.620.0/3.633.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.620.0/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.620.0/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@aws-sdk/client-s3](https://togithub.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) ([source](https://togithub.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)) | [`3.620.0` -> `3.633.0`](https://renovatebot.com/diffs/npm/@aws-sdk%2fclient-s3/3.620.0/3.633.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@aws-sdk%2fclient-s3/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@aws-sdk%2fclient-s3/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@aws-sdk%2fclient-s3/3.620.0/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@aws-sdk%2fclient-s3/3.620.0/3.633.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@commitlint/cli](https://commitlint.js.org/) ([source](https://togithub.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli)) | [`19.3.0` -> `19.4.0`](https://renovatebot.com/diffs/npm/@commitlint%2fcli/19.3.0/19.4.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@commitlint%2fcli/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@commitlint%2fcli/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@commitlint%2fcli/19.3.0/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@commitlint%2fcli/19.3.0/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@fal-ai/serverless-client](https://togithub.com/fal-ai/fal-js) ([source](https://togithub.com/fal-ai/fal-js/tree/HEAD/libs/client)) | [`^0.13.0` -> `^0.14.0`](https://renovatebot.com/diffs/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@fal-ai%2fserverless-client/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@fal-ai%2fserverless-client/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@fal-ai%2fserverless-client/0.13.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@floating-ui/dom](https://floating-ui.com) ([source](https://togithub.com/floating-ui/floating-ui/tree/HEAD/packages/dom)) | [`1.6.8` -> `1.6.10`](https://renovatebot.com/diffs/npm/@floating-ui%2fdom/1.6.8/1.6.10) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@floating-ui%2fdom/1.6.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@floating-ui%2fdom/1.6.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@floating-ui%2fdom/1.6.8/1.6.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@floating-ui%2fdom/1.6.8/1.6.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@napi-rs/cli](https://togithub.com/napi-rs/napi-rs) | [`3.0.0-alpha.60` -> `3.0.0-alpha.62`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/3.0.0-alpha.60/3.0.0-alpha.62?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@nestjs/common](https://nestjs.com) ([source](https://togithub.com/nestjs/nest/tree/HEAD/packages/common)) | [`10.3.10` -> `10.4.1`](https://renovatebot.com/diffs/npm/@nestjs%2fcommon/10.3.10/10.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcommon/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcommon/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcommon/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcommon/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@nestjs/core](https://nestjs.com) ([source](https://togithub.com/nestjs/nest/tree/HEAD/packages/core)) | [`10.3.10` -> `10.4.1`](https://renovatebot.com/diffs/npm/@nestjs%2fcore/10.3.10/10.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcore/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcore/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcore/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcore/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@nestjs/platform-express](https://nestjs.com) ([source](https://togithub.com/nestjs/nest/tree/HEAD/packages/platform-express)) | [`10.3.10` -> `10.4.1`](https://renovatebot.com/diffs/npm/@nestjs%2fplatform-express/10.3.10/10.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fplatform-express/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fplatform-express/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fplatform-express/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fplatform-express/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@nestjs/platform-socket.io](https://nestjs.com) ([source](https://togithub.com/nestjs/nest/tree/HEAD/packages/platform-socket.io)) | [`10.3.10` -> `10.4.1`](https://renovatebot.com/diffs/npm/@nestjs%2fplatform-socket.io/10.3.10/10.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fplatform-socket.io/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fplatform-socket.io/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fplatform-socket.io/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fplatform-socket.io/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@nestjs/testing](https://nestjs.com) ([source](https://togithub.com/nestjs/nest/tree/HEAD/packages/testing)) | [`10.3.10` -> `10.4.1`](https://renovatebot.com/diffs/npm/@nestjs%2ftesting/10.3.10/10.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2ftesting/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2ftesting/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2ftesting/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2ftesting/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@nestjs/websockets](https://togithub.com/nestjs/nest) ([source](https://togithub.com/nestjs/nest/tree/HEAD/packages/websockets)) | [`10.3.10` -> `10.4.1`](https://renovatebot.com/diffs/npm/@nestjs%2fwebsockets/10.3.10/10.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fwebsockets/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fwebsockets/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fwebsockets/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fwebsockets/10.3.10/10.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@nx/vite](https://nx.dev) ([source](https://togithub.com/nrwl/nx/tree/HEAD/packages/vite)) | [`19.5.3` -> `19.6.0`](https://renovatebot.com/diffs/npm/@nx%2fvite/19.5.3/19.6.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@nx%2fvite/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nx%2fvite/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nx%2fvite/19.5.3/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nx%2fvite/19.5.3/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@playwright/test](https://playwright.dev) ([source](https://togithub.com/microsoft/playwright)) | [`=1.44.1` -> `=1.46.1`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.44.1/1.46.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@playwright%2ftest/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@playwright%2ftest/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@prisma/client](https://www.prisma.io) ([source](https://togithub.com/prisma/prisma/tree/HEAD/packages/client)) | [`5.17.0` -> `5.18.0`](https://renovatebot.com/diffs/npm/@prisma%2fclient/5.17.0/5.18.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@prisma%2fclient/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@prisma%2fclient/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@prisma%2fclient/5.17.0/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@prisma%2fclient/5.17.0/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@prisma/instrumentation](https://www.prisma.io) ([source](https://togithub.com/prisma/prisma/tree/HEAD/packages/instrumentation)) | [`5.17.0` -> `5.18.0`](https://renovatebot.com/diffs/npm/@prisma%2finstrumentation/5.17.0/5.18.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@prisma%2finstrumentation/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@prisma%2finstrumentation/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@prisma%2finstrumentation/5.17.0/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@prisma%2finstrumentation/5.17.0/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@sentry/esbuild-plugin](https://togithub.com/getsentry/sentry-javascript-bundler-plugins/tree/main/packages/esbuild-plugin) ([source](https://togithub.com/getsentry/sentry-javascript-bundler-plugins)) | [`2.21.1` -> `2.22.2`](https://renovatebot.com/diffs/npm/@sentry%2fesbuild-plugin/2.21.1/2.22.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2fesbuild-plugin/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2fesbuild-plugin/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2fesbuild-plugin/2.21.1/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2fesbuild-plugin/2.21.1/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@sentry/integrations](https://togithub.com/getsentry/sentry-javascript/tree/master/packages/integrations) ([source](https://togithub.com/getsentry/sentry-javascript)) | [`7.118.0` -> `7.119.0`](https://renovatebot.com/diffs/npm/@sentry%2fintegrations/7.118.0/7.119.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2fintegrations/7.119.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2fintegrations/7.119.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2fintegrations/7.118.0/7.119.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2fintegrations/7.118.0/7.119.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@sentry/react](https://togithub.com/getsentry/sentry-javascript/tree/master/packages/react) ([source](https://togithub.com/getsentry/sentry-javascript)) | [`8.20.0` -> `8.26.0`](https://renovatebot.com/diffs/npm/@sentry%2freact/8.20.0/8.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2freact/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2freact/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2freact/8.20.0/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2freact/8.20.0/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@sentry/react](https://togithub.com/getsentry/sentry-javascript/tree/master/packages/react) ([source](https://togithub.com/getsentry/sentry-javascript)) | [`8.20.0` -> `8.26.0`](https://renovatebot.com/diffs/npm/@sentry%2freact/8.20.0/8.26.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2freact/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2freact/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2freact/8.20.0/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2freact/8.20.0/8.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@sentry/webpack-plugin](https://togithub.com/getsentry/sentry-javascript-bundler-plugins/tree/main/packages/webpack-plugin) ([source](https://togithub.com/getsentry/sentry-javascript-bundler-plugins)) | [`2.21.1` -> `2.22.2`](https://renovatebot.com/diffs/npm/@sentry%2fwebpack-plugin/2.21.1/2.22.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@sentry%2fwebpack-plugin/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@sentry%2fwebpack-plugin/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@sentry%2fwebpack-plugin/2.21.1/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@sentry%2fwebpack-plugin/2.21.1/2.22.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@swc/core](https://swc.rs) ([source](https://togithub.com/swc-project/swc)) | [`1.6.13` -> `1.7.12`](https://renovatebot.com/diffs/npm/@swc%2fcore/1.6.13/1.7.12) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@swc%2fcore/1.7.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@swc%2fcore/1.7.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@swc%2fcore/1.6.13/1.7.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@swc%2fcore/1.6.13/1.7.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@tanstack/react-table](https://tanstack.com/table) ([source](https://togithub.com/TanStack/table/tree/HEAD/packages/react-table)) | [`8.19.3` -> `8.20.1`](https://renovatebot.com/diffs/npm/@tanstack%2freact-table/8.19.3/8.20.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@tanstack%2freact-table/8.20.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@tanstack%2freact-table/8.20.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@tanstack%2freact-table/8.19.3/8.20.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@tanstack%2freact-table/8.19.3/8.20.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [@toeverything/theme](https://togithub.com/toeverything/design) | [`1.0.4` -> `1.0.5`](https://renovatebot.com/diffs/npm/@toeverything%2ftheme/1.0.4/1.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@toeverything%2ftheme/1.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@toeverything%2ftheme/1.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@toeverything%2ftheme/1.0.4/1.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@toeverything%2ftheme/1.0.4/1.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`20.14.12` -> `20.16.1`](https://renovatebot.com/diffs/npm/@types%2fnode/20.14.12/20.16.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.14.12/20.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.14.12/20.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [@types/ws](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ws) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws)) | [`8.5.11` -> `8.5.12`](https://renovatebot.com/diffs/npm/@types%2fws/8.5.11/8.5.12) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fws/8.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fws/8.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fws/8.5.11/8.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fws/8.5.11/8.5.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@vanilla-extract/css](https://togithub.com/vanilla-extract-css/vanilla-extract) ([source](https://togithub.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/css)) | [`1.15.3` -> `1.15.4`](https://renovatebot.com/diffs/npm/@vanilla-extract%2fcss/1.15.3/1.15.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vanilla-extract%2fcss/1.15.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vanilla-extract%2fcss/1.15.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vanilla-extract%2fcss/1.15.3/1.15.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vanilla-extract%2fcss/1.15.3/1.15.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@vanilla-extract/dynamic](https://togithub.com/vanilla-extract-css/vanilla-extract) ([source](https://togithub.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/dynamic)) | [`2.1.1` -> `2.1.2`](https://renovatebot.com/diffs/npm/@vanilla-extract%2fdynamic/2.1.1/2.1.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vanilla-extract%2fdynamic/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vanilla-extract%2fdynamic/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vanilla-extract%2fdynamic/2.1.1/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vanilla-extract%2fdynamic/2.1.1/2.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [@vanilla-extract/vite-plugin](https://togithub.com/vanilla-extract-css/vanilla-extract) ([source](https://togithub.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/vite-plugin)) | [`4.0.13` -> `4.0.14`](https://renovatebot.com/diffs/npm/@vanilla-extract%2fvite-plugin/4.0.13/4.0.14) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vanilla-extract%2fvite-plugin/4.0.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vanilla-extract%2fvite-plugin/4.0.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vanilla-extract%2fvite-plugin/4.0.13/4.0.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vanilla-extract%2fvite-plugin/4.0.13/4.0.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [@vanilla-extract/webpack-plugin](https://togithub.com/vanilla-extract-css/vanilla-extract) ([source](https://togithub.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/webpack-plugin)) | [`2.3.11` -> `2.3.12`](https://renovatebot.com/diffs/npm/@vanilla-extract%2fwebpack-plugin/2.3.11/2.3.12) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@vanilla-extract%2fwebpack-plugin/2.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vanilla-extract%2fwebpack-plugin/2.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vanilla-extract%2fwebpack-plugin/2.3.11/2.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vanilla-extract%2fwebpack-plugin/2.3.11/2.3.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [autoprefixer](https://togithub.com/postcss/autoprefixer) | [`10.4.19` -> `10.4.20`](https://renovatebot.com/diffs/npm/autoprefixer/10.4.19/10.4.20) | [![age](https://developer.mend.io/api/mc/badges/age/npm/autoprefixer/10.4.20?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/autoprefixer/10.4.20?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/autoprefixer/10.4.19/10.4.20?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/autoprefixer/10.4.19/10.4.20?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [commitlint](https://commitlint.js.org/) ([source](https://togithub.com/conventional-changelog/commitlint/tree/HEAD/@alias/commitlint)) | [`19.3.0` -> `19.4.0`](https://renovatebot.com/diffs/npm/commitlint/19.3.0/19.4.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/commitlint/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/commitlint/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/commitlint/19.3.0/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/commitlint/19.3.0/19.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [core-js](https://togithub.com/zloirock/core-js) ([source](https://togithub.com/zloirock/core-js/tree/HEAD/packages/core-js)) | [`3.37.1` -> `3.38.0`](https://renovatebot.com/diffs/npm/core-js/3.37.1/3.38.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/core-js/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/core-js/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/core-js/3.37.1/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/core-js/3.37.1/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [core-js](https://togithub.com/zloirock/core-js) ([source](https://togithub.com/zloirock/core-js/tree/HEAD/packages/core-js)) | [`3.37.1` -> `3.38.0`](https://renovatebot.com/diffs/npm/core-js/3.37.1/3.38.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/core-js/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/core-js/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/core-js/3.37.1/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/core-js/3.37.1/3.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [cssnano](https://togithub.com/cssnano/cssnano) | [`7.0.4` -> `7.0.5`](https://renovatebot.com/diffs/npm/cssnano/7.0.4/7.0.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/cssnano/7.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/cssnano/7.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/cssnano/7.0.4/7.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/cssnano/7.0.4/7.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [electron](https://togithub.com/electron/electron) | [`~30.2.0` -> `~30.4.0`](https://renovatebot.com/diffs/npm/electron/30.2.0/30.4.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/electron/30.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/electron/30.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/electron/30.2.0/30.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/electron/30.2.0/30.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [embla-carousel-react](https://www.embla-carousel.com) ([source](https://togithub.com/davidjerleke/embla-carousel)) | [`8.1.7` -> `8.1.8`](https://renovatebot.com/diffs/npm/embla-carousel-react/8.1.7/8.1.8) | [![age](https://developer.mend.io/api/mc/badges/age/npm/embla-carousel-react/8.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/embla-carousel-react/8.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/embla-carousel-react/8.1.7/8.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/embla-carousel-react/8.1.7/8.1.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [esbuild](https://togithub.com/evanw/esbuild) | [`0.23.0` -> `0.23.1`](https://renovatebot.com/diffs/npm/esbuild/0.23.0/0.23.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/esbuild/0.23.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/esbuild/0.23.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/esbuild/0.23.0/0.23.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/esbuild/0.23.0/0.23.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [file-type](https://togithub.com/sindresorhus/file-type) | [`19.3.0` -> `19.4.1`](https://renovatebot.com/diffs/npm/file-type/19.3.0/19.4.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/file-type/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/file-type/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/file-type/19.3.0/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/file-type/19.3.0/19.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [husky](https://togithub.com/typicode/husky) | [`9.1.2` -> `9.1.4`](https://renovatebot.com/diffs/npm/husky/9.1.2/9.1.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/husky/9.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/husky/9.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/husky/9.1.2/9.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/husky/9.1.2/9.1.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [i18next](https://www.i18next.com) ([source](https://togithub.com/i18next/i18next)) | [`23.12.2` -> `23.13.0`](https://renovatebot.com/diffs/npm/i18next/23.12.2/23.13.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/i18next/23.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/i18next/23.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/i18next/23.12.2/23.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/i18next/23.12.2/23.13.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [is-svg](https://togithub.com/sindresorhus/is-svg) | [`5.0.1` -> `5.1.0`](https://renovatebot.com/diffs/npm/is-svg/5.0.1/5.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/is-svg/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/is-svg/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/is-svg/5.0.1/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/is-svg/5.0.1/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [jotai](https://togithub.com/pmndrs/jotai) | [`2.9.1` -> `2.9.3`](https://renovatebot.com/diffs/npm/jotai/2.9.1/2.9.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai/2.9.1/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai/2.9.1/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [jotai](https://togithub.com/pmndrs/jotai) | [`2.9.1` -> `2.9.3`](https://renovatebot.com/diffs/npm/jotai/2.9.1/2.9.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai/2.9.1/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai/2.9.1/2.9.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [jotai-devtools](https://togithub.com/jotaijs/jotai-devtools) | [`0.10.0` -> `0.10.1`](https://renovatebot.com/diffs/npm/jotai-devtools/0.10.0/0.10.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai-devtools/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai-devtools/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai-devtools/0.10.0/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai-devtools/0.10.0/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [jotai-devtools](https://togithub.com/jotaijs/jotai-devtools) | [`0.10.0` -> `0.10.1`](https://renovatebot.com/diffs/npm/jotai-devtools/0.10.0/0.10.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai-devtools/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai-devtools/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai-devtools/0.10.0/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai-devtools/0.10.0/0.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [jotai-scope](https://togithub.com/jotaijs/jotai-scope) | [`0.7.0` -> `0.7.1`](https://renovatebot.com/diffs/npm/jotai-scope/0.7.0/0.7.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/jotai-scope/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jotai-scope/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jotai-scope/0.7.0/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jotai-scope/0.7.0/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [lib0](https://togithub.com/dmonad/lib0) | [`0.2.95` -> `0.2.97`](https://renovatebot.com/diffs/npm/lib0/0.2.95/0.2.97) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lib0/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lib0/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lib0/0.2.95/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lib0/0.2.95/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [lib0](https://togithub.com/dmonad/lib0) | [`0.2.95` -> `0.2.97`](https://renovatebot.com/diffs/npm/lib0/0.2.95/0.2.97) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lib0/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lib0/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lib0/0.2.95/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lib0/0.2.95/0.2.97?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [lint-staged](https://togithub.com/lint-staged/lint-staged) | [`15.2.7` -> `15.2.9`](https://renovatebot.com/diffs/npm/lint-staged/15.2.7/15.2.9) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lint-staged/15.2.9?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lint-staged/15.2.9?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lint-staged/15.2.7/15.2.9?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lint-staged/15.2.7/15.2.9?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [lit](https://lit.dev/) ([source](https://togithub.com/lit/lit/tree/HEAD/packages/lit)) | [`3.1.4` -> `3.2.0`](https://renovatebot.com/diffs/npm/lit/3.1.4/3.2.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lit/3.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lit/3.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lit/3.1.4/3.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lit/3.1.4/3.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [lucide-react](https://lucide.dev) ([source](https://togithub.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react)) | [`^0.408.0` -> `^0.428.0`](https://renovatebot.com/diffs/npm/lucide-react/0.408.0/0.428.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/lucide-react/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lucide-react/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lucide-react/0.408.0/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lucide-react/0.408.0/0.428.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [mixpanel-browser](https://togithub.com/mixpanel/mixpanel-js) | [`2.54.0` -> `2.55.0`](https://renovatebot.com/diffs/npm/mixpanel-browser/2.54.0/2.55.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/mixpanel-browser/2.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/mixpanel-browser/2.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/mixpanel-browser/2.54.0/2.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/mixpanel-browser/2.54.0/2.55.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [msw](https://mswjs.io) ([source](https://togithub.com/mswjs/msw)) | [`2.3.4` -> `2.3.5`](https://renovatebot.com/diffs/npm/msw/2.3.4/2.3.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/msw/2.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/msw/2.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/msw/2.3.4/2.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/msw/2.3.4/2.3.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [napi](https://togithub.com/napi-rs/napi-rs) | `3.0.0-alpha.7` -> `3.0.0-alpha.8` | [![age](https://developer.mend.io/api/mc/badges/age/crate/napi/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi/3.0.0-alpha.7/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi/3.0.0-alpha.7/3.0.0-alpha.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [napi-derive](https://togithub.com/napi-rs/napi-rs) | `3.0.0-alpha.6` -> `3.0.0-alpha.7` | [![age](https://developer.mend.io/api/mc/badges/age/crate/napi-derive/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-derive/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-derive/3.0.0-alpha.6/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-derive/3.0.0-alpha.6/3.0.0-alpha.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | workspace.dependencies | patch |
| [nest-commander](https://nest-commander.jaymcdoniel.dev) ([source](https://togithub.com/jmcdo29/nest-commander/tree/HEAD/pacakges/nest-commander)) | [`3.14.0` -> `3.15.0`](https://renovatebot.com/diffs/npm/nest-commander/3.14.0/3.15.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nest-commander/3.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nest-commander/3.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nest-commander/3.14.0/3.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nest-commander/3.14.0/3.15.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [nestjs-throttler-storage-redis](https://togithub.com/kkoomen/nestjs-throttler-storage-redis) | [`^0.4.1` -> `^0.5.0`](https://renovatebot.com/diffs/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nestjs-throttler-storage-redis/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nestjs-throttler-storage-redis/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nestjs-throttler-storage-redis/0.4.4/0.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [node](https://nodejs.org) ([source](https://togithub.com/nodejs/node)) | `20.15.1` -> `20.16.0` | [![age](https://developer.mend.io/api/mc/badges/age/node-version/node/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/node-version/node/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/node-version/node/v20.15.1/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/node-version/node/v20.15.1/v20.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |  | minor |
| [nx](https://nx.dev) ([source](https://togithub.com/nrwl/nx/tree/HEAD/packages/nx)) | [`19.5.3` -> `19.6.0`](https://renovatebot.com/diffs/npm/nx/19.5.3/19.6.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/nx/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nx/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nx/19.5.3/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nx/19.5.3/19.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [openai](https://togithub.com/openai/openai-node) | [`4.53.2` -> `4.56.0`](https://renovatebot.com/diffs/npm/openai/4.53.2/4.56.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/openai/4.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/openai/4.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/openai/4.53.2/4.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/openai/4.53.2/4.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| openresty/openresty | `1.25.3.1-0-buster` -> `1.25.3.2-0-buster` | [![age](https://developer.mend.io/api/mc/badges/age/docker/openresty%2fopenresty/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/docker/openresty%2fopenresty/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/docker/openresty%2fopenresty/1.25.3.1/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/openresty%2fopenresty/1.25.3.1/1.25.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | final | patch |
| [playwright](https://playwright.dev) ([source](https://togithub.com/microsoft/playwright)) | [`=1.44.1` -> `=1.46.1`](https://renovatebot.com/diffs/npm/playwright/1.44.1/1.46.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/playwright/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/playwright/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/playwright/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/playwright/1.44.1/1.46.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [postcss](https://postcss.org/) ([source](https://togithub.com/postcss/postcss)) | [`8.4.40` -> `8.4.41`](https://renovatebot.com/diffs/npm/postcss/8.4.40/8.4.41) | [![age](https://developer.mend.io/api/mc/badges/age/npm/postcss/8.4.41?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/postcss/8.4.41?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/postcss/8.4.40/8.4.41?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/postcss/8.4.40/8.4.41?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | patch |
| [prisma](https://www.prisma.io) ([source](https://togithub.com/prisma/prisma/tree/HEAD/packages/cli)) | [`5.17.0` -> `5.18.0`](https://renovatebot.com/diffs/npm/prisma/5.17.0/5.18.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prisma/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prisma/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prisma/5.17.0/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prisma/5.17.0/5.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [react-hook-form](https://www.react-hook-form.com) ([source](https://togithub.com/react-hook-form/react-hook-form)) | [`7.52.1` -> `7.52.2`](https://renovatebot.com/diffs/npm/react-hook-form/7.52.1/7.52.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-hook-form/7.52.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-hook-form/7.52.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-hook-form/7.52.1/7.52.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-hook-form/7.52.1/7.52.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [react-i18next](https://togithub.com/i18next/react-i18next) | [`15.0.0` -> `15.0.1`](https://renovatebot.com/diffs/npm/react-i18next/15.0.0/15.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-i18next/15.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-i18next/15.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-i18next/15.0.0/15.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-i18next/15.0.0/15.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | patch |
| [react-refresh](https://reactjs.org/) ([source](https://togithub.com/facebook/react/tree/HEAD/packages/react)) | [`^0.10.0` -> `^0.14.0`](https://renovatebot.com/diffs/npm/react-refresh/0.10.0/0.14.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-refresh/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-refresh/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-refresh/0.10.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-refresh/0.10.0/0.14.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | devDependencies | minor |
| [react-resizable-panels](https://togithub.com/bvaughn/react-resizable-panels) | [`2.0.22` -> `2.1.0`](https://renovatebot.com/diffs/npm/react-resizable-panels/2.0.22/2.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-resizable-panels/2.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-resizable-panels/2.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-resizable-panels/2.0.22/2.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-resizable-panels/2.0.22/2.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | dependencies | minor |
| [react-router-dom](https://togithub.com/remix-run/react-router) ([source](https://togithub.com/remix-run/react-router/tree/HEAD/packages/react-router-dom)) | [`6.25.1` -> `6.26.1`](https://renovatebot.com/diffs/npm/react-router-dom/6.25.1/6.26.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react-router-dom/6.26.1?slim=true)](https://docs.renovatebot.com/merge
2024-08-19 07:51:51 +00:00
pengx17
4a89b1a5dd fix(electron): adjust tab styles (#7919)
![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/121ee595-99f0-43cb-be5f-ca1bdd15d6ca.png)

fix AF-1261
2024-08-19 06:15:06 +00:00
JimmFly
4916eea24f feat(core): new share menu (#7838)
close AF-1224 AF-1216

![image](https://github.com/user-attachments/assets/204c408a-3dab-4068-86f6-e20abcfa863c)
2024-08-19 05:51:05 +00:00
EYHN
cfac3ebf1f feat(core): workbench open doc in mode (#7906) 2024-08-19 02:37:33 +00:00
pengx17
e0a91f63d3 fix(core): tag menu should not accept keyboard shortcut when renaming tag (#7913)
fix #7890, fix PD-1603
2024-08-18 08:29:25 +00:00
pengx17
23c73243ab chore(electron): re-enable sentry for electron (#7898)
related
https://github.com/toeverything/AFFiNE/pull/7001
2024-08-17 04:32:49 +00:00
renovate[bot]
f324fa4719 chore: bump up storybook monorepo to v8 (major) (#6068)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: EYHN <cneyhn@gmail.com>
2024-08-16 11:42:24 +00:00
EYHN
c822594882 feat(core): mode in query string (#7904) 2024-08-16 10:59:43 +00:00
EYHN
83716c2fd9 feat(core): share in workspace link (#7897)
ShareDocsService -> ShareDocsListService
ShareService -> ShareInfoService
(*new) ShareReaderService

`/share/:workspaceId/:docId` -> redirect to -> `/workspace/:workspaceId/:docId`

workspace loading process

1. find workspace in workspace list
2. (if not found) revalidate workspace list
3. (if still not found) try load share page
4. (if share page found) => share page
5. (if share page not found) => 404
6. (if workspace found) => workspace page
2024-08-16 09:12:18 +00:00
L-Sun
620d20710a chore: bump bs (#7899)
Bump blocksuite from https://github.com/toeverything/blocksuite/pull/7934

## Bugfix
- https://github.com/toeverything/BlockSuite/pull/7985 @L-Sun

## Misc
- https://github.com/toeverything/BlockSuite/pull/7971 @L-Sun
- https://github.com/toeverything/BlockSuite/pull/7965 @doouding
2024-08-16 08:46:16 +00:00
CatsJuice
cfc367efe7 feat(component): add more customizable prop for radio-group with new story (#7850)
![CleanShot 2024-08-13 at 16.40.22@2x.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/LakojjjzZNf6ogjOVwKE/06a128c3-f0bb-47f9-babf-6d4eca2597d7.png)
2024-08-16 07:19:16 +00:00
pengx17
69c507fded fix(electron): do not use async callback in onBeforeSendHeaders (#7894)
it seems using async callback for onBeforeSendHeaders may crash the app.
the main reason why it is async is to read the cookies from session.

fix AF-1172
2024-08-16 05:17:47 +00:00
pengx17
b57ce4646f chore(electron): adjust log level (#7887) 2024-08-16 05:17:46 +00:00
Brooooooklyn
dba024d561 docs: update LICENSE description (#7869) 2024-08-15 14:29:07 +00:00
darkskygit
e26ba48a45 feat: update ingress health check (#7888) 2024-08-15 12:16:25 +00:00
forehalo
e53dde7944 test(server): all instance variants (#7882) 2024-08-15 10:01:54 +00:00
forehalo
624f3514fc feat(server): make permission a standalone module (#7880) 2024-08-15 10:01:52 +00:00
donteatfriedrice
ba8958f39b fix: chat block peek view input reset height (#7884)
[BS-1202](https://linear.app/affine-design/issue/BS-1202/ai-chat-block-输入大段内容发送后输入框-resize-问题)
2024-08-15 08:08:00 +00:00
pengx17
9af0e53ae2 fix(electron): header button not working on linux (#7883)
tested locally on windows/linux(vm)
2024-08-15 04:39:47 +00:00
forehalo
5a2f93f035 chore(admin): disable ai settings (#7877) 2024-08-15 02:50:46 +00:00
forehalo
9192ac4420 fix(server): command line nestjs does not have http adapter (#7876) 2024-08-14 13:41:23 +00:00
liuyi
57449c1530 fix(server): redirect to setup page if not initialized (#7875) 2024-08-14 21:02:16 +08:00
EYHN
89537e6892 refactor(core): separate editor & doc mode (#7873)
doc.mode -> primaryMode
(*new) editor.mode

New Service:
editor service

Change Mode:

```
const editor = useService(EditorService).editor;
editor.setMode('page')
```

Change primary mode

```
const editor = useService(EditorService).editor;
editor.doc.setPrimaryMode('page')
```
2024-08-14 11:43:03 +00:00
EYHN
50948318e0 feat(core): use emoji as folder icon (#7842)
![CleanShot 2024-08-12 at 22.33.42.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/g3jz87HxbjOJpXV3FPT7/c0c1a196-be29-4e45-a28d-87a55d80fc9d.png)
2024-08-14 10:35:22 +00:00
EYHN
0504d0b0ff feat(core): init feature flag service (#7856) 2024-08-14 10:35:21 +00:00
darkskygit
339c39c1ec feat: improve prompt management (#7853) 2024-08-14 08:38:36 +00:00
forehalo
cd3924b8fc Revert "fix(server): redirect to setup page if not initialized (#7871)"
This reverts commit 42b5ef7a8b.
2024-08-14 16:37:52 +08:00
liuyi
42b5ef7a8b fix(server): redirect to setup page if not initialized (#7871) 2024-08-14 08:05:55 +00:00
donteatfriedrice
ad42418089 fix: add hover enter delay for ask ai button (#7872)
[AF-1075](https://linear.app/affine-design/issue/AF-1075/双击选中内容的时候,如果-toolbar-出现在内容上方,ai-action-会自动展开)
2024-08-14 07:27:17 +00:00
forehalo
99e70c91e8 perf(core): avoid page init when only id required (#7867) 2024-08-14 05:22:18 +00:00
doouding
05ac3dbdcb feat: bump bs (#7866) 2024-08-14 04:42:20 +00:00
JimmFly
994b539507 fix(admin): user form not dynamically updating as expected (#7858)
- Fixed the issue that a certain feature must be enabled when creating a user
- Fixed the issue that the modified content was not reset to the default content when exiting the user form without saving after modification
- Fixed the issue that the content did not switch as expected when switching user forms of different users

https://github.com/user-attachments/assets/02567021-9342-4ed1-be77-3bdcbb3d86ab
2024-08-14 04:28:15 +00:00
pengx17
d5edadabe6 fix(electron): cmd+num not working on mac (#7865)
fix AF-1248
hidden menu group + acceleratorWorksWhenHidden does not work on mac
2024-08-14 04:14:16 +00:00
JimmFly
05247bb24e fix(admin): frequent query requests in the search (#7854) 2024-08-14 03:49:45 +00:00
forehalo
f69f026ac3 fix(admin): avoid frequent refetch (#7863) 2024-08-14 03:34:41 +00:00
forehalo
015247345c chore(admin): organize massive routes (#7857) 2024-08-14 03:34:38 +00:00
forehalo
0ba516866f fix(server): change password with token should be public (#7855) 2024-08-14 03:34:35 +00:00
forehalo
7afba6b8b5 fix(server): prelude should load both local and remote config file (#7852) 2024-08-14 03:34:33 +00:00
renovate
08cc15a55c chore: bump up oxlint version to v0.7.1 (#7846)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [oxlint](https://oxc.rs) ([source](https://togithub.com/oxc-project/oxc/tree/HEAD/npm/oxlint)) | [`0.7.0` -> `0.7.1`](https://renovatebot.com/diffs/npm/oxlint/0.7.0/0.7.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint/0.7.0/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint/0.7.0/0.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxlint)</summary>

### [`v0.7.1`](https://togithub.com/oxc-project/oxc/blob/HEAD/npm/oxlint/CHANGELOG.md#071---2024-08-12)

[Compare Source](3ac02fd838...972492cc4d)

##### Features

-   [`cc922f4`](https://togithub.com/oxc-project/oxc/commit/cc922f4) vscode: Provide config's schema to oxlint config files ([#&#8203;4826](https://togithub.com/oxc-project/oxc/issues/4826)) (Don Isaac)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4yMC4xIiwidXBkYXRlZEluVmVyIjoiMzguMjAuMSIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2024-08-13 14:02:00 +00:00
DarkSky
24c34eb3fc fix: admin panel schema (#7851) 2024-08-13 09:16:56 +00:00
JimmFly
ba5ba71f35 chore: add test for all collection and all tag (#7687) 2024-08-13 08:19:54 +00:00
pengx17
d4065fee78 fix(electron): adjust app-tabs-header styles (#7849) 2024-08-13 08:06:30 +00:00
pengx17
d86f7f41dc fix: center peek support open in new tab (#7848) 2024-08-13 07:52:03 +00:00
961 changed files with 37296 additions and 21984 deletions

View File

@@ -34,8 +34,8 @@ const createPattern = packageName => [
{
group: ['@affine/env/constant'],
message:
'Do not import from @affine/env/constant. Use `environment.isDesktop` instead',
importNames: ['isDesktop'],
'Do not import from @affine/env/constant. Use `environment.isElectron` instead',
importNames: ['isElectron'],
},
];
@@ -248,7 +248,7 @@ const config = {
'warn',
{
additionalHooks:
'(useAsyncCallback|useCatchEventCallback|useDraggable|useDropTarget)',
'(useAsyncCallback|useCatchEventCallback|useDraggable|useDropTarget|useRefEffect)',
},
],
},

36
.github/actions/cluster-auth/action.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: 'Auth to Cluster'
description: 'Auth to the GCP Cluster'
inputs:
gcp-project-number:
description: 'GCP project number'
required: true
gcp-project-id:
description: 'GCP project id'
required: true
service-account:
description: 'Service account'
cluster-name:
description: 'Cluster name'
cluster-location:
description: 'Cluster location'
runs:
using: 'composite'
steps:
- id: auth
uses: google-github-actions/auth@v2
with:
workload_identity_provider: 'projects/${{ inputs.gcp-project-number }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-helm-deploy'
service_account: '${{ inputs.service-account }}'
token_format: 'access_token'
project_id: '${{ inputs.gcp-project-id }}'
- name: 'Setup gcloud cli'
uses: 'google-github-actions/setup-gcloud@v2'
with:
install_components: 'gke-gcloud-auth-plugin'
- id: get-gke-credentials
shell: bash
run: |
gcloud container clusters get-credentials ${{ inputs.cluster-name }} --region ${{ inputs.cluster-location }} --project ${{ inputs.gcp-project-id }}

View File

@@ -24,24 +24,14 @@ runs:
shell: bash
run: |
echo "GIT_SHORT_HASH=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
- uses: azure/setup-helm@v4
- id: auth
uses: google-github-actions/auth@v2
- name: 'Auth to cluster'
uses: './.github/actions/cluster-auth'
with:
workload_identity_provider: 'projects/${{ inputs.gcp-project-number }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-helm-deploy'
service_account: '${{ inputs.service-account }}'
token_format: 'access_token'
project_id: '${{ inputs.gcp-project-id }}'
- name: 'Setup gcloud cli'
uses: 'google-github-actions/setup-gcloud@v2'
with:
install_components: 'gke-gcloud-auth-plugin'
- id: get-gke-credentials
shell: bash
run: |
gcloud container clusters get-credentials ${{ inputs.cluster-name }} --region ${{ inputs.cluster-location }} --project ${{ inputs.gcp-project-id }}
gcp-project-number: '${{ inputs.gcp-project-number }}'
gcp-project-id: '${{ inputs.gcp-project-id }}'
service-account: '${{ inputs.service-account }}'
cluster-name: '${{ inputs.cluster-name }}'
cluster-location: '${{ inputs.cluster-location }}'
- name: Deploy
shell: bash

View File

@@ -156,7 +156,7 @@ runs:
- name: Install Playwright's dependencies
shell: bash
if: inputs.playwright-install == 'true'
run: yarn playwright install --with-deps chromium
run: yarn playwright install --with-deps chromium webkit
env:
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/node_modules/.cache/ms-playwright

View File

@@ -1,7 +1,8 @@
FROM openresty/openresty:1.25.3.1-0-buster
FROM openresty/openresty:1.25.3.2-0-buster
WORKDIR /app
COPY ./packages/frontend/web/dist ./dist
COPY ./packages/frontend/admin/dist ./admin
COPY ./packages/frontend/mobile/dist ./mobile
COPY ./.github/deployment/front/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
COPY ./.github/deployment/front/affine.nginx.conf /etc/nginx/conf.d/affine.nginx.conf

View File

@@ -11,10 +11,28 @@ server {
try_files $uri $uri/ =404;
}
set $app_root_path /app/dist/;
set $mobile_root /app/dist/;
set_by_lua $affine_env 'return os.getenv("AFFINE_ENV")';
if ($affine_env = "dev") {
set $mobile_root /app/mobile/;
}
# https://gist.github.com/mariusom/6683dc52b1cad1a1f372e908bdb209d0
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
set $app_root_path $mobile_root;
}
if ($http_user_agent ~* "^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)") {
set $app_root_path $mobile_root;
}
location / {
root /app/dist/;
root $app_root_path;
index index.html;
try_files $uri $uri/ /index.html;
add_header Cache-Control "private, no-cache, no-store, max-age=0, must-revalidate";
}
error_page 404 /404.html;

View File

@@ -1,14 +1,15 @@
worker_processes 4;
worker_processes 4;
error_log /var/log/nginx/error.log warn;
pcre_jit on;
env AFFINE_ENV;
events {
worker_connections 1024;
worker_connections 1024;
}
http {
include mime.types;
log_format main '$remote_addr [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
include /etc/nginx/conf.d/*.conf;
include mime.types;
log_format main '$remote_addr [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
include /etc/nginx/conf.d/*.conf;
}

View File

@@ -77,8 +77,6 @@ spec:
value: "{{ .Values.app.https }}"
- name: ENABLE_R2_OBJECT_STORAGE
value: "{{ .Values.app.objectStorage.r2.enabled }}"
- name: ENABLE_CAPTCHA
value: "{{ .Values.app.captcha.enabled }}"
- name: FEATURES_EARLY_ACCESS_PREVIEW
value: "{{ .Values.app.features.earlyAccessPreview }}"
- name: FEATURES_SYNC_CLIENT_VERSION_CHECK
@@ -204,12 +202,12 @@ spec:
protocol: TCP
livenessProbe:
httpGet:
path: /
path: /info
port: http
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
readinessProbe:
httpGet:
path: /
path: /info
port: http
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
resources:

View File

@@ -4,6 +4,10 @@ metadata:
name: {{ include "graphql.fullname" . }}
labels:
{{- include "graphql.labels" . | nindent 4 }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
ports:

View File

@@ -27,6 +27,9 @@ spec:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: AFFINE_ENV
value: "{{ .Release.Namespace }}"
ports:
- name: http
containerPort: {{ .Values.service.port }}

View File

@@ -60,13 +60,6 @@ spec:
name: affine-graphql
port:
number: {{ .Values.graphql.service.port }}
- path: /oauth
pathType: Prefix
backend:
service:
name: affine-graphql
port:
number: {{ .Values.graphql.service.port }}
- path: /
pathType: Prefix
backend:

View File

@@ -36,14 +36,14 @@ graphql:
type: ClusterIP
port: 3000
annotations:
cloud.google.com/backend-config: '{"default": "affine-backendconfig"}'
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
sync:
service:
type: ClusterIP
port: 3010
annotations:
cloud.google.com/backend-config: '{"default": "affine-backendconfig"}'
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
web:
service:

View File

@@ -0,0 +1,10 @@
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: "affine-api-backendconfig"
spec:
healthCheck:
timeoutSec: 1
type: HTTP
requestPath: /info

View File

@@ -143,6 +143,36 @@ jobs:
path: ./test-results
if-no-files-found: ignore
e2e-mobile-test:
name: E2E Mobile Test
runs-on: ubuntu-latest
env:
DISTRIBUTION: mobile
IN_CI_TEST: true
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
playwright-install: true
electron-install: false
full-cache: true
- name: Run playwright tests
run: yarn workspace @affine-test/affine-mobile e2e --forbid-only --shard=${{ matrix.shard }}/${{ strategy.job-total }}
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: test-results-e2e-mobile-${{ matrix.shard }}
path: ./test-results
if-no-files-found: ignore
e2e-migration-test:
name: E2E Migration Test
runs-on: ubuntu-latest
@@ -180,7 +210,7 @@ jobs:
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
electron-install: true
full-cache: true
- name: Download affine.linux-x64-gnu.node
@@ -571,6 +601,7 @@ jobs:
- lint
- check-yarn-binary
- e2e-test
- e2e-mobile-test
- e2e-migration-test
- unit-test
- server-test

View File

@@ -21,6 +21,47 @@ permissions:
packages: 'write'
jobs:
output-prev-version:
name: Output previous version
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.flavor }}
outputs:
prev: ${{ steps.print.outputs.version }}
namespace: ${{ steps.print.outputs.namespace }}
steps:
- uses: actions/checkout@v4
- name: Auth to Cluster
uses: './.github/actions/cluster-auth'
with:
gcp-project-number: ${{ secrets.GCP_PROJECT_NUMBER }}
gcp-project-id: ${{ secrets.GCP_PROJECT_ID }}
service-account: ${{ secrets.GCP_HELM_DEPLOY_SERVICE_ACCOUNT }}
cluster-name: ${{ secrets.GCP_CLUSTER_NAME }}
cluster-location: ${{ secrets.GCP_CLUSTER_LOCATION }}
- name: Output previous version
id: print
run: |
namespace=""
if [ "${{ github.event.inputs.flavor }}" = "canary" ]; then
namespace="dev"
elif [ "${{ github.event.inputs.flavor }}" = "beta" ]; then
namespace="beta"
elif [ "${{ github.event.inputs.flavor }}" = "stable" ]; then
namespace="production"
else
echo "Invalid flavor: ${{ github.event.inputs.flavor }}"
exit 1
fi
echo "Namespace set to: $namespace"
# Get the previous version from the deployment
prev_version=$(kubectl get deployment -n $namespace affine-graphql -o=jsonpath='{.spec.template.spec.containers[0].image}' | awk -F '-' '{print $3}')
echo "Previous version: $prev_version"
echo "version=$prev_version" >> $GITHUB_OUTPUT
echo "namesapce=$namespace" >> $GITHUB_OUTPUT
build-server-image:
name: Build Server Image
uses: ./.github/workflows/build-server-image.yml
@@ -71,7 +112,7 @@ jobs:
uses: ./.github/actions/setup-version
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Build Core
- name: Build Admin
run: yarn nx build @affine/admin --skip-nx-cache
env:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
@@ -92,12 +133,45 @@ jobs:
path: ./packages/frontend/admin/dist
if-no-files-found: error
build-mobile:
name: Build @affine/mobile
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.flavor }}
steps:
- uses: actions/checkout@v4
- name: Setup Version
id: version
uses: ./.github/actions/setup-version
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Build Mobile
run: yarn nx build @affine/mobile --skip-nx-cache
env:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
BUILD_TYPE: ${{ github.event.inputs.flavor }}
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: 'affine-mobile'
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
- name: Upload mobile artifact
uses: actions/upload-artifact@v4
with:
name: mobile
path: ./packages/frontend/mobile/dist
if-no-files-found: error
build-frontend-image:
name: Build Frontend Image
runs-on: ubuntu-latest
needs:
- build-web
- build-admin
- build-mobile
steps:
- uses: actions/checkout@v4
- name: Download web artifact
@@ -110,6 +184,11 @@ jobs:
with:
name: admin
path: ./packages/frontend/admin/dist
- name: Download mobile artifact
uses: actions/download-artifact@v4
with:
name: mobile
path: ./packages/frontend/mobile/dist
- name: Setup env
run: |
echo "GIT_SHORT_HASH=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
@@ -193,3 +272,98 @@ jobs:
STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
STRIPE_WEBHOOK_KEY: ${{ secrets.STRIPE_WEBHOOK_KEY }}
STATIC_IP_NAME: ${{ secrets.STATIC_IP_NAME }}
deploy-done:
needs:
- output-prev-version
- build-web
- build-admin
- build-mobile
- build-frontend-image
- build-server-image
- deploy
if: always()
runs-on: ubuntu-latest
name: Post deploy message
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
with:
repository: toeverything/blocksuite
path: blocksuite
fetch-depth: 0
fetch-tags: true
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
extra-flags: 'workspaces focus @affine/changelog'
electron-install: false
- name: Output deployed info
if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
id: set_info
run: |
if [ "${{ github.event.inputs.flavor }}" = "canary" ]; then
echo "deployed_url=https://affine.fail" >> $GITHUB_OUTPUT
elif [ "${{ github.event.inputs.flavor }}" = "beta" ]; then
echo "deployed_url=https://insider.affine.pro" >> $GITHUB_OUTPUT
elif [ "${{ github.event.inputs.flavor }}" = "stable" ]; then
echo "deployed_url=https://app.affine.pro" >> $GITHUB_OUTPUT
else
exit 1
fi
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Post Success event to a Slack channel
if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
run: node ./tools/changelog/index.js
env:
CHANNEL_ID: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
DEPLOYED_URL: ${{ steps.set_info.outputs.deployed_url }}
PREV_VERSION: ${{ needs.output-prev-version.outputs.prev }}
NAMESPACE: ${{ needs.output-prev-version.outputs.namespace }}
DEPLOYMENT: 'SERVER'
FLAVOR: ${{ github.event.inputs.flavor }}
BLOCKSUITE_REPO_PATH: ${{ github.workspace }}/blocksuite
- name: Post Failed event to a Slack channel
id: failed-slack
uses: slackapi/slack-github-action@v1.27.0
if: ${{ always() && contains(needs.*.result, 'failure') }}
with:
channel-id: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
payload: |
{
"blocks": [
{
"type": "section",
"text": {
"text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Backend deploy failed `${{ github.event.inputs.flavor }}`>",
"type": "mrkdwn"
}
}
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- name: Post Cancel event to a Slack channel
id: cancel-slack
uses: slackapi/slack-github-action@v1.27.0
if: ${{ always() && contains(needs.*.result, 'cancelled') && !contains(needs.*.result, 'failure') }}
with:
channel-id: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
payload: |
{
"blocks": [
{
"type": "section",
"text": {
"text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Backend deploy cancelled `${{ github.event.inputs.flavor }}`>",
"type": "mrkdwn"
}
}
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

2
.nvmrc
View File

@@ -1 +1 @@
20.15.1
20.17.0

File diff suppressed because one or more lines are too long

925
.yarn/releases/yarn-4.4.1.cjs vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -12,4 +12,4 @@ npmPublishAccess: public
npmPublishRegistry: "https://registry.npmjs.org"
yarnPath: .yarn/releases/yarn-4.3.1.cjs
yarnPath: .yarn/releases/yarn-4.4.1.cjs

619
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ rand = "0.8"
serde = "1"
serde_json = "1"
sha3 = "0.10"
sqlx = { version = "0.7", default-features = false, features = ["chrono", "macros", "migrate", "runtime-tokio", "sqlite", "tls-rustls"] }
sqlx = { version = "0.8", default-features = false, features = ["chrono", "macros", "migrate", "runtime-tokio", "sqlite", "tls-rustls"] }
tiktoken-rs = "0.5"
tokio = "1.37"
uuid = "1.8"

View File

@@ -176,6 +176,12 @@ Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testi
## License
### Editions
- AFFiNE Community Edition (CE) is the current available version, it's free for self-host under the MIT license.
- AFFiNE Enterprise Edition (EE) is yet to be published, it will have more advanced features and enterprise-oriented offerings, including but not exclusive to rebranding and SSO, advanced admin and audit, etc., you may refer to https://affine.pro/pricing for more information
See [LICENSE] for details.
[all-contributors-badge]: https://img.shields.io/github/contributors/toeverything/AFFiNE

View File

@@ -56,26 +56,26 @@
"@affine/cli": "workspace:*",
"@commitlint/cli": "^19.2.1",
"@commitlint/config-conventional": "^19.1.0",
"@faker-js/faker": "^8.4.1",
"@faker-js/faker": "^9.0.0",
"@istanbuljs/schema": "^0.1.3",
"@magic-works/i18n-codegen": "^0.6.0",
"@nx/vite": "^19.5.3",
"@playwright/test": "=1.44.1",
"@playwright/test": "=1.46.1",
"@taplo/cli": "^0.7.0",
"@testing-library/react": "^16.0.0",
"@toeverything/infra": "workspace:*",
"@types/affine__env": "workspace:*",
"@types/eslint": "^8.56.7",
"@types/eslint": "^9.0.0",
"@types/node": "^20.12.7",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"@vanilla-extract/vite-plugin": "^4.0.7",
"@vanilla-extract/webpack-plugin": "^2.3.7",
"@vitejs/plugin-react-swc": "^3.6.0",
"@vitest/coverage-istanbul": "1.6.0",
"@vitest/ui": "1.6.0",
"@vitest/coverage-istanbul": "2.0.5",
"@vitest/ui": "2.0.5",
"cross-env": "^7.0.3",
"electron": "~30.2.0",
"electron": "^31.0.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import-x": "^0.5.0",
@@ -88,15 +88,15 @@
"eslint-plugin-unused-imports": "^3.1.0",
"eslint-plugin-vue": "^9.24.1",
"fake-indexeddb": "6.0.0",
"happy-dom": "^14.7.1",
"happy-dom": "^15.0.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"msw": "^2.3.0",
"nanoid": "^5.0.7",
"nx": "^19.0.0",
"nyc": "^17.0.0",
"oxlint": "0.7.0",
"prettier": "^3.2.5",
"oxlint": "0.9.2",
"prettier": "^3.3.3",
"semver": "^7.6.0",
"serve": "^14.2.1",
"string-width": "^7.1.0",
@@ -106,11 +106,11 @@
"vite": "^5.2.8",
"vite-plugin-istanbul": "^6.0.0",
"vite-plugin-static-copy": "^1.0.2",
"vitest": "1.6.0",
"vitest": "2.0.5",
"vitest-fetch-mock": "^0.3.0",
"vitest-mock-extended": "^2.0.0"
},
"packageManager": "yarn@4.3.1",
"packageManager": "yarn@4.4.1",
"resolutions": {
"array-buffer-byte-length": "npm:@nolyfill/array-buffer-byte-length@latest",
"array-includes": "npm:@nolyfill/array-includes@latest",

View File

@@ -33,7 +33,7 @@
"build:debug": "napi build"
},
"devDependencies": {
"@napi-rs/cli": "3.0.0-alpha.60",
"@napi-rs/cli": "3.0.0-alpha.62",
"lib0": "^0.2.93",
"nx": "^19.0.0",
"nx-cloud": "^19.0.0",

View File

@@ -1 +1,2 @@
.env
static/

View File

@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "ai_prompts_metadata" ADD COLUMN "modified" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "updated_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;

View File

@@ -0,0 +1,13 @@
-- CreateTable
CREATE TABLE "user_snapshots" (
"user_id" VARCHAR NOT NULL,
"id" VARCHAR NOT NULL,
"blob" BYTEA NOT NULL,
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "user_snapshots_pkey" PRIMARY KEY ("user_id","id")
);
-- AddForeignKey
ALTER TABLE "user_snapshots" ADD CONSTRAINT "user_snapshots_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,14 @@
/*
Warnings:
- The primary key for the `updates` table will be changed. If it partially fails, the table could be left without primary key constraint.
*/
-- AlterTable
ALTER TABLE "snapshots" ALTER COLUMN "seq" DROP NOT NULL;
-- AlterTable
ALTER TABLE "updates" DROP CONSTRAINT "updates_pkey",
ALTER COLUMN "created_at" DROP DEFAULT,
ALTER COLUMN "seq" DROP NOT NULL,
ADD CONSTRAINT "updates_pkey" PRIMARY KEY ("workspace_id", "guid", "created_at");

View File

@@ -0,0 +1,21 @@
-- AlterTable
ALTER TABLE "snapshot_histories" ADD COLUMN "created_by" VARCHAR;
-- AlterTable
ALTER TABLE "snapshots" ADD COLUMN "created_by" VARCHAR,
ADD COLUMN "updated_by" VARCHAR;
-- AlterTable
ALTER TABLE "updates" ADD COLUMN "created_by" VARCHAR;
-- AddForeignKey
ALTER TABLE "snapshots" ADD CONSTRAINT "snapshots_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "snapshots" ADD CONSTRAINT "snapshots_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "updates" ADD CONSTRAINT "updates_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "snapshot_histories" ADD CONSTRAINT "snapshot_histories_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@@ -21,11 +21,11 @@
"dependencies": {
"@apollo/server": "^4.10.2",
"@aws-sdk/client-s3": "^3.620.0",
"@fal-ai/serverless-client": "^0.13.0",
"@fal-ai/serverless-client": "^0.14.0",
"@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.19.0",
"@google-cloud/opentelemetry-cloud-trace-exporter": "^2.2.0",
"@google-cloud/opentelemetry-resource-util": "^2.2.0",
"@keyv/redis": "^2.8.4",
"@keyv/redis": "^3.0.0",
"@nestjs/apollo": "^12.1.0",
"@nestjs/common": "^10.3.7",
"@nestjs/core": "^10.3.7",
@@ -34,26 +34,25 @@
"@nestjs/platform-express": "^10.3.7",
"@nestjs/platform-socket.io": "^10.3.7",
"@nestjs/schedule": "^4.0.1",
"@nestjs/serve-static": "^4.0.2",
"@nestjs/throttler": "5.2.0",
"@nestjs/throttler": "6.2.1",
"@nestjs/websockets": "^10.3.7",
"@node-rs/argon2": "^1.8.0",
"@node-rs/crc32": "^1.10.0",
"@node-rs/jsonwebtoken": "^0.5.2",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/core": "^1.25.0",
"@opentelemetry/exporter-prometheus": "^0.52.0",
"@opentelemetry/exporter-prometheus": "^0.53.0",
"@opentelemetry/exporter-zipkin": "^1.25.0",
"@opentelemetry/host-metrics": "^0.35.2",
"@opentelemetry/instrumentation": "^0.52.0",
"@opentelemetry/instrumentation-graphql": "^0.42.0",
"@opentelemetry/instrumentation-http": "^0.52.0",
"@opentelemetry/instrumentation-ioredis": "^0.42.0",
"@opentelemetry/instrumentation-nestjs-core": "^0.39.0",
"@opentelemetry/instrumentation-socket.io": "^0.41.0",
"@opentelemetry/instrumentation": "^0.53.0",
"@opentelemetry/instrumentation-graphql": "^0.43.0",
"@opentelemetry/instrumentation-http": "^0.53.0",
"@opentelemetry/instrumentation-ioredis": "^0.43.0",
"@opentelemetry/instrumentation-nestjs-core": "^0.40.0",
"@opentelemetry/instrumentation-socket.io": "^0.42.0",
"@opentelemetry/resources": "^1.25.0",
"@opentelemetry/sdk-metrics": "^1.25.0",
"@opentelemetry/sdk-node": "^0.52.0",
"@opentelemetry/sdk-node": "^0.53.0",
"@opentelemetry/sdk-trace-node": "^1.25.0",
"@opentelemetry/semantic-conventions": "^1.25.0",
"@prisma/client": "^5.15.0",
@@ -71,13 +70,13 @@
"graphql-upload": "^16.0.2",
"html-validate": "^8.20.1",
"ioredis": "^5.3.2",
"keyv": "^4.5.4",
"keyv": "^5.0.0",
"lodash-es": "^4.17.21",
"mixpanel": "^0.18.0",
"mustache": "^4.2.0",
"nanoid": "^5.0.7",
"nest-commander": "^3.12.5",
"nestjs-throttler-storage-redis": "^0.4.1",
"nestjs-throttler-storage-redis": "^0.5.0",
"nodemailer": "^6.9.13",
"on-headers": "^1.0.2",
"openai": "^4.33.0",
@@ -138,6 +137,7 @@
],
"watchMode": {
"ignoreChanges": [
"static/**",
"**/*.gen.*"
]
},

View File

@@ -32,6 +32,11 @@ model User {
sessions UserSession[]
aiSessions AiSession[]
updatedRuntimeConfigs RuntimeConfig[]
userSnapshots UserSnapshot[]
createdSnapshot Snapshot[] @relation("createdSnapshot")
updatedSnapshot Snapshot[] @relation("updatedSnapshot")
createdUpdate Update[] @relation("createdUpdate")
createdHistory SnapshotHistory[] @relation("createdHistory")
@@index([email])
@@map("users")
@@ -57,12 +62,13 @@ model ConnectedAccount {
}
model Session {
id String @id @default(uuid()) @db.VarChar
expiresAt DateTime? @map("expires_at") @db.Timestamptz(3)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
id String @id @default(uuid()) @db.VarChar
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
userSessions UserSession[]
// @deprecated use [UserSession.expiresAt]
deprecated_expiresAt DateTime? @map("expires_at") @db.Timestamptz(3)
@@map("multiple_users_sessions")
}
@@ -235,25 +241,60 @@ model Snapshot {
workspaceId String @map("workspace_id") @db.VarChar
id String @default(uuid()) @map("guid") @db.VarChar
blob Bytes @db.ByteA
seq Int @default(0) @db.Integer
state Bytes? @db.ByteA
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
// the `updated_at` field will not record the time of record changed,
// but the created time of last seen update that has been merged into snapshot.
updatedAt DateTime @map("updated_at") @db.Timestamptz(3)
createdBy String? @map("created_by") @db.VarChar
updatedBy String? @map("updated_by") @db.VarChar
// should not delete origin snapshot even if user is deleted
// we only delete the snapshot if the workspace is deleted
createdByUser User? @relation(name: "createdSnapshot", fields: [createdBy], references: [id], onDelete: SetNull)
updatedByUser User? @relation(name: "updatedSnapshot", fields: [updatedBy], references: [id], onDelete: SetNull)
// @deprecated use updatedAt only
seq Int? @default(0) @db.Integer
// we need to clear all hanging updates and snapshots before enable the foreign key on workspaceId
// workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
@@id([id, workspaceId])
@@map("snapshots")
}
// user snapshots are special snapshots for user storage like personal app settings, distinguished from workspace snapshots
// basically they share the same structure with workspace snapshots
// but for convenience, we don't fork the updates queue and hisotry for user snapshots, until we have to
// which means all operation on user snapshot will happen in-pace
model UserSnapshot {
userId String @map("user_id") @db.VarChar
id String @map("id") @db.VarChar
blob Bytes @db.ByteA
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([userId, id])
@@map("user_snapshots")
}
model Update {
workspaceId String @map("workspace_id") @db.VarChar
id String @map("guid") @db.VarChar
seq Int @db.Integer
blob Bytes @db.ByteA
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
createdAt DateTime @map("created_at") @db.Timestamptz(3)
createdBy String? @map("created_by") @db.VarChar
@@id([workspaceId, id, seq])
// will delete createor record if createor's account is deleted
createdByUser User? @relation(name: "createdUpdate", fields: [createdBy], references: [id], onDelete: SetNull)
// @deprecated use createdAt only
seq Int? @db.Integer
@@id([workspaceId, id, createdAt])
@@map("updates")
}
@@ -264,6 +305,10 @@ model SnapshotHistory {
blob Bytes @db.ByteA
state Bytes? @db.ByteA
expiredAt DateTime @map("expired_at") @db.Timestamptz(3)
createdBy String? @map("created_by") @db.VarChar
// will delete createor record if creator's account is deleted
createdByUser User? @relation(name: "createdHistory", fields: [createdBy], references: [id], onDelete: SetNull)
@@id([workspaceId, id, timestamp])
@@map("snapshot_histories")
@@ -367,6 +412,9 @@ model AiPrompt {
model String @db.VarChar
config Json? @db.Json
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(3)
// whether the prompt is modified by the admin panel
modified Boolean @default(false)
messages AiPromptMessage[]
sessions AiSession[]

View File

@@ -3,7 +3,7 @@ import { Controller, Get } from '@nestjs/common';
import { Public } from './core/auth';
import { Config, SkipThrottle } from './fundamentals';
@Controller('/')
@Controller('/info')
export class AppController {
constructor(private readonly config: Config) {}
@@ -15,7 +15,7 @@ export class AppController {
compatibility: this.config.version,
message: `AFFiNE ${this.config.version} Server`,
type: this.config.type,
flavor: this.config.flavor,
flavor: this.config.flavor.type,
};
}
}

View File

@@ -1,5 +1,3 @@
import { join } from 'node:path';
import {
DynamicModule,
ForwardReference,
@@ -7,16 +5,16 @@ import {
Module,
} from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { ServeStaticModule } from '@nestjs/serve-static';
import { get } from 'lodash-es';
import { AppController } from './app.controller';
import { AuthModule } from './core/auth';
import { ADD_ENABLED_FEATURES, ServerConfigModule } from './core/config';
import { DocModule } from './core/doc';
import { DocStorageModule } from './core/doc';
import { FeatureModule } from './core/features';
import { PermissionModule } from './core/permission';
import { QuotaModule } from './core/quota';
import { CustomSetupModule } from './core/setup';
import { SelfhostModule } from './core/selfhost';
import { StorageModule } from './core/storage';
import { SyncModule } from './core/sync';
import { UserModule } from './core/user';
@@ -137,7 +135,7 @@ export class AppModuleBuilder {
compile() {
@Module({
imports: this.modules,
controllers: this.config.isSelfhosted ? [] : [AppController],
controllers: [AppController],
})
class AppModule {}
@@ -145,20 +143,20 @@ export class AppModuleBuilder {
}
}
function buildAppModule() {
export function buildAppModule() {
AFFiNE = mergeConfigOverride(AFFiNE);
const factor = new AppModuleBuilder(AFFiNE);
factor
// common fundamental modules
// basic
.use(...FunctionalityModules)
.useIf(config => config.flavor.sync, WebSocketModule)
// auth
.use(UserModule, AuthModule)
.use(UserModule, AuthModule, PermissionModule)
// business modules
.use(DocModule)
.use(DocStorageModule)
// sync server only
.useIf(config => config.flavor.sync, SyncModule)
@@ -166,27 +164,16 @@ function buildAppModule() {
// graphql server only
.useIf(
config => config.flavor.graphql,
ServerConfigModule,
GqlModule,
StorageModule,
ServerConfigModule,
WorkspaceModule,
FeatureModule,
QuotaModule
)
// self hosted server only
.useIf(
config => config.isSelfhosted,
CustomSetupModule,
ServeStaticModule.forRoot({
rootPath: join('/app', 'static'),
exclude: ['/admin*'],
}),
ServeStaticModule.forRoot({
rootPath: join('/app', 'static', 'admin'),
serveRoot: '/admin',
})
);
.useIf(config => config.isSelfhosted, SelfhostModule);
// plugin modules
ENABLED_PLUGINS.forEach(name => {

View File

@@ -25,6 +25,7 @@ AFFiNE.ENV_MAP = {
OAUTH_OIDC_CLAIM_MAP_EMAIL: 'plugins.oauth.providers.oidc.args.claim_email',
OAUTH_OIDC_CLAIM_MAP_NAME: 'plugins.oauth.providers.oidc.args.claim_name',
METRICS_CUSTOMER_IO_TOKEN: ['metrics.customerIo.token', 'string'],
CAPTCHA_TURNSTILE_SECRET: ['plugins.captcha.turnstile.secret', 'string'],
COPILOT_OPENAI_API_KEY: 'plugins.copilot.openai.apiKey',
COPILOT_FAL_API_KEY: 'plugins.copilot.fal.apiKey',
COPILOT_UNSPLASH_API_KEY: 'plugins.copilot.unsplashKey',

View File

@@ -71,6 +71,14 @@ AFFiNE.use('payment', {
});
AFFiNE.use('oauth');
/* Captcha Plugin Default Config */
AFFiNE.use('captcha', {
turnstile: {},
challenge: {
bits: 20,
},
});
if (AFFiNE.deploy) {
AFFiNE.mailer = {
service: 'gmail',

View File

@@ -95,6 +95,15 @@ AFFiNE.server.port = 3010;
// });
//
//
// /* Captcha Plugin Default Config */
// AFFiNE.plugins.use('captcha', {
// turnstile: {},
// challenge: {
// bits: 20,
// },
// });
//
//
// /* Cloudflare R2 Plugin */
// /* Enable if you choose to store workspace blobs or user avatars in Cloudflare R2 Storage Service */
// AFFiNE.use('cloudflare-r2', {

View File

@@ -1,5 +1,3 @@
import { randomUUID } from 'node:crypto';
import {
Body,
Controller,
@@ -18,26 +16,34 @@ import {
EarlyAccessRequired,
EmailTokenNotFound,
InternalServerError,
InvalidEmail,
InvalidEmailToken,
SignUpForbidden,
Throttle,
URLHelper,
UseNamedGuard,
} from '../../fundamentals';
import { UserService } from '../user';
import { validators } from '../utils/validators';
import { CurrentUser } from './current-user';
import { Public } from './guard';
import { AuthService, parseAuthUserSeqNum } from './service';
import { AuthService } from './service';
import { CurrentUser, Session } from './session';
import { TokenService, TokenType } from './token';
class SignInCredential {
email!: string;
password?: string;
interface PreflightResponse {
registered: boolean;
hasPassword: boolean;
}
class MagicLinkCredential {
email!: string;
token!: string;
interface SignInCredential {
email: string;
password?: string;
callbackUrl?: string;
}
interface MagicLinkCredential {
email: string;
token: string;
}
@Throttle('strict')
@@ -52,13 +58,44 @@ export class AuthController {
) {}
@Public()
@Post('/preflight')
async preflight(
@Body() params?: { email: string }
): Promise<PreflightResponse> {
if (!params?.email) {
throw new InvalidEmail();
}
validators.assertValidEmail(params.email);
const user = await this.user.findUserWithHashedPasswordByEmail(
params.email
);
if (!user) {
return {
registered: false,
hasPassword: false,
};
}
return {
registered: user.registered,
hasPassword: !!user.password,
};
}
@Public()
@UseNamedGuard('captcha')
@Post('/sign-in')
@Header('content-type', 'application/json')
async signIn(
@Req() req: Request,
@Res() res: Response,
@Body() credential: SignInCredential,
@Query('redirect_uri') redirectUri = this.url.home
/**
* @deprecated
*/
@Query('redirect_uri') redirectUri?: string
) {
validators.assertValidEmail(credential.email);
const canSignIn = await this.auth.canSignIn(credential.email);
@@ -67,80 +104,86 @@ export class AuthController {
}
if (credential.password) {
const user = await this.auth.signIn(
await this.passwordSignIn(
req,
res,
credential.email,
credential.password
);
await this.auth.setCookie(req, res, user);
res.status(HttpStatus.OK).send(user);
} else {
// send email magic link
const user = await this.user.findUserByEmail(credential.email);
if (!user) {
const allowSignup = await this.config.runtime.fetch('auth/allowSignup');
if (!allowSignup) {
throw new SignUpForbidden();
}
}
const result = await this.sendSignInEmail(
{ email: credential.email, signUp: !user },
await this.sendMagicLink(
req,
res,
credential.email,
credential.callbackUrl,
redirectUri
);
if (result.rejected.length) {
throw new InternalServerError('Failed to send sign-in email.');
}
res.status(HttpStatus.OK).send({
email: credential.email,
});
}
}
async sendSignInEmail(
{ email, signUp }: { email: string; signUp: boolean },
redirectUri: string
async passwordSignIn(
req: Request,
res: Response,
email: string,
password: string
) {
const user = await this.auth.signIn(email, password);
await this.auth.setCookies(req, res, user.id);
res.status(HttpStatus.OK).send(user);
}
async sendMagicLink(
_req: Request,
res: Response,
email: string,
callbackUrl = '/magic-link',
redirectUrl?: string
) {
// send email magic link
const user = await this.user.findUserByEmail(email);
if (!user) {
const allowSignup = await this.config.runtime.fetch('auth/allowSignup');
if (!allowSignup) {
throw new SignUpForbidden();
}
}
const token = await this.token.createToken(TokenType.SignIn, email);
const magicLink = this.url.link('/magic-link', {
const magicLink = this.url.link(callbackUrl, {
token,
email,
redirect_uri: redirectUri,
...(redirectUrl
? {
redirect_uri: redirectUrl,
}
: {}),
});
const result = await this.auth.sendSignInEmail(email, magicLink, signUp);
const result = await this.auth.sendSignInEmail(email, magicLink, !user);
return result;
if (result.rejected.length) {
throw new InternalServerError('Failed to send sign-in email.');
}
res.status(HttpStatus.OK).send({
email: email,
});
}
@Get('/sign-out')
async signOut(
@Req() req: Request,
@Res() res: Response,
@Query('redirect_uri') redirectUri?: string
@Session() session: Session,
@Body() { all }: { all: boolean }
) {
const session = await this.auth.signOut(
req.cookies[AuthService.sessionCookieName],
parseAuthUserSeqNum(req.headers[AuthService.authUserSeqHeaderName])
await this.auth.signOut(
session.sessionId,
all ? undefined : session.userId
);
if (session) {
res.cookie(AuthService.sessionCookieName, session.id, {
expires: session.expiresAt ?? void 0, // expiredAt is `string | null`
...this.auth.cookieOptions,
});
} else {
res.clearCookie(AuthService.sessionCookieName);
}
if (redirectUri) {
return this.url.safeRedirect(res, redirectUri);
} else {
return res.send(null);
}
res.status(HttpStatus.OK).send({});
}
@Public()
@@ -156,11 +199,11 @@ export class AuthController {
validators.assertValidEmail(email);
const valid = await this.token.verifyToken(TokenType.SignIn, token, {
const tokenRecord = await this.token.verifyToken(TokenType.SignIn, token, {
credential: email,
});
if (!valid) {
if (!tokenRecord) {
throw new InvalidEmailToken();
}
@@ -169,9 +212,8 @@ export class AuthController {
registered: true,
});
await this.auth.setCookie(req, res, user);
res.send({ id: user.id, email: user.email, name: user.name });
await this.auth.setCookies(req, res, user.id);
res.send({ id: user.id });
}
@Throttle('default', { limit: 1200 })
@@ -198,14 +240,4 @@ export class AuthController {
users: await this.auth.getUserList(token),
};
}
@Public()
@Get('/challenge')
async challenge() {
// TODO(@darksky): impl in following PR
return {
challenge: randomUUID(),
resource: randomUUID(),
};
}
}

View File

@@ -4,7 +4,7 @@ import type {
FactoryProvider,
OnModuleInit,
} from '@nestjs/common';
import { Injectable, SetMetadata, UseGuards } from '@nestjs/common';
import { Injectable, SetMetadata } from '@nestjs/common';
import { ModuleRef, Reflector } from '@nestjs/core';
import type { Request } from 'express';
@@ -16,16 +16,8 @@ import {
parseCookies,
} from '../../fundamentals';
import { WEBSOCKET_OPTIONS } from '../../fundamentals/websocket';
import { CurrentUser, UserSession } from './current-user';
import { AuthService, parseAuthUserSeqNum } from './service';
function extractTokenFromHeader(authorization: string) {
if (!/^Bearer\s/i.test(authorization)) {
return;
}
return authorization.substring(7);
}
import { AuthService } from './service';
import { Session } from './session';
const PUBLIC_ENTRYPOINT_SYMBOL = Symbol('public');
@@ -46,8 +38,8 @@ export class AuthGuard implements CanActivate, OnModuleInit {
const { req, res } = getRequestResponseFromContext(context);
const userSession = await this.signIn(req);
if (res && userSession && userSession.session.expiresAt) {
await this.auth.refreshUserSessionIfNeeded(req, res, userSession.session);
if (res && userSession && userSession.expiresAt) {
await this.auth.refreshUserSessionIfNeeded(res, userSession);
}
// api is public
@@ -60,43 +52,31 @@ export class AuthGuard implements CanActivate, OnModuleInit {
return true;
}
if (!req.user) {
if (!userSession) {
throw new AuthenticationRequired();
}
return true;
}
async signIn(
req: Request
): Promise<{ user: CurrentUser; session: UserSession } | null> {
if (req.user && req.session) {
return {
user: req.user,
session: req.session,
};
async signIn(req: Request): Promise<Session | null> {
if (req.session) {
return req.session;
}
// compatibility with websocket request
parseCookies(req);
let sessionToken: string | undefined =
req.cookies[AuthService.sessionCookieName];
if (!sessionToken && req.headers.authorization) {
sessionToken = extractTokenFromHeader(req.headers.authorization);
}
// TODO(@forehalo): a cache for user session
const userSession = await this.auth.getUserSessionFromRequest(req);
if (sessionToken) {
const userSeq = parseAuthUserSeqNum(
req.headers[AuthService.authUserSeqHeaderName]
);
if (userSession) {
req.session = {
...userSession.session,
user: userSession.user,
};
const userSession = await this.auth.getUserSession(sessionToken, userSeq);
if (userSession) {
req.session = userSession.session;
req.user = userSession.user;
}
return userSession;
return req.session;
}
return null;
@@ -104,26 +84,8 @@ export class AuthGuard implements CanActivate, OnModuleInit {
}
/**
* This guard is used to protect routes/queries/mutations that require a user to be logged in.
*
* The `@CurrentUser()` parameter decorator used in a `Auth` guarded queries would always give us the user because the `Auth` guard will
* fast throw if user is not logged in.
*
* @example
*
* ```typescript
* \@Auth()
* \@Query(() => UserType)
* user(@CurrentUser() user: CurrentUser) {
* return user;
* }
* ```
* Mark api to be public accessible
*/
export const Auth = () => {
return UseGuards(AuthGuard);
};
// api is public accessible
export const Public = () => SetMetadata(PUBLIC_ENTRYPOINT_SYMBOL, true);
export const AuthWebsocketOptionsProvider: FactoryProvider = {

View File

@@ -20,7 +20,7 @@ import { TokenService, TokenType } from './token';
AuthGuard,
AuthWebsocketOptionsProvider,
],
exports: [AuthService, AuthGuard, AuthWebsocketOptionsProvider],
exports: [AuthService, AuthGuard, AuthWebsocketOptionsProvider, TokenService],
controllers: [AuthController],
})
export class AuthModule {}
@@ -28,4 +28,4 @@ export class AuthModule {}
export * from './guard';
export { ClientTokenType } from './resolver';
export { AuthService, TokenService, TokenType };
export * from './current-user';
export * from './session';

View File

@@ -11,11 +11,11 @@ import {
import {
ActionForbidden,
Config,
EmailAlreadyUsed,
EmailTokenNotFound,
EmailVerificationRequired,
InvalidEmailToken,
LinkExpired,
SameEmailProvided,
SkipThrottle,
Throttle,
@@ -25,9 +25,9 @@ import { Admin } from '../common';
import { UserService } from '../user';
import { UserType } from '../user/types';
import { validators } from '../utils/validators';
import { CurrentUser } from './current-user';
import { Public } from './guard';
import { AuthService } from './service';
import { CurrentUser } from './session';
import { TokenService, TokenType } from './token';
@ObjectType('tokenType')
@@ -46,7 +46,6 @@ export class ClientTokenType {
@Resolver(() => UserType)
export class AuthResolver {
constructor(
private readonly config: Config,
private readonly url: URLHelper,
private readonly auth: AuthService,
private readonly user: UserService,
@@ -66,7 +65,7 @@ export class AuthResolver {
@ResolveField(() => ClientTokenType, {
name: 'token',
deprecationReason: 'use [/api/auth/authorize]',
deprecationReason: 'use [/api/auth/sign-in?native=true] instead',
})
async clientToken(
@CurrentUser() currentUser: CurrentUser,
@@ -76,39 +75,32 @@ export class AuthResolver {
throw new ActionForbidden();
}
const session = await this.auth.createUserSession(
user,
undefined,
this.config.auth.accessToken.ttl
);
const userSession = await this.auth.createUserSession(user.id);
return {
sessionToken: session.sessionId,
token: session.sessionId,
sessionToken: userSession.sessionId,
token: userSession.sessionId,
refresh: '',
};
}
@Mutation(() => UserType)
@Public()
@Mutation(() => Boolean)
async changePassword(
@CurrentUser() user: CurrentUser,
@Args('token') token: string,
@Args('newPassword') newPassword: string
@Args('newPassword') newPassword: string,
@Args('userId', { type: () => String, nullable: true }) userId?: string
) {
const config = await this.config.runtime.fetchAll({
'auth/password.max': true,
'auth/password.min': true,
});
validators.assertValidPassword(newPassword, {
min: config['auth/password.min'],
max: config['auth/password.max'],
});
if (!userId) {
throw new LinkExpired();
}
// NOTE: Set & Change password are using the same token type.
const valid = await this.token.verifyToken(
TokenType.ChangePassword,
token,
{
credential: user.id,
credential: userId,
}
);
@@ -116,10 +108,10 @@ export class AuthResolver {
throw new InvalidEmailToken();
}
await this.auth.changePassword(user.id, newPassword);
await this.auth.revokeUserSessions(user.id);
await this.auth.changePassword(userId, newPassword);
await this.auth.revokeUserSessions(userId);
return user;
return true;
}
@Mutation(() => UserType)
@@ -128,7 +120,6 @@ export class AuthResolver {
@Args('token') token: string,
@Args('email') email: string
) {
validators.assertValidEmail(email);
// @see [sendChangeEmail]
const valid = await this.token.verifyToken(TokenType.VerifyEmail, token, {
credential: user.id,
@@ -151,8 +142,11 @@ export class AuthResolver {
async sendChangePasswordEmail(
@CurrentUser() user: CurrentUser,
@Args('callbackUrl') callbackUrl: string,
// @deprecated
@Args('email', { nullable: true }) _email?: string
@Args('email', {
nullable: true,
deprecationReason: 'fetched from signed in user',
})
_email?: string
) {
if (!user.emailVerified) {
throw new EmailVerificationRequired();
@@ -163,7 +157,7 @@ export class AuthResolver {
user.id
);
const url = this.url.link(callbackUrl, { token });
const url = this.url.link(callbackUrl, { userId: user.id, token });
const res = await this.auth.sendChangePasswordEmail(user.email, url);
@@ -174,21 +168,13 @@ export class AuthResolver {
async sendSetPasswordEmail(
@CurrentUser() user: CurrentUser,
@Args('callbackUrl') callbackUrl: string,
@Args('email', { nullable: true }) _email?: string
@Args('email', {
nullable: true,
deprecationReason: 'fetched from signed in user',
})
_email?: string
) {
if (!user.emailVerified) {
throw new EmailVerificationRequired();
}
const token = await this.token.createToken(
TokenType.ChangePassword,
user.id
);
const url = this.url.link(callbackUrl, { token });
const res = await this.auth.sendSetPasswordEmail(user.email, url);
return !res.rejected.length;
return this.sendChangePasswordEmail(user, callbackUrl);
}
// The change email step is:
@@ -305,6 +291,7 @@ export class AuthResolver {
TokenType.ChangePassword,
userId
);
return this.url.link(callbackUrl, { token });
return this.url.link(callbackUrl, { userId, token });
}
}

View File

@@ -5,35 +5,12 @@ import { PrismaClient } from '@prisma/client';
import type { CookieOptions, Request, Response } from 'express';
import { assign, pick } from 'lodash-es';
import { Config, EmailAlreadyUsed, MailService } from '../../fundamentals';
import { Config, MailService, SignUpForbidden } from '../../fundamentals';
import { FeatureManagementService } from '../features/management';
import { QuotaService } from '../quota/service';
import { QuotaType } from '../quota/types';
import { UserService } from '../user/service';
import type { CurrentUser } from './current-user';
export function parseAuthUserSeqNum(value: any) {
let seq: number = 0;
switch (typeof value) {
case 'number': {
seq = value;
break;
}
case 'string': {
const result = value.match(/^([\d{0, 10}])$/);
if (result?.[1]) {
seq = Number(result[1]);
}
break;
}
default: {
seq = 0;
}
}
return Math.max(0, seq);
}
import type { CurrentUser } from './session';
export function sessionUser(
user: Pick<
@@ -48,6 +25,14 @@ export function sessionUser(
});
}
function extractTokenFromHeader(authorization: string) {
if (!/^Bearer\s/i.test(authorization)) {
return;
}
return authorization.substring(7);
}
@Injectable()
export class AuthService implements OnApplicationBootstrap {
readonly cookieOptions: CookieOptions = {
@@ -57,7 +42,7 @@ export class AuthService implements OnApplicationBootstrap {
secure: this.config.server.https,
};
static readonly sessionCookieName = 'affine_session';
static readonly authUserSeqHeaderName = 'x-auth-user';
static readonly userCookieName = 'affine_user_id';
constructor(
private readonly config: Config,
@@ -83,7 +68,7 @@ export class AuthService implements OnApplicationBootstrap {
await this.quota.switchUserQuota(devUser.id, QuotaType.ProPlanV1);
await this.feature.addAdmin(devUser.id);
await this.feature.addCopilot(devUser.id);
} catch (e) {
} catch {
// ignore
}
}
@@ -93,46 +78,69 @@ export class AuthService implements OnApplicationBootstrap {
return this.feature.canEarlyAccess(email);
}
async signUp(
name: string,
email: string,
password: string
): Promise<CurrentUser> {
const user = await this.user.findUserByEmail(email);
if (user) {
throw new EmailAlreadyUsed();
/**
* This is a test only helper to quickly signup a user, do not use in production
*/
async signUp(email: string, password: string): Promise<CurrentUser> {
if (!this.config.node.test) {
throw new SignUpForbidden(
'sign up helper is forbidden for non-test environment'
);
}
return this.user
.createUser({
name,
.createUser_without_verification({
email,
password,
})
.then(sessionUser);
}
async signIn(email: string, password: string) {
const user = await this.user.signIn(email, password);
async signIn(email: string, password: string): Promise<CurrentUser> {
return this.user.signIn(email, password).then(sessionUser);
}
return sessionUser(user);
async signOut(sessionId: string, userId?: string) {
// sign out all users in the session
if (!userId) {
await this.db.session.deleteMany({
where: {
id: sessionId,
},
});
} else {
await this.db.userSession.deleteMany({
where: {
sessionId,
userId,
},
});
}
}
async getUserSession(
token: string,
seq = 0
sessionId: string,
userId?: string
): Promise<{ user: CurrentUser; session: UserSession } | null> {
const session = await this.getSession(token);
const userSession = await this.db.userSession.findFirst({
where: {
sessionId,
userId,
},
select: {
id: true,
sessionId: true,
userId: true,
createdAt: true,
expiresAt: true,
user: true,
},
orderBy: {
createdAt: 'asc',
},
});
// no such session
if (!session) {
return null;
}
const userSession = session.userSessions.at(seq);
// no such user session
if (!userSession) {
return null;
}
@@ -142,112 +150,93 @@ export class AuthService implements OnApplicationBootstrap {
return null;
}
const user = await this.db.user.findUnique({
where: { id: userSession.userId },
});
if (!user) {
return null;
}
return { user: sessionUser(user), session: userSession };
return { user: sessionUser(userSession.user), session: userSession };
}
async getUserList(token: string) {
const session = await this.getSession(token);
if (!session || !session.userSessions.length) {
return [];
}
const users = await this.db.user.findMany({
where: {
id: {
in: session.userSessions.map(({ userId }) => userId),
},
},
});
// TODO(@forehalo): need to separate expired session, same for [getUser]
// Session
// | { user: LimitedUser { email, avatarUrl }, expired: true }
// | { user: User, expired: false }
return session.userSessions
.map(userSession => {
// keep users in the same order as userSessions
const user = users.find(({ id }) => id === userSession.userId);
if (!user) {
return null;
}
return sessionUser(user);
})
.filter(Boolean) as CurrentUser[];
}
async signOut(token: string, seq = 0) {
const session = await this.getSession(token);
if (session) {
// overflow the logged in user
if (session.userSessions.length <= seq) {
return session;
}
await this.db.userSession.deleteMany({
where: { id: session.userSessions[seq].id },
});
// no more user session active, delete the whole session
if (session.userSessions.length === 1) {
await this.db.session.delete({ where: { id: session.id } });
return null;
}
return session;
}
return null;
}
async getSession(token: string) {
if (!token) {
return null;
}
return this.db.$transaction(async tx => {
const session = await tx.session.findUnique({
async createUserSession(
userId: string,
sessionId?: string,
ttl = this.config.auth.session.ttl
) {
// check whether given session is valid
if (sessionId) {
const session = await this.db.session.findFirst({
where: {
id: token,
},
include: {
userSessions: {
orderBy: {
createdAt: 'asc',
},
},
id: sessionId,
},
});
if (!session) {
return null;
sessionId = undefined;
}
}
if (session.expiresAt && session.expiresAt <= new Date()) {
await tx.session.delete({
where: {
id: session.id,
if (!sessionId) {
const session = await this.createSession();
sessionId = session.id;
}
const expiresAt = new Date(Date.now() + ttl * 1000);
return this.db.userSession.upsert({
where: {
sessionId_userId: {
sessionId,
userId,
},
},
update: {
expiresAt,
},
create: {
sessionId,
userId,
expiresAt,
},
});
}
async getUserList(sessionId: string) {
const sessions = await this.db.userSession.findMany({
where: {
sessionId,
OR: [
{
expiresAt: null,
},
});
{
expiresAt: {
gt: new Date(),
},
},
],
},
include: {
user: true,
},
orderBy: {
createdAt: 'asc',
},
});
return null;
}
return sessions.map(({ user }) => sessionUser(user));
}
return session;
async createSession() {
return this.db.session.create({
data: {},
});
}
async getSession(sessionId: string) {
return this.db.session.findFirst({
where: {
id: sessionId,
},
});
}
async refreshUserSessionIfNeeded(
_req: Request,
res: Response,
session: UserSession,
ttr = this.config.auth.session.ttr
@@ -281,70 +270,63 @@ export class AuthService implements OnApplicationBootstrap {
return true;
}
async createUserSession(
user: { id: string },
existingSession?: string,
ttl = this.config.auth.session.ttl
) {
const session = existingSession
? await this.getSession(existingSession)
: null;
const expiresAt = new Date(Date.now() + ttl * 1000);
if (session) {
return this.db.userSession.upsert({
where: {
sessionId_userId: {
sessionId: session.id,
userId: user.id,
},
},
update: {
expiresAt,
},
create: {
sessionId: session.id,
userId: user.id,
expiresAt,
},
});
} else {
return this.db.userSession.create({
data: {
expiresAt,
session: {
create: {},
},
user: {
connect: {
id: user.id,
},
},
},
});
}
}
async revokeUserSessions(userId: string, sessionId?: string) {
async revokeUserSessions(userId: string) {
return this.db.userSession.deleteMany({
where: {
userId,
sessionId,
},
});
}
async setCookie(_req: Request, res: Response, user: { id: string }) {
const session = await this.createUserSession(
user
// TODO(@forehalo): enable multi user session
// req.cookies[AuthService.sessionCookieName]
);
getSessionOptionsFromRequest(req: Request) {
let sessionId: string | undefined =
req.cookies[AuthService.sessionCookieName];
res.cookie(AuthService.sessionCookieName, session.sessionId, {
expires: session.expiresAt ?? void 0,
if (!sessionId && req.headers.authorization) {
sessionId = extractTokenFromHeader(req.headers.authorization);
}
const userId: string | undefined =
req.cookies[AuthService.userCookieName] ||
req.headers[AuthService.userCookieName];
return {
sessionId,
userId,
};
}
async setCookies(req: Request, res: Response, userId: string) {
const { sessionId } = this.getSessionOptionsFromRequest(req);
const userSession = await this.createUserSession(userId, sessionId);
res.cookie(AuthService.sessionCookieName, userSession.sessionId, {
...this.cookieOptions,
expires: userSession.expiresAt ?? void 0,
});
this.setUserCookie(res, userId);
}
setUserCookie(res: Response, userId: string) {
res.cookie(AuthService.userCookieName, userId, {
...this.cookieOptions,
// user cookie is client readable & writable for fast user switch if there are multiple users in one session
// it safe to be non-secure & non-httpOnly because server will validate it by `cookie[AuthService.sessionCookieName]`
httpOnly: false,
secure: false,
});
}
async getUserSessionFromRequest(req: Request) {
const { sessionId, userId } = this.getSessionOptionsFromRequest(req);
if (!sessionId) {
return null;
}
return this.getUserSession(sessionId, userId);
}
async changePassword(
@@ -393,24 +375,16 @@ export class AuthService implements OnApplicationBootstrap {
async sendSignInEmail(email: string, link: string, signUp: boolean) {
return signUp
? await this.mailer.sendSignUpMail(link.toString(), {
? await this.mailer.sendSignUpMail(link, {
to: email,
})
: await this.mailer.sendSignInMail(link.toString(), {
: await this.mailer.sendSignInMail(link, {
to: email,
});
}
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)
async cleanExpiredSessions() {
await this.db.session.deleteMany({
where: {
expiresAt: {
lte: new Date(),
},
},
});
await this.db.userSession.deleteMany({
where: {
expiresAt: {

View File

@@ -4,10 +4,6 @@ import { User, UserSession } from '@prisma/client';
import { getRequestResponseFromContext } from '../../fundamentals';
function getUserFromContext(context: ExecutionContext) {
return getRequestResponseFromContext(context).req.user;
}
/**
* Used to fetch current user from the request context.
*
@@ -44,7 +40,7 @@ function getUserFromContext(context: ExecutionContext) {
// eslint-disable-next-line no-redeclare
export const CurrentUser = createParamDecorator(
(_: unknown, context: ExecutionContext) => {
return getUserFromContext(context);
return getRequestResponseFromContext(context).req.session?.user;
}
);
@@ -54,4 +50,14 @@ export interface CurrentUser
emailVerified: boolean;
}
export { type UserSession };
// interface and variable don't conflict
// eslint-disable-next-line no-redeclare
export const Session = createParamDecorator(
(_: unknown, context: ExecutionContext) => {
return getRequestResponseFromContext(context).req.session;
}
);
export type Session = UserSession & {
user: CurrentUser;
};

View File

@@ -69,13 +69,9 @@ export class TokenService {
const valid =
!expired && (!record.credential || record.credential === credential);
if ((expired || valid) && !keep) {
const deleted = await this.db.verificationToken.deleteMany({
where: {
token,
type,
},
});
// always revoke expired token
if (expired || (valid && !keep)) {
const deleted = await this.revokeToken(type, token);
// already deleted, means token has been used
if (!deleted.count) {
@@ -86,6 +82,15 @@ export class TokenService {
return valid ? record : null;
}
async revokeToken(type: TokenType, token: string) {
return await this.db.verificationToken.deleteMany({
where: {
token,
type,
},
});
}
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)
async cleanExpiredTokens() {
await this.db.verificationToken.deleteMany({

View File

@@ -25,8 +25,8 @@ export class AdminGuard implements CanActivate, OnModuleInit {
async canActivate(context: ExecutionContext) {
const { req } = getRequestResponseFromContext(context);
let allow = false;
if (req.user) {
allow = await this.feature.isAdmin(req.user.id);
if (req.session) {
allow = await this.feature.isAdmin(req.session.user.id);
}
if (!allow) {

View File

@@ -4,17 +4,23 @@ import { Module } from '@nestjs/common';
import {
ServerConfigResolver,
ServerFeatureConfigResolver,
ServerRuntimeConfigResolver,
ServerServiceConfigResolver,
} from './resolver';
import { ServerService } from './service';
@Module({
providers: [
ServerService,
ServerConfigResolver,
ServerFeatureConfigResolver,
ServerRuntimeConfigResolver,
ServerServiceConfigResolver,
],
exports: [ServerService],
})
export class ServerConfigModule {}
export { ServerService };
export { ADD_ENABLED_FEATURES } from './server-feature';
export { ServerFeature } from './types';

View File

@@ -9,7 +9,7 @@ import {
ResolveField,
Resolver,
} from '@nestjs/graphql';
import { PrismaClient, RuntimeConfig, RuntimeConfigType } from '@prisma/client';
import { RuntimeConfig, RuntimeConfigType } from '@prisma/client';
import { GraphQLJSON, GraphQLJSONObject } from 'graphql-scalars';
import { Config, URLHelper } from '../../fundamentals';
@@ -19,6 +19,7 @@ import { FeatureType } from '../features';
import { AvailableUserFeatureConfig } from '../features/resolver';
import { ServerFlags } from './config';
import { ENABLED_FEATURES } from './server-feature';
import { ServerService } from './service';
import { ServerConfigType } from './types';
@ObjectType()
@@ -76,7 +77,7 @@ export class ServerConfigResolver {
constructor(
private readonly config: Config,
private readonly url: URLHelper,
private readonly db: PrismaClient
private readonly server: ServerService
) {}
@Public()
@@ -131,7 +132,7 @@ export class ServerConfigResolver {
description: 'whether server has been initialized',
})
async initialized() {
return (await this.db.user.count()) > 0;
return this.server.initialized();
}
}

View File

@@ -0,0 +1,17 @@
import { Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class ServerService {
private _initialized: boolean | null = null;
constructor(private readonly db: PrismaClient) {}
async initialized() {
if (!this._initialized) {
const userCount = await this.db.user.count();
this._initialized = userCount > 0;
}
return this._initialized;
}
}

View File

@@ -3,6 +3,7 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
import { DeploymentType } from '../../fundamentals';
export enum ServerFeature {
Captcha = 'captcha',
Copilot = 'copilot',
Payment = 'payment',
OAuth = 'oauth',

View File

@@ -0,0 +1,186 @@
import { Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { Mutex } from '../../../fundamentals';
import { DocStorageOptions } from '../options';
import { DocRecord, DocStorageAdapter } from '../storage';
@Injectable()
export class PgUserspaceDocStorageAdapter extends DocStorageAdapter {
constructor(
private readonly db: PrismaClient,
private readonly mutex: Mutex,
options: DocStorageOptions
) {
super(options);
}
// no updates queue for userspace, directly merge them inplace
// no history record for userspace
protected async getDocUpdates() {
return [];
}
protected async markUpdatesMerged() {
return 0;
}
async listDocHistories() {
return [];
}
async getDocHistory() {
return null;
}
protected async createDocHistory() {
return false;
}
override async rollbackDoc() {
return;
}
override async getDoc(spaceId: string, docId: string) {
return this.getDocSnapshot(spaceId, docId);
}
async pushDocUpdates(
userId: string,
docId: string,
updates: Uint8Array[],
editorId?: string
) {
if (!updates.length) {
return 0;
}
await using _lock = await this.lockDocForUpdate(userId, docId);
const snapshot = await this.getDocSnapshot(userId, docId);
const now = Date.now();
const pendings = updates.map((update, i) => ({
bin: update,
timestamp: now + i,
}));
const { timestamp, bin } = await this.squash(
snapshot ? [snapshot, ...pendings] : pendings
);
await this.setDocSnapshot({
spaceId: userId,
docId,
bin,
timestamp,
editor: editorId,
});
return timestamp;
}
async deleteDoc(userId: string, docId: string) {
await this.db.userSnapshot.deleteMany({
where: {
userId,
id: docId,
},
});
}
async deleteSpace(userId: string) {
await this.db.userSnapshot.deleteMany({
where: {
userId,
},
});
}
async getSpaceDocTimestamps(userId: string, after?: number) {
const snapshots = await this.db.userSnapshot.findMany({
select: {
id: true,
updatedAt: true,
},
where: {
userId,
...(after
? {
updatedAt: {
gt: new Date(after),
},
}
: {}),
},
});
const result: Record<string, number> = {};
snapshots.forEach(s => {
result[s.id] = s.updatedAt.getTime();
});
return result;
}
protected async getDocSnapshot(userId: string, docId: string) {
const snapshot = await this.db.userSnapshot.findUnique({
where: {
userId_id: {
userId,
id: docId,
},
},
});
if (!snapshot) {
return null;
}
return {
spaceId: userId,
docId,
bin: snapshot.blob,
timestamp: snapshot.updatedAt.getTime(),
editor: snapshot.userId,
};
}
protected async setDocSnapshot(snapshot: DocRecord) {
// we always get lock before writing to user snapshot table,
// so a simple upsert without testing on updatedAt is safe
await this.db.userSnapshot.upsert({
where: {
userId_id: {
userId: snapshot.spaceId,
id: snapshot.docId,
},
},
update: {
blob: Buffer.from(snapshot.bin),
updatedAt: new Date(snapshot.timestamp),
},
create: {
userId: snapshot.spaceId,
id: snapshot.docId,
blob: Buffer.from(snapshot.bin),
createdAt: new Date(snapshot.timestamp),
updatedAt: new Date(snapshot.timestamp),
},
});
return true;
}
protected override async lockDocForUpdate(
workspaceId: string,
docId: string
) {
const lock = await this.mutex.lock(`userspace:${workspaceId}:${docId}`);
if (!lock) {
throw new Error('Too many concurrent writings');
}
return lock;
}
}

View File

@@ -0,0 +1,618 @@
import { Injectable, Logger } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { chunk } from 'lodash-es';
import {
Cache,
DocHistoryNotFound,
DocNotFound,
FailedToSaveUpdates,
FailedToUpsertSnapshot,
metrics,
Mutex,
} from '../../../fundamentals';
import { retryable } from '../../../fundamentals/utils/promise';
import { DocStorageOptions } from '../options';
import {
DocRecord,
DocStorageAdapter,
DocUpdate,
HistoryFilter,
} from '../storage';
const UPDATES_QUEUE_CACHE_KEY = 'doc:manager:updates';
@Injectable()
export class PgWorkspaceDocStorageAdapter extends DocStorageAdapter {
private readonly logger = new Logger(PgWorkspaceDocStorageAdapter.name);
constructor(
private readonly db: PrismaClient,
private readonly mutex: Mutex,
private readonly cache: Cache,
protected override readonly options: DocStorageOptions
) {
super(options);
}
async pushDocUpdates(
workspaceId: string,
docId: string,
updates: Uint8Array[],
editorId?: string
) {
if (!updates.length) {
return 0;
}
let pendings = updates;
let done = 0;
let timestamp = Date.now();
try {
await retryable(async () => {
if (done !== 0) {
pendings = pendings.slice(done);
}
// TODO(@forehalo): remove in next release
const lastSeq = await this.getUpdateSeq(
workspaceId,
docId,
updates.length
);
let turn = 0;
const batchCount = 10;
for (const batch of chunk(pendings, batchCount)) {
const now = Date.now();
await this.db.update.createMany({
data: batch.map((update, i) => {
const subSeq = turn * batchCount + i + 1;
// `seq` is the last seq num of the batch
// example for 11 batched updates, start from seq num 20
// seq for first update in the batch should be:
// 31 - 11 + subSeq(0 * 10 + 0 + 1) = 21
// ^ last seq num ^ updates.length ^ turn ^ batchCount ^i
const seq = lastSeq - updates.length + subSeq;
const createdAt = now + subSeq;
timestamp = Math.max(timestamp, createdAt);
return {
workspaceId,
id: docId,
blob: Buffer.from(update),
seq,
createdAt: new Date(createdAt),
createdBy: editorId || null,
};
}),
});
turn++;
done += batch.length;
await this.updateCachedUpdatesCount(workspaceId, docId, batch.length);
}
});
} catch (e) {
this.logger.error('Failed to insert doc updates', e);
metrics.doc.counter('doc_update_insert_failed').add(1);
throw new FailedToSaveUpdates();
}
return timestamp;
}
protected async getDocUpdates(workspaceId: string, docId: string) {
const rows = await this.db.update.findMany({
where: {
workspaceId,
id: docId,
},
orderBy: {
createdAt: 'asc',
},
});
return rows.map(row => ({
bin: row.blob,
timestamp: row.createdAt.getTime(),
editor: row.createdBy || undefined,
}));
}
async deleteDoc(workspaceId: string, docId: string) {
const ident = { where: { workspaceId, id: docId } };
await this.db.$transaction([
this.db.snapshot.deleteMany(ident),
this.db.update.deleteMany(ident),
this.db.snapshotHistory.deleteMany(ident),
]);
}
async deleteSpace(workspaceId: string) {
const ident = { where: { workspaceId } };
await this.db.$transaction([
this.db.workspace.deleteMany({
where: {
id: workspaceId,
},
}),
this.db.snapshot.deleteMany(ident),
this.db.update.deleteMany(ident),
this.db.snapshotHistory.deleteMany(ident),
]);
}
async getSpaceDocTimestamps(workspaceId: string, after?: number) {
const snapshots = await this.db.snapshot.findMany({
select: {
id: true,
updatedAt: true,
},
where: {
workspaceId,
...(after
? {
updatedAt: {
gt: new Date(after),
},
}
: {}),
},
});
const updates = await this.db.update.groupBy({
where: {
workspaceId,
...(after
? {
createdAt: {
gt: new Date(after),
},
}
: {}),
},
by: ['id'],
_max: {
createdAt: true,
},
});
const result: Record<string, number> = {};
snapshots.forEach(s => {
result[s.id] = s.updatedAt.getTime();
});
updates.forEach(u => {
if (u._max.createdAt) {
result[u.id] = u._max.createdAt.getTime();
}
});
return result;
}
protected async markUpdatesMerged(
workspaceId: string,
docId: string,
updates: DocUpdate[]
) {
const result = await this.db.update.deleteMany({
where: {
workspaceId,
id: docId,
createdAt: {
in: updates.map(u => new Date(u.timestamp)),
},
},
});
await this.updateCachedUpdatesCount(workspaceId, docId, -result.count);
return result.count;
}
async listDocHistories(
workspaceId: string,
docId: string,
query: HistoryFilter
) {
const histories = await this.db.snapshotHistory.findMany({
select: {
timestamp: true,
createdByUser: {
select: {
name: true,
avatarUrl: true,
},
},
},
where: {
workspaceId,
id: docId,
timestamp: {
lt: query.before ? new Date(query.before) : new Date(),
},
},
orderBy: {
timestamp: 'desc',
},
take: query.limit,
});
return histories.map(h => ({
timestamp: h.timestamp.getTime(),
editor: h.createdByUser,
}));
}
async getDocHistory(workspaceId: string, docId: string, timestamp: number) {
const history = await this.db.snapshotHistory.findUnique({
where: {
workspaceId_id_timestamp: {
workspaceId,
id: docId,
timestamp: new Date(timestamp),
},
},
});
if (!history) {
return null;
}
return {
spaceId: workspaceId,
docId,
bin: history.blob,
timestamp,
editor: history.createdBy || undefined,
};
}
override async rollbackDoc(
spaceId: string,
docId: string,
timestamp: number,
editorId?: string
): Promise<void> {
await using _lock = await this.lockDocForUpdate(spaceId, docId);
const toSnapshot = await this.getDocHistory(spaceId, docId, timestamp);
if (!toSnapshot) {
throw new DocHistoryNotFound({ spaceId, docId, timestamp });
}
const fromSnapshot = await this.getDocSnapshot(spaceId, docId);
if (!fromSnapshot) {
throw new DocNotFound({ spaceId, docId });
}
// force create a new history record after rollback
await this.createDocHistory(
{
...fromSnapshot,
// override the editor to the one who requested the rollback
editor: editorId,
},
true
);
// WARN:
// we should never do the snapshot updating in recovering,
// which is not the solution in CRDT.
// let user revert in client and update the data in sync system
// const change = this.generateChangeUpdate(fromSnapshot.bin, toSnapshot.bin);
// await this.pushDocUpdates(spaceId, docId, [change]);
metrics.doc
.counter('history_recovered_counter', {
description: 'How many times history recovered request happened',
})
.add(1);
}
protected async createDocHistory(snapshot: DocRecord, force = false) {
const last = await this.lastDocHistory(snapshot.spaceId, snapshot.docId);
let shouldCreateHistory = false;
if (!last) {
// never created
shouldCreateHistory = true;
} else {
const lastHistoryTimestamp = last.timestamp.getTime();
if (lastHistoryTimestamp === snapshot.timestamp) {
// no change
shouldCreateHistory = false;
} else if (
// force
force ||
// last history created before interval in configs
lastHistoryTimestamp <
snapshot.timestamp - this.options.historyMinInterval(snapshot.spaceId)
) {
shouldCreateHistory = true;
}
}
if (shouldCreateHistory) {
if (this.isEmptyBin(snapshot.bin)) {
this.logger.debug(
`Doc is empty, skip creating history record for ${snapshot.docId} in workspace ${snapshot.spaceId}`
);
return false;
}
await this.db.snapshotHistory
.create({
select: {
timestamp: true,
},
data: {
workspaceId: snapshot.spaceId,
id: snapshot.docId,
timestamp: new Date(snapshot.timestamp),
blob: Buffer.from(snapshot.bin),
createdBy: snapshot.editor,
expiredAt: new Date(
Date.now() + (await this.options.historyMaxAge(snapshot.spaceId))
),
},
})
.catch(() => {
// safe to ignore
// only happens when duplicated history record created in multi processes
});
metrics.doc
.counter('history_created_counter', {
description: 'How many times the snapshot history created',
})
.add(1);
this.logger.debug(
`History created for ${snapshot.docId} in workspace ${snapshot.spaceId}.`
);
return true;
}
return false;
}
protected async getDocSnapshot(workspaceId: string, docId: string) {
const snapshot = await this.db.snapshot.findUnique({
where: {
id_workspaceId: {
workspaceId,
id: docId,
},
},
});
if (!snapshot) {
return null;
}
return {
spaceId: workspaceId,
docId,
bin: snapshot.blob,
timestamp: snapshot.updatedAt.getTime(),
// creator and editor may null if their account is deleted
editor: snapshot.updatedBy || snapshot.createdBy || undefined,
};
}
protected async setDocSnapshot(snapshot: DocRecord) {
const { spaceId, docId, bin, timestamp } = snapshot;
if (this.isEmptyBin(bin)) {
return false;
}
const updatedAt = new Date(timestamp);
// CONCERNS:
// i. Because we save the real user's last seen action time as `updatedAt`,
// it's possible to simply compare the `updatedAt` to determine if the snapshot is older than the one we are going to save.
//
// ii. Prisma doesn't support `upsert` with additional `where` condition along side unique constraint.
// In our case, we need to manually check the `updatedAt` to avoid overriding the newer snapshot.
// where: { id_workspaceId: {}, updatedAt: { lt: updatedAt } }
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
try {
const result: { updatedAt: Date }[] = await this.db.$queryRaw`
INSERT INTO "snapshots" ("workspace_id", "guid", "blob", "created_at", "updated_at", "created_by", "updated_by")
VALUES (${spaceId}, ${docId}, ${bin}, DEFAULT, ${updatedAt}, ${snapshot.editor}, ${snapshot.editor})
ON CONFLICT ("workspace_id", "guid")
DO UPDATE SET "blob" = ${bin}, "updated_at" = ${updatedAt}, "updated_by" = ${snapshot.editor}
WHERE "snapshots"."workspace_id" = ${spaceId} AND "snapshots"."guid" = ${docId} AND "snapshots"."updated_at" <= ${updatedAt}
RETURNING "snapshots"."workspace_id" as "workspaceId", "snapshots"."guid" as "id", "snapshots"."updated_at" as "updatedAt"
`;
// const result = await this.db.snapshot.upsert({
// select: {
// updatedAt: true,
// seq: true,
// },
// where: {
// id_workspaceId: {
// workspaceId,
// id: guid,
// },
// ⬇️ NOT SUPPORTED BY PRISMA YET
// updatedAt: {
// lt: updatedAt,
// },
// },
// update: {
// blob,
// state,
// updatedAt,
// },
// create: {
// workspaceId,
// id: guid,
// blob,
// state,
// updatedAt,
// seq,
// },
// });
// if the condition `snapshot.updatedAt > updatedAt` is true, by which means the snapshot has already been updated by other process,
// the updates has been applied to current `doc` must have been seen by the other process as well.
// The `updatedSnapshot` will be `undefined` in this case.
const updatedSnapshot = result.at(0);
return !!updatedSnapshot;
} catch (e) {
metrics.doc.counter('snapshot_upsert_failed').add(1);
this.logger.error('Failed to upsert snapshot', e);
throw new FailedToUpsertSnapshot();
}
}
protected override async lockDocForUpdate(
workspaceId: string,
docId: string
) {
const lock = await this.mutex.lock(`doc:update:${workspaceId}:${docId}`);
if (!lock) {
throw new Error('Too many concurrent writings');
}
return lock;
}
protected async lastDocHistory(workspaceId: string, id: string) {
return this.db.snapshotHistory.findFirst({
where: {
workspaceId,
id,
},
select: {
timestamp: true,
state: true,
},
orderBy: {
timestamp: 'desc',
},
});
}
// for auto merging
async randomDoc() {
const key = await this.cache.mapRandomKey(UPDATES_QUEUE_CACHE_KEY);
if (key) {
const cachedCount = await this.cache.mapIncrease(
UPDATES_QUEUE_CACHE_KEY,
key,
0
);
if (cachedCount > 0) {
const [workspaceId, id] = key.split('::');
const count = await this.db.update.count({
where: {
workspaceId,
id,
},
});
// FIXME(@forehalo): somehow the update count in cache is not accurate
if (count === 0) {
metrics.doc
.counter('doc_update_count_inconsistent_with_cache')
.add(1);
await this.cache.mapDelete(UPDATES_QUEUE_CACHE_KEY, key);
return null;
}
return { workspaceId, docId: id };
}
}
return null;
}
private async updateCachedUpdatesCount(
workspaceId: string,
guid: string,
count: number
) {
const result = await this.cache.mapIncrease(
UPDATES_QUEUE_CACHE_KEY,
`${workspaceId}::${guid}`,
count
);
if (result <= 0) {
await this.cache.mapDelete(
UPDATES_QUEUE_CACHE_KEY,
`${workspaceId}::${guid}`
);
}
}
/**
* @deprecated
*/
private readonly seqMap = new Map<string, number>();
/**
*
* @deprecated updates do not rely on seq number anymore
*
* keep in next release to avoid downtime when upgrading instances
*/
private async getUpdateSeq(workspaceId: string, guid: string, batch = 1) {
const MAX_SEQ_NUM = 0x3fffffff; // u31
try {
const { seq } = await this.db.snapshot.update({
select: {
seq: true,
},
where: {
id_workspaceId: {
workspaceId,
id: guid,
},
},
data: {
seq: {
increment: batch,
},
},
});
if (!seq) {
return batch;
}
// reset
if (seq >= MAX_SEQ_NUM) {
await this.db.snapshot.update({
select: {
seq: true,
},
where: {
id_workspaceId: {
workspaceId,
id: guid,
},
},
data: {
seq: 0,
},
});
}
return seq;
} catch {
// not existing snapshot just count it from 1
const last = this.seqMap.get(workspaceId + guid) ?? 0;
this.seqMap.set(workspaceId + guid, last + batch);
return last + batch;
}
}
}

View File

@@ -1,266 +0,0 @@
import { isDeepStrictEqual } from 'node:util';
import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { PrismaClient } from '@prisma/client';
import type { EventPayload } from '../../fundamentals';
import {
Config,
DocHistoryNotFound,
DocNotFound,
metrics,
OnEvent,
WorkspaceNotFound,
} from '../../fundamentals';
import { QuotaService } from '../quota';
import { Permission } from '../workspaces/types';
import { isEmptyBuffer } from './manager';
@Injectable()
export class DocHistoryManager {
private readonly logger = new Logger(DocHistoryManager.name);
constructor(
private readonly config: Config,
private readonly db: PrismaClient,
private readonly quota: QuotaService
) {}
@OnEvent('workspace.deleted')
onWorkspaceDeleted(workspaceId: EventPayload<'workspace.deleted'>) {
return this.db.snapshotHistory.deleteMany({
where: {
workspaceId,
},
});
}
@OnEvent('snapshot.deleted')
onSnapshotDeleted({ workspaceId, id }: EventPayload<'snapshot.deleted'>) {
return this.db.snapshotHistory.deleteMany({
where: {
workspaceId,
id,
},
});
}
@OnEvent('snapshot.updated')
async onDocUpdated(
{ workspaceId, id, previous }: EventPayload<'snapshot.updated'>,
forceCreate = false
) {
const last = await this.last(workspaceId, id);
let shouldCreateHistory = false;
if (!last) {
// never created
shouldCreateHistory = true;
} else if (last.timestamp === previous.updatedAt) {
// no change
shouldCreateHistory = false;
} else if (
// force
forceCreate ||
// last history created before interval in configs
last.timestamp.getTime() <
previous.updatedAt.getTime() - this.config.doc.history.interval
) {
shouldCreateHistory = true;
}
if (shouldCreateHistory) {
// skip the history recording when no actual update on snapshot happended
if (last && isDeepStrictEqual(last.state, previous.state)) {
this.logger.debug(
`State matches, skip creating history record for ${id} in workspace ${workspaceId}`
);
return;
}
if (isEmptyBuffer(previous.blob)) {
this.logger.debug(
`Doc is empty, skip creating history record for ${id} in workspace ${workspaceId}`
);
return;
}
await this.db.snapshotHistory
.create({
select: {
timestamp: true,
},
data: {
workspaceId,
id,
timestamp: previous.updatedAt,
blob: previous.blob,
state: previous.state,
expiredAt: await this.getExpiredDateFromNow(workspaceId),
},
})
.catch(() => {
// safe to ignore
// only happens when duplicated history record created in multi processes
});
metrics.doc
.counter('history_created_counter', {
description: 'How many times the snapshot history created',
})
.add(1);
this.logger.debug(
`History created for ${id} in workspace ${workspaceId}.`
);
}
}
async list(
workspaceId: string,
id: string,
before: Date = new Date(),
take: number = 10
) {
return this.db.snapshotHistory.findMany({
select: {
timestamp: true,
},
where: {
workspaceId,
id,
timestamp: {
lt: before,
},
// only include the ones has not expired
expiredAt: {
gt: new Date(),
},
},
orderBy: {
timestamp: 'desc',
},
take,
});
}
async count(workspaceId: string, id: string) {
return this.db.snapshotHistory.count({
where: {
workspaceId,
id,
expiredAt: {
gt: new Date(),
},
},
});
}
async get(workspaceId: string, id: string, timestamp: Date) {
return this.db.snapshotHistory.findUnique({
where: {
workspaceId_id_timestamp: {
workspaceId,
id,
timestamp,
},
expiredAt: {
gt: new Date(),
},
},
});
}
async last(workspaceId: string, id: string) {
return this.db.snapshotHistory.findFirst({
where: {
workspaceId,
id,
},
select: {
timestamp: true,
state: true,
},
orderBy: {
timestamp: 'desc',
},
});
}
async recover(workspaceId: string, id: string, timestamp: Date) {
const history = await this.db.snapshotHistory.findUnique({
where: {
workspaceId_id_timestamp: {
workspaceId,
id,
timestamp,
},
},
});
if (!history) {
throw new DocHistoryNotFound({
workspaceId,
docId: id,
timestamp: timestamp.getTime(),
});
}
const oldSnapshot = await this.db.snapshot.findUnique({
where: {
id_workspaceId: {
id,
workspaceId,
},
},
});
if (!oldSnapshot) {
throw new DocNotFound({ workspaceId, docId: id });
}
// save old snapshot as one history record
await this.onDocUpdated({ workspaceId, id, previous: oldSnapshot }, true);
// WARN:
// we should never do the snapshot updating in recovering,
// which is not the solution in CRDT.
// let user revert in client and update the data in sync system
// `await this.db.snapshot.update();`
metrics.doc
.counter('history_recovered_counter', {
description: 'How many times history recovered request happened',
})
.add(1);
return history.timestamp;
}
async getExpiredDateFromNow(workspaceId: string) {
const permission = await this.db.workspaceUserPermission.findFirst({
select: {
userId: true,
},
where: {
workspaceId,
type: Permission.Owner,
},
});
if (!permission) {
throw new WorkspaceNotFound({ workspaceId });
}
const quota = await this.quota.getUserQuota(permission.userId);
return quota.feature.historyPeriodFromNow;
}
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT /* everyday at 12am */)
async cleanupExpiredHistory() {
await this.db.snapshotHistory.deleteMany({
where: {
expiredAt: {
lte: new Date(),
},
},
});
}
}

View File

@@ -2,15 +2,24 @@ import './config';
import { Module } from '@nestjs/common';
import { PermissionModule } from '../permission';
import { QuotaModule } from '../quota';
import { DocHistoryManager } from './history';
import { DocManager } from './manager';
import { PgUserspaceDocStorageAdapter } from './adapters/userspace';
import { PgWorkspaceDocStorageAdapter } from './adapters/workspace';
import { DocStorageCronJob } from './job';
import { DocStorageOptions } from './options';
@Module({
imports: [QuotaModule],
providers: [DocManager, DocHistoryManager],
exports: [DocManager, DocHistoryManager],
imports: [QuotaModule, PermissionModule],
providers: [
DocStorageOptions,
PgWorkspaceDocStorageAdapter,
PgUserspaceDocStorageAdapter,
DocStorageCronJob,
],
exports: [PgWorkspaceDocStorageAdapter, PgUserspaceDocStorageAdapter],
})
export class DocModule {}
export class DocStorageModule {}
export { PgUserspaceDocStorageAdapter, PgWorkspaceDocStorageAdapter };
export { DocHistoryManager, DocManager };
export { DocStorageAdapter, type Editor } from './storage';

View File

@@ -0,0 +1,76 @@
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { Cron, CronExpression, SchedulerRegistry } from '@nestjs/schedule';
import { PrismaClient } from '@prisma/client';
import { CallTimer, Config, metrics } from '../../fundamentals';
import { PgWorkspaceDocStorageAdapter } from './adapters/workspace';
@Injectable()
export class DocStorageCronJob implements OnModuleInit {
private readonly logger = new Logger(DocStorageCronJob.name);
private busy = false;
constructor(
private readonly registry: SchedulerRegistry,
private readonly config: Config,
private readonly db: PrismaClient,
private readonly workspace: PgWorkspaceDocStorageAdapter
) {}
onModuleInit() {
if (this.config.doc.manager.enableUpdateAutoMerging) {
this.registry.addInterval(
this.autoMergePendingDocUpdates.name,
// scheduler registry will clean up the interval when the app is stopped
setInterval(() => {
if (this.busy) {
return;
}
this.busy = true;
this.autoMergePendingDocUpdates()
.catch(() => {
/* never fail */
})
.finally(() => {
this.busy = false;
});
}, this.config.doc.manager.updatePollInterval)
);
this.logger.log('Updates pending queue auto merging cron started');
}
}
@CallTimer('doc', 'auto_merge_pending_doc_updates')
async autoMergePendingDocUpdates() {
try {
const randomDoc = await this.workspace.randomDoc();
if (!randomDoc) {
return;
}
await this.workspace.getDoc(randomDoc.workspaceId, randomDoc.docId);
} catch (e) {
metrics.doc.counter('auto_merge_pending_doc_updates_error').add(1);
this.logger.error('Failed to auto merge pending doc updates', e);
}
}
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT /* everyday at 12am */)
async cleanupExpiredHistory() {
await this.db.snapshotHistory.deleteMany({
where: {
expiredAt: {
lte: new Date(),
},
},
});
}
@Cron(CronExpression.EVERY_MINUTE)
async reportUpdatesQueueCount() {
metrics.doc
.gauge('updates_queue_count')
.record(await this.db.update.count());
}
}

View File

@@ -1,853 +0,0 @@
import {
Injectable,
Logger,
OnModuleDestroy,
OnModuleInit,
} from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { PrismaClient, Snapshot, Update } from '@prisma/client';
import { chunk } from 'lodash-es';
import { defer, retry } from 'rxjs';
import {
applyUpdate,
Doc,
encodeStateAsUpdate,
encodeStateVector,
transact,
} from 'yjs';
import type { EventPayload } from '../../fundamentals';
import {
Cache,
CallTimer,
Config,
EventEmitter,
mergeUpdatesInApplyWay as jwstMergeUpdates,
metrics,
OnEvent,
} from '../../fundamentals';
function compare(yBinary: Buffer, jwstBinary: Buffer, strict = false): boolean {
if (yBinary.equals(jwstBinary)) {
return true;
}
if (strict) {
return false;
}
const doc = new Doc();
applyUpdate(doc, jwstBinary);
const yBinary2 = Buffer.from(encodeStateAsUpdate(doc));
return compare(yBinary, yBinary2, true);
}
export function isEmptyBuffer(buf: Buffer): boolean {
return (
buf.length === 0 ||
// 0x0000
(buf.length === 2 && buf[0] === 0 && buf[1] === 0)
);
}
const MAX_SEQ_NUM = 0x3fffffff; // u31
const UPDATES_QUEUE_CACHE_KEY = 'doc:manager:updates';
interface DocResponse {
doc: Doc;
timestamp: number;
}
interface BinaryResponse {
binary: Buffer;
timestamp: number;
}
/**
* Since we can't directly save all client updates into database, in which way the database will overload,
* we need to buffer the updates and merge them to reduce db write.
*
* And also, if a new client join, it would be nice to see the latest doc asap,
* so we need to at least store a snapshot of the doc and return quickly,
* along side all the updates that have not been applies to that snapshot(timestamp).
*/
@Injectable()
export class DocManager implements OnModuleInit, OnModuleDestroy {
private readonly logger = new Logger(DocManager.name);
private job: NodeJS.Timeout | null = null;
private readonly seqMap = new Map<string, number>();
private busy = false;
constructor(
private readonly db: PrismaClient,
private readonly config: Config,
private readonly cache: Cache,
private readonly event: EventEmitter
) {}
onModuleInit() {
if (this.config.doc.manager.enableUpdateAutoMerging) {
this.logger.log('Use Database');
this.setup();
}
}
onModuleDestroy() {
this.destroy();
}
@CallTimer('doc', 'yjs_recover_updates_to_doc')
private recoverDoc(...updates: Buffer[]): Promise<Doc> {
const doc = new Doc();
const chunks = chunk(updates, 10);
return new Promise(resolve => {
const next = () => {
const updates = chunks.shift();
if (updates?.length) {
transact(doc, () => {
updates.forEach(u => {
try {
applyUpdate(doc, u);
} catch (e) {
this.logger.error('Failed to apply update', e);
}
});
});
// avoid applying too many updates in single round which will take the whole cpu time like dead lock
setImmediate(() => {
next();
});
} else {
resolve(doc);
}
};
next();
});
}
private async applyUpdates(guid: string, ...updates: Buffer[]): Promise<Doc> {
const doc = await this.recoverDoc(...updates);
const useYocto = await this.config.runtime.fetch(
'doc/experimentalMergeWithYOcto'
);
// test jwst codec
if (useYocto) {
metrics.jwst.counter('codec_merge_counter').add(1);
const yjsResult = Buffer.from(encodeStateAsUpdate(doc));
let log = false;
try {
const jwstResult = jwstMergeUpdates(updates);
if (!compare(yjsResult, jwstResult)) {
metrics.jwst.counter('codec_not_match').add(1);
this.logger.warn(
`jwst codec result doesn't match yjs codec result for: ${guid}`
);
log = true;
if (this.config.node.dev) {
this.logger.warn(`Expected:\n ${yjsResult.toString('hex')}`);
this.logger.warn(`Result:\n ${jwstResult.toString('hex')}`);
}
}
} catch (e) {
metrics.jwst.counter('codec_fails_counter').add(1);
this.logger.warn(`jwst apply update failed for ${guid}: ${e}`);
log = true;
} finally {
if (log && this.config.node.dev) {
this.logger.warn(
`Updates: ${updates.map(u => u.toString('hex')).join('\n')}`
);
}
}
}
return doc;
}
/**
* setup pending update processing loop
*/
setup() {
this.job = setInterval(() => {
if (!this.busy) {
this.busy = true;
this.autoSquash()
.catch(() => {
/* we handle all errors in work itself */
})
.finally(() => {
this.busy = false;
});
}
}, this.config.doc.manager.updatePollInterval);
this.logger.log('Automation started');
}
/**
* stop pending update processing loop
*/
destroy() {
if (this.job) {
clearInterval(this.job);
this.job = null;
this.logger.log('Automation stopped');
}
}
@OnEvent('workspace.deleted')
async onWorkspaceDeleted(workspaceId: string) {
await this.db.snapshot.deleteMany({
where: {
workspaceId,
},
});
await this.db.update.deleteMany({
where: {
workspaceId,
},
});
}
@OnEvent('snapshot.deleted')
async onSnapshotDeleted({
id,
workspaceId,
}: EventPayload<'snapshot.deleted'>) {
await this.db.update.deleteMany({
where: {
id,
workspaceId,
},
});
}
/**
* add update to manager for later processing.
*/
async push(
workspaceId: string,
guid: string,
update: Buffer,
retryTimes = 10
) {
const timestamp = await new Promise<number>((resolve, reject) => {
defer(async () => {
const seq = await this.getUpdateSeq(workspaceId, guid);
const { createdAt } = await this.db.update.create({
select: {
createdAt: true,
},
data: {
workspaceId,
id: guid,
seq,
blob: update,
},
});
return createdAt.getTime();
})
.pipe(retry(retryTimes)) // retry until seq num not conflict
.subscribe({
next: timestamp => {
this.logger.debug(
`pushed 1 update for ${guid} in workspace ${workspaceId}`
);
resolve(timestamp);
},
error: e => {
this.logger.error('Failed to push updates', e);
reject(new Error('Failed to push update'));
},
});
});
await this.updateCachedUpdatesCount(workspaceId, guid, 1);
return timestamp;
}
async batchPush(
workspaceId: string,
guid: string,
updates: Buffer[],
retryTimes = 10
) {
const timestamp = await new Promise<number>((resolve, reject) => {
defer(async () => {
const lastSeq = await this.getUpdateSeq(
workspaceId,
guid,
updates.length
);
const now = Date.now();
let timestamp = now;
let turn = 0;
const batchCount = 10;
for (const batch of chunk(updates, batchCount)) {
await this.db.update.createMany({
data: batch.map((update, i) => {
const subSeq = turn * batchCount + i + 1;
// `seq` is the last seq num of the batch
// example for 11 batched updates, start from seq num 20
// seq for first update in the batch should be:
// 31 - 11 + subSeq(0 * 10 + 0 + 1) = 21
// ^ last seq num ^ updates.length ^ turn ^ batchCount ^i
const seq = lastSeq - updates.length + subSeq;
const createdAt = now + subSeq;
timestamp = Math.max(timestamp, createdAt);
return {
workspaceId,
id: guid,
blob: update,
seq,
createdAt: new Date(createdAt), // make sure the updates can be ordered by create time
};
}),
});
turn++;
}
return timestamp;
})
.pipe(retry(retryTimes)) // retry until seq num not conflict
.subscribe({
next: timestamp => {
this.logger.debug(
`pushed ${updates.length} updates for ${guid} in workspace ${workspaceId}`
);
resolve(timestamp);
},
error: e => {
this.logger.error('Failed to push updates', e);
reject(new Error('Failed to push update'));
},
});
});
await this.updateCachedUpdatesCount(workspaceId, guid, updates.length);
return timestamp;
}
/**
* Get latest timestamp of all docs in the workspace.
*/
@CallTimer('doc', 'get_doc_timestamps')
async getDocTimestamps(workspaceId: string, after: number | undefined = 0) {
const snapshots = await this.db.snapshot.findMany({
where: {
workspaceId,
updatedAt: {
gt: new Date(after),
},
},
select: {
id: true,
updatedAt: true,
},
});
const updates = await this.db.update.groupBy({
where: {
workspaceId,
createdAt: {
gt: new Date(after),
},
},
by: ['id'],
_max: {
createdAt: true,
},
});
const result: Record<string, number> = {};
snapshots.forEach(s => {
result[s.id] = s.updatedAt.getTime();
});
updates.forEach(u => {
if (u._max.createdAt) {
result[u.id] = u._max.createdAt.getTime();
}
});
return result;
}
/**
* get the latest doc with all update applied.
*/
async get(workspaceId: string, guid: string): Promise<DocResponse | null> {
const result = await this._get(workspaceId, guid);
if (result) {
if ('doc' in result) {
return result;
} else {
const doc = await this.recoverDoc(result.binary);
return {
doc,
timestamp: result.timestamp,
};
}
}
return null;
}
/**
* get the latest doc binary with all update applied.
*/
async getBinary(
workspaceId: string,
guid: string
): Promise<BinaryResponse | null> {
const result = await this._get(workspaceId, guid);
if (result) {
if ('doc' in result) {
return {
binary: Buffer.from(encodeStateAsUpdate(result.doc)),
timestamp: result.timestamp,
};
} else {
return result;
}
}
return null;
}
/**
* get the latest doc state vector with all update applied.
*/
async getDocState(
workspaceId: string,
guid: string
): Promise<BinaryResponse | null> {
const snapshot = await this.getSnapshot(workspaceId, guid);
const updates = await this.getUpdates(workspaceId, guid);
if (updates.length) {
const { doc, timestamp } = await this.squash(snapshot, updates);
return {
binary: Buffer.from(encodeStateVector(doc)),
timestamp,
};
}
return snapshot?.state
? {
binary: snapshot.state,
timestamp: snapshot.updatedAt.getTime(),
}
: null;
}
/**
* get the snapshot of the doc we've seen.
*/
async getSnapshot(workspaceId: string, guid: string) {
return this.db.snapshot.findUnique({
where: {
id_workspaceId: {
workspaceId,
id: guid,
},
},
});
}
/**
* get pending updates
*/
async getUpdates(workspaceId: string, guid: string) {
const updates = await this.db.update.findMany({
where: {
workspaceId,
id: guid,
},
// take it ease, we don't want to overload db and or cpu
// if we limit the taken number here,
// user will never see the latest doc if there are too many updates pending to be merged.
take: this.config.doc.manager.maxUpdatesPullCount,
});
// perf(memory): avoid sorting in db
return updates.sort((a, b) => (a.createdAt < b.createdAt ? -1 : 1));
}
/**
* apply pending updates to snapshot
*/
private async autoSquash() {
// find the first update and batch process updates with same id
const candidate = await this.getAutoSquashCandidate();
// no pending updates
if (!candidate) {
return;
}
const { id, workspaceId } = candidate;
await this.lockUpdatesForAutoSquash(workspaceId, id, async () => {
try {
await this._get(workspaceId, id);
} catch (e) {
this.logger.error(
`Failed to apply updates for workspace: ${workspaceId}, guid: ${id}`
);
this.logger.error(e);
}
});
}
private async getAutoSquashCandidate() {
const cache = await this.getAutoSquashCandidateFromCache();
if (cache) {
return cache;
}
return this.db.update.findFirst({
select: {
id: true,
workspaceId: true,
},
});
}
/**
* @returns whether the snapshot is updated to the latest, `undefined` means the doc to be upserted is outdated.
*/
@CallTimer('doc', 'upsert')
private async upsert(
workspaceId: string,
guid: string,
doc: Doc,
// we always delay the snapshot update to avoid db overload,
// so the value of auto updated `updatedAt` by db will never be accurate to user's real action time
updatedAt: Date,
seq: number
) {
const blob = Buffer.from(encodeStateAsUpdate(doc));
if (isEmptyBuffer(blob)) {
return undefined;
}
const state = Buffer.from(encodeStateVector(doc));
// CONCERNS:
// i. Because we save the real user's last seen action time as `updatedAt`,
// it's possible to simply compare the `updatedAt` to determine if the snapshot is older than the one we are going to save.
//
// ii. Prisma doesn't support `upsert` with additional `where` condition along side unique constraint.
// In our case, we need to manually check the `updatedAt` to avoid overriding the newer snapshot.
// where: { id_workspaceId: {}, updatedAt: { lt: updatedAt } }
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// iii. Only set the seq number when creating the snapshot.
// For updating scenario, the seq number will be updated when updates pushed to db.
try {
const result: { updatedAt: Date }[] = await this.db.$queryRaw`
INSERT INTO "snapshots" ("workspace_id", "guid", "blob", "state", "seq", "created_at", "updated_at")
VALUES (${workspaceId}, ${guid}, ${blob}, ${state}, ${seq}, DEFAULT, ${updatedAt})
ON CONFLICT ("workspace_id", "guid")
DO UPDATE SET "blob" = ${blob}, "state" = ${state}, "updated_at" = ${updatedAt}, "seq" = ${seq}
WHERE "snapshots"."workspace_id" = ${workspaceId} AND "snapshots"."guid" = ${guid} AND "snapshots"."updated_at" <= ${updatedAt}
RETURNING "snapshots"."workspace_id" as "workspaceId", "snapshots"."guid" as "id", "snapshots"."updated_at" as "updatedAt"
`;
// const result = await this.db.snapshot.upsert({
// select: {
// updatedAt: true,
// seq: true,
// },
// where: {
// id_workspaceId: {
// workspaceId,
// id: guid,
// },
// ⬇️ NOT SUPPORTED BY PRISMA YET
// updatedAt: {
// lt: updatedAt,
// },
// },
// update: {
// blob,
// state,
// updatedAt,
// },
// create: {
// workspaceId,
// id: guid,
// blob,
// state,
// updatedAt,
// seq,
// },
// });
// if the condition `snapshot.updatedAt > updatedAt` is true, by which means the snapshot has already been updated by other process,
// the updates has been applied to current `doc` must have been seen by the other process as well.
// The `updatedSnapshot` will be `undefined` in this case.
const updatedSnapshot = result.at(0);
if (!updatedSnapshot) {
return undefined;
}
return true;
} catch (e) {
this.logger.error('Failed to upsert snapshot', e);
return false;
}
}
private async _get(
workspaceId: string,
guid: string
): Promise<DocResponse | BinaryResponse | null> {
const snapshot = await this.getSnapshot(workspaceId, guid);
const updates = await this.getUpdates(workspaceId, guid);
if (updates.length) {
return this.squash(snapshot, updates);
}
return snapshot
? { binary: snapshot.blob, timestamp: snapshot.updatedAt.getTime() }
: null;
}
/**
* Squash updates into a single update and save it as snapshot,
* and delete the updates records at the same time.
*/
@CallTimer('doc', 'squash')
private async squash(
snapshot: Snapshot | null,
updates: Update[]
): Promise<DocResponse> {
if (!updates.length) {
throw new Error('No updates to squash');
}
const last = updates[updates.length - 1];
const { id, workspaceId } = last;
const doc = await this.applyUpdates(
id,
snapshot ? snapshot.blob : Buffer.from([0, 0]),
...updates.map(u => u.blob)
);
const done = await this.upsert(
workspaceId,
id,
doc,
last.createdAt,
last.seq
);
if (done) {
if (snapshot) {
this.event.emit('snapshot.updated', {
id,
workspaceId,
previous: {
blob: snapshot.blob,
state: snapshot.state,
updatedAt: snapshot.updatedAt,
},
});
}
this.logger.debug(
`Squashed ${updates.length} updates for ${id} in workspace ${workspaceId}`
);
}
// we will keep the updates only if the upsert failed on unknown reason
// `done === undefined` means the updates is outdated(have already been merged by other process), safe to be deleted
// `done === true` means the upsert is successful, safe to be deleted
if (done !== false) {
// always delete updates
// the upsert will return false if the state is not newer, so we don't need to worry about it
const { count } = await this.db.update.deleteMany({
where: {
id,
workspaceId,
seq: {
in: updates.map(u => u.seq),
},
},
});
await this.updateCachedUpdatesCount(workspaceId, id, -count);
}
return { doc, timestamp: last.createdAt.getTime() };
}
private async getUpdateSeq(workspaceId: string, guid: string, batch = 1) {
try {
const { seq } = await this.db.snapshot.update({
select: {
seq: true,
},
where: {
id_workspaceId: {
workspaceId,
id: guid,
},
},
data: {
seq: {
increment: batch,
},
},
});
// reset
if (seq >= MAX_SEQ_NUM) {
await this.db.snapshot.update({
select: {
seq: true,
},
where: {
id_workspaceId: {
workspaceId,
id: guid,
},
},
data: {
seq: 0,
},
});
}
return seq;
} catch {
// not existing snapshot just count it from 1
const last = this.seqMap.get(workspaceId + guid) ?? 0;
this.seqMap.set(workspaceId + guid, last + batch);
return last + batch;
}
}
private async updateCachedUpdatesCount(
workspaceId: string,
guid: string,
count: number
) {
const result = await this.cache.mapIncrease(
UPDATES_QUEUE_CACHE_KEY,
`${workspaceId}::${guid}`,
count
);
if (result <= 0) {
await this.cache.mapDelete(
UPDATES_QUEUE_CACHE_KEY,
`${workspaceId}::${guid}`
);
}
}
private async getAutoSquashCandidateFromCache() {
const key = await this.cache.mapRandomKey(UPDATES_QUEUE_CACHE_KEY);
if (key) {
const cachedCount = await this.cache.mapIncrease(
UPDATES_QUEUE_CACHE_KEY,
key,
0
);
if (cachedCount > 0) {
const [workspaceId, id] = key.split('::');
const count = await this.db.update.count({
where: {
workspaceId,
id,
},
});
// FIXME(@forehalo): somehow the update count in cache is not accurate
if (count === 0) {
await this.cache.mapDelete(UPDATES_QUEUE_CACHE_KEY, key);
return null;
}
return { id, workspaceId };
}
}
return null;
}
private async doWithLock<T>(
lockScope: string,
lockResource: string,
job: () => Promise<T>
) {
const lock = `lock:${lockScope}:${lockResource}`;
const acquired = await this.cache.setnx(lock, 1, {
ttl: 60 * 1000,
});
metrics.doc.counter('lock').add(1, { scope: lockScope });
if (!acquired) {
metrics.doc.counter('lock_failed').add(1, { scope: lockScope });
return;
}
metrics.doc.counter('lock_required').add(1, { scope: lockScope });
try {
return await job();
} finally {
await this.cache
.delete(lock)
.then(() => {
metrics.doc.counter('lock_released').add(1, { scope: lockScope });
})
.catch(e => {
metrics.doc
.counter('lock_release_failed')
.add(1, { scope: lockScope });
// safe, the lock will be expired when ttl ends
this.logger.error(`Failed to release lock ${lock}`, e);
});
}
}
private async lockUpdatesForAutoSquash<T>(
workspaceId: string,
guid: string,
job: () => Promise<T>
) {
return this.doWithLock(
'doc:manager:updates',
`${workspaceId}::${guid}`,
job
);
}
@Cron(CronExpression.EVERY_MINUTE)
async reportUpdatesQueueCount() {
metrics.doc
.gauge('updates_queue_count')
.record(await this.db.update.count());
}
}

View File

@@ -0,0 +1,130 @@
import { Injectable, Logger } from '@nestjs/common';
import { chunk } from 'lodash-es';
import * as Y from 'yjs';
import {
CallTimer,
Config,
mergeUpdatesInApplyWay as yotcoMergeUpdates,
metrics,
} from '../../fundamentals';
import { PermissionService } from '../permission';
import { QuotaService } from '../quota';
import { DocStorageOptions as IDocStorageOptions } from './storage';
function compare(yBinary: Buffer, jwstBinary: Buffer, strict = false): boolean {
if (yBinary.equals(jwstBinary)) {
return true;
}
if (strict) {
return false;
}
const doc = new Y.Doc();
Y.applyUpdate(doc, jwstBinary);
const yBinary2 = Buffer.from(Y.encodeStateAsUpdate(doc));
return compare(yBinary, yBinary2, true);
}
@Injectable()
export class DocStorageOptions implements IDocStorageOptions {
private readonly logger = new Logger('DocStorageOptions');
constructor(
private readonly config: Config,
private readonly permission: PermissionService,
private readonly quota: QuotaService
) {}
mergeUpdates = async (updates: Uint8Array[]) => {
const useYocto = await this.config.runtime.fetch(
'doc/experimentalMergeWithYOcto'
);
if (useYocto) {
const doc = await this.recoverDoc(updates);
metrics.jwst.counter('codec_merge_counter').add(1);
const yjsResult = Buffer.from(Y.encodeStateAsUpdate(doc));
let log = false;
try {
const yocto = yotcoMergeUpdates(updates.map(Buffer.from));
if (!compare(yjsResult, yocto)) {
metrics.jwst.counter('codec_not_match').add(1);
this.logger.warn(`yocto codec result doesn't match yjs codec result`);
log = true;
if (this.config.node.dev) {
this.logger.warn(`Expected:\n ${yjsResult.toString('hex')}`);
this.logger.warn(`Result:\n ${yocto.toString('hex')}`);
}
}
} catch (e) {
metrics.jwst.counter('codec_fails_counter').add(1);
this.logger.warn(`jwst apply update failed: ${e}`);
log = true;
}
if (log && this.config.node.dev) {
this.logger.warn(
`Updates: ${updates.map(u => Buffer.from(u).toString('hex')).join('\n')}`
);
}
return yjsResult;
} else {
return this.simpleMergeUpdates(updates);
}
};
historyMaxAge = async (spaceId: string) => {
const owner = await this.permission.getWorkspaceOwner(spaceId);
const quota = await this.quota.getUserQuota(owner.id);
return quota.feature.historyPeriod;
};
historyMinInterval = (_spaceId: string) => {
return this.config.doc.history.interval;
};
@CallTimer('doc', 'yjs_merge_updates')
private simpleMergeUpdates(updates: Uint8Array[]) {
return Y.mergeUpdates(updates);
}
@CallTimer('doc', 'yjs_recover_updates_to_doc')
private recoverDoc(updates: Uint8Array[]): Promise<Y.Doc> {
const doc = new Y.Doc();
const chunks = chunk(updates, 10);
let i = 0;
return new Promise(resolve => {
Y.transact(doc, () => {
const next = () => {
const updates = chunks.at(i++);
if (updates?.length) {
updates.forEach(u => {
try {
Y.applyUpdate(doc, u);
} catch (e) {
this.logger.error('Failed to apply update', e);
}
});
// avoid applying too many updates in single round which will take the whole cpu time like dead lock
setImmediate(() => {
next();
});
} else {
resolve(doc);
}
};
next();
});
});
}
}

View File

@@ -0,0 +1,16 @@
import { Connection } from './connection';
export interface BlobStorageOptions {}
export interface Blob {
key: string;
bin: Uint8Array;
mimeType: string;
}
export abstract class BlobStorageAdapter extends Connection {
abstract getBlob(spaceId: string, key: string): Promise<Blob | null>;
abstract setBlob(spaceId: string, blob: Blob): Promise<string>;
abstract deleteBlob(spaceId: string, key: string): Promise<boolean>;
abstract listBlobs(spaceId: string): Promise<Blob>;
}

View File

@@ -0,0 +1,11 @@
export class Connection {
protected connected: boolean = false;
connect(): Promise<void> {
this.connected = true;
return Promise.resolve();
}
disconnect(): Promise<void> {
this.connected = false;
return Promise.resolve();
}
}

View File

@@ -0,0 +1,216 @@
import {
applyUpdate,
Doc,
encodeStateAsUpdate,
encodeStateVector,
mergeUpdates,
UndoManager,
} from 'yjs';
import { CallTimer } from '../../../fundamentals';
import { Connection } from './connection';
import { SingletonLocker } from './lock';
export interface DocRecord {
spaceId: string;
docId: string;
bin: Uint8Array;
timestamp: number;
editor?: string;
}
export interface DocUpdate {
bin: Uint8Array;
timestamp: number;
editor?: string;
}
export interface HistoryFilter {
before?: number;
limit?: number;
}
export interface Editor {
name: string;
avatarUrl: string | null;
}
export interface DocStorageOptions {
mergeUpdates?: (updates: Uint8Array[]) => Promise<Uint8Array> | Uint8Array;
}
export abstract class DocStorageAdapter extends Connection {
private readonly locker = new SingletonLocker();
constructor(
protected readonly options: DocStorageOptions = {
mergeUpdates,
}
) {
super();
}
// open apis
isEmptyBin(bin: Uint8Array): boolean {
return (
bin.length === 0 ||
// 0x0 for state vector
(bin.length === 1 && bin[0] === 0) ||
// 0x00 for update
(bin.length === 2 && bin[0] === 0 && bin[1] === 0)
);
}
async getDoc(spaceId: string, docId: string): Promise<DocRecord | null> {
await using _lock = await this.lockDocForUpdate(spaceId, docId);
const snapshot = await this.getDocSnapshot(spaceId, docId);
const updates = await this.getDocUpdates(spaceId, docId);
if (updates.length) {
const { timestamp, bin, editor } = await this.squash(
snapshot ? [snapshot, ...updates] : updates
);
const newSnapshot = {
spaceId: spaceId,
docId,
bin,
timestamp,
editor,
};
const success = await this.setDocSnapshot(newSnapshot);
// if there is old snapshot, create a new history record
if (success && snapshot) {
await this.createDocHistory(snapshot);
}
// always mark updates as merged unless throws
await this.markUpdatesMerged(spaceId, docId, updates);
return newSnapshot;
}
return snapshot;
}
abstract pushDocUpdates(
spaceId: string,
docId: string,
updates: Uint8Array[],
editorId?: string
): Promise<number>;
abstract deleteDoc(spaceId: string, docId: string): Promise<void>;
abstract deleteSpace(spaceId: string): Promise<void>;
async rollbackDoc(
spaceId: string,
docId: string,
timestamp: number,
editorId?: string
): Promise<void> {
await using _lock = await this.lockDocForUpdate(spaceId, docId);
const toSnapshot = await this.getDocHistory(spaceId, docId, timestamp);
if (!toSnapshot) {
throw new Error('Can not find the version to rollback to.');
}
const fromSnapshot = await this.getDocSnapshot(spaceId, docId);
if (!fromSnapshot) {
throw new Error('Can not find the current version of the doc.');
}
const change = this.generateChangeUpdate(fromSnapshot.bin, toSnapshot.bin);
await this.pushDocUpdates(spaceId, docId, [change], editorId);
// force create a new history record after rollback
await this.createDocHistory(fromSnapshot, true);
}
abstract getSpaceDocTimestamps(
spaceId: string,
after?: number
): Promise<Record<string, number> | null>;
abstract listDocHistories(
spaceId: string,
docId: string,
query: { skip?: number; limit?: number }
): Promise<{ timestamp: number; editor: Editor | null }[]>;
abstract getDocHistory(
spaceId: string,
docId: string,
timestamp: number
): Promise<DocRecord | null>;
// api for internal usage
protected abstract getDocSnapshot(
spaceId: string,
docId: string
): Promise<DocRecord | null>;
protected abstract setDocSnapshot(snapshot: DocRecord): Promise<boolean>;
protected abstract getDocUpdates(
spaceId: string,
docId: string
): Promise<DocUpdate[]>;
protected abstract markUpdatesMerged(
spaceId: string,
docId: string,
updates: DocUpdate[]
): Promise<number>;
protected abstract createDocHistory(
snapshot: DocRecord,
force?: boolean
): Promise<boolean>;
@CallTimer('doc', 'squash')
protected async squash(updates: DocUpdate[]): Promise<DocUpdate> {
const merge = this.options?.mergeUpdates ?? mergeUpdates;
const lastUpdate = updates.at(-1);
if (!lastUpdate) {
throw new Error('No updates to be squashed.');
}
// fast return
if (updates.length === 1) {
return lastUpdate;
}
const finalUpdate = await merge(updates.map(u => u.bin));
return {
bin: finalUpdate,
timestamp: lastUpdate.timestamp,
editor: lastUpdate.editor,
};
}
protected async lockDocForUpdate(
spaceId: string,
docId: string
): Promise<AsyncDisposable> {
return this.locker.lock(`workspace:${spaceId}:update`, docId);
}
protected generateChangeUpdate(newerBin: Uint8Array, olderBin: Uint8Array) {
const newerDoc = new Doc();
applyUpdate(newerDoc, newerBin);
const olderDoc = new Doc();
applyUpdate(olderDoc, olderBin);
const newerState = encodeStateVector(newerDoc);
const olderState = encodeStateVector(olderDoc);
const diff = encodeStateAsUpdate(newerDoc, olderState);
const undoManager = new UndoManager(Array.from(newerDoc.share.values()));
applyUpdate(olderDoc, diff);
undoManager.undo();
return encodeStateAsUpdate(olderDoc, newerState);
}
}

View File

@@ -0,0 +1,33 @@
// TODO(@forehalo): share with frontend
import type { BlobStorageAdapter } from './blob';
import { Connection } from './connection';
import type { DocStorageAdapter } from './doc';
export class SpaceStorage extends Connection {
constructor(
public readonly doc: DocStorageAdapter,
public readonly blob: BlobStorageAdapter
) {
super();
}
override async connect() {
await this.doc.connect();
await this.blob.connect();
}
override async disconnect() {
await this.doc.disconnect();
await this.blob.disconnect();
}
}
export { BlobStorageAdapter, type BlobStorageOptions } from './blob';
export {
type DocRecord,
DocStorageAdapter,
type DocStorageOptions,
type DocUpdate,
type Editor,
type HistoryFilter,
} from './doc';

View File

@@ -0,0 +1,42 @@
export interface Locker {
lock(domain: string, resource: string): Promise<Lock>;
}
export class SingletonLocker implements Locker {
lockedResource = new Map<string, Lock>();
constructor() {}
async lock(domain: string, resource: string) {
let lock = this.lockedResource.get(`${domain}:${resource}`);
if (!lock) {
lock = new Lock();
}
await lock.acquire();
return lock;
}
}
export class Lock {
private inner: Promise<void> = Promise.resolve();
private release: () => void = () => {};
async acquire() {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
let release: () => void = null!;
const nextLock = new Promise<void>(resolve => {
release = resolve;
});
await this.inner;
this.inner = nextLock;
this.release = release;
}
[Symbol.asyncDispose]() {
this.release();
return Promise.resolve();
}
}

View File

@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { PermissionService } from './service';
@Module({
providers: [PermissionService],
exports: [PermissionService],
})
export class PermissionModule {}
export { PermissionService } from './service';
export { Permission, PublicPageMode } from './types';

View File

@@ -2,13 +2,12 @@ import { Injectable } from '@nestjs/common';
import type { Prisma } from '@prisma/client';
import { PrismaClient } from '@prisma/client';
import { DocAccessDenied, WorkspaceAccessDenied } from '../../fundamentals';
import { Permission } from './types';
export enum PublicPageMode {
Page,
Edgeless,
}
import {
DocAccessDenied,
SpaceAccessDenied,
SpaceOwnerNotFound,
} from '../../fundamentals';
import { Permission, PublicPageMode } from './types';
@Injectable()
export class PermissionService {
@@ -59,7 +58,7 @@ export class PermissionService {
}
async getWorkspaceOwner(workspaceId: string) {
return this.prisma.workspaceUserPermission.findFirstOrThrow({
const owner = await this.prisma.workspaceUserPermission.findFirst({
where: {
workspaceId,
type: Permission.Owner,
@@ -68,6 +67,20 @@ export class PermissionService {
user: true,
},
});
if (!owner) {
throw new SpaceOwnerNotFound({ spaceId: workspaceId });
}
return owner.user;
}
async getWorkspaceMemberCount(workspaceId: string) {
return this.prisma.workspaceUserPermission.count({
where: {
workspaceId,
},
});
}
async tryGetWorkspaceOwner(workspaceId: string) {
@@ -152,7 +165,7 @@ export class PermissionService {
permission: Permission = Permission.Read
) {
if (!(await this.tryCheckWorkspace(ws, user, permission))) {
throw new WorkspaceAccessDenied({ workspaceId: ws });
throw new SpaceAccessDenied({ spaceId: ws });
}
}
@@ -195,6 +208,17 @@ export class PermissionService {
return false;
}
async allowUrlPreview(ws: string) {
const count = await this.prisma.workspace.count({
where: {
id: ws,
public: true,
},
});
return count > 0;
}
async grant(
ws: string,
user: string,
@@ -324,7 +348,7 @@ export class PermissionService {
permission = Permission.Read
) {
if (!(await this.tryCheckPage(ws, page, user, permission))) {
throw new DocAccessDenied({ workspaceId: ws, docId: page });
throw new DocAccessDenied({ spaceId: ws, docId: page });
}
}

View File

@@ -0,0 +1,11 @@
export enum Permission {
Read = 0,
Write = 1,
Admin = 10,
Owner = 99,
}
export enum PublicPageMode {
Page,
Edgeless,
}

View File

@@ -1,8 +1,8 @@
import { Module } from '@nestjs/common';
import { FeatureModule } from '../features';
import { PermissionModule } from '../permission';
import { StorageModule } from '../storage';
import { PermissionService } from '../workspaces/permission';
import { QuotaManagementResolver } from './resolver';
import { QuotaService } from './service';
import { QuotaManagementService } from './storage';
@@ -14,13 +14,8 @@ import { QuotaManagementService } from './storage';
* - quota statistics
*/
@Module({
imports: [FeatureModule, StorageModule],
providers: [
PermissionService,
QuotaService,
QuotaManagementResolver,
QuotaManagementService,
],
imports: [FeatureModule, StorageModule, PermissionModule],
providers: [QuotaService, QuotaManagementResolver, QuotaManagementService],
exports: [QuotaService, QuotaManagementService],
})
export class QuotaModule {}

View File

@@ -71,10 +71,6 @@ export class QuotaConfig {
return this.config.configs.historyPeriod;
}
get historyPeriodFromNow() {
return new Date(Date.now() + this.historyPeriod);
}
get memberLimit() {
return this.config.configs.memberLimit;
}

View File

@@ -7,7 +7,7 @@ import {
} from '@nestjs/graphql';
import { SafeIntResolver } from 'graphql-scalars';
import { CurrentUser } from '../auth/current-user';
import { CurrentUser } from '../auth/session';
import { EarlyAccessType } from '../features';
import { UserType } from '../user';
import { QuotaService } from './service';

View File

@@ -69,7 +69,7 @@ export class QuotaService {
...quota,
feature: await QuotaConfig.get(this.prisma, quota.featureId),
};
} catch (_) {}
} catch {}
return null as unknown as typeof quota & {
feature: QuotaConfig;
};

View File

@@ -1,9 +1,8 @@
import { Injectable, Logger } from '@nestjs/common';
import { WorkspaceOwnerNotFound } from '../../fundamentals';
import { FeatureService, FeatureType } from '../features';
import { PermissionService } from '../permission';
import { WorkspaceBlobStorage } from '../storage';
import { PermissionService } from '../workspaces/permission';
import { OneGB } from './constant';
import { QuotaService } from './service';
import { formatSize, QuotaQueryType } from './types';
@@ -113,9 +112,9 @@ export class QuotaManagementService {
// get workspace's owner quota and total size of used
// quota was apply to owner's account
async getWorkspaceUsage(workspaceId: string): Promise<QuotaBusinessType> {
const { user: owner } =
await this.permissions.getWorkspaceOwner(workspaceId);
if (!owner) throw new WorkspaceOwnerNotFound({ workspaceId });
const owner = await this.permissions.getWorkspaceOwner(workspaceId);
const memberCount =
await this.permissions.getWorkspaceMemberCount(workspaceId);
const {
feature: {
name,
@@ -148,6 +147,7 @@ export class QuotaManagementService {
humanReadable,
usedSize,
unlimited,
memberCount,
};
if (quota.unlimited) {

View File

@@ -87,6 +87,9 @@ export class QuotaQueryType {
@Field(() => SafeIntResolver)
memberLimit!: number;
@Field(() => SafeIntResolver)
memberCount!: number;
@Field(() => SafeIntResolver)
storageQuota!: number;

View File

@@ -1,15 +1,15 @@
import { Body, Controller, Post, Req, Res } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import type { Request, Response } from 'express';
import {
ActionForbidden,
EventEmitter,
InternalServerError,
MutexService,
Mutex,
PasswordRequired,
} from '../../fundamentals';
import { AuthService, Public } from '../auth';
import { ServerService } from '../config';
import { UserService } from '../user/service';
interface CreateUserInput {
@@ -20,11 +20,11 @@ interface CreateUserInput {
@Controller('/api/setup')
export class CustomSetupController {
constructor(
private readonly db: PrismaClient,
private readonly user: UserService,
private readonly auth: AuthService,
private readonly event: EventEmitter,
private readonly mutex: MutexService
private readonly mutex: Mutex,
private readonly server: ServerService
) {}
@Public()
@@ -44,7 +44,7 @@ export class CustomSetupController {
throw new InternalServerError();
}
if ((await this.db.user.count()) > 0) {
if (await this.server.initialized()) {
throw new ActionForbidden('First user already created');
}
@@ -56,7 +56,7 @@ export class CustomSetupController {
try {
await this.event.emitAsync('user.admin.created', user);
await this.auth.setCookie(req, res, user);
await this.auth.setCookies(req, res, user.id);
res.send({ id: user.id, email: user.email, name: user.name });
} catch (e) {
await this.user.deleteUser(user.id);

View File

@@ -0,0 +1,104 @@
import { join } from 'node:path';
import {
Injectable,
Module,
NestMiddleware,
OnModuleInit,
} from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
import type { Application, Request, Response } from 'express';
import { static as serveStatic } from 'express';
import { Config } from '../../fundamentals';
import { AuthModule } from '../auth';
import { ServerConfigModule, ServerService } from '../config';
import { UserModule } from '../user';
import { CustomSetupController } from './controller';
@Injectable()
export class SetupMiddleware implements NestMiddleware {
constructor(private readonly server: ServerService) {}
use = (req: Request, res: Response, next: (error?: Error | any) => void) => {
// never throw
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.server
.initialized()
.then(initialized => {
// Redirect to setup page if not initialized
if (!initialized && req.path !== '/admin/setup') {
res.redirect('/admin/setup');
return;
}
// redirect to admin page if initialized
if (initialized && req.path === '/admin/setup') {
res.redirect('/admin');
return;
}
next();
})
.catch(() => {
next();
});
};
}
@Module({
imports: [AuthModule, UserModule, ServerConfigModule],
providers: [SetupMiddleware],
controllers: [CustomSetupController],
})
export class SelfhostModule implements OnModuleInit {
constructor(
private readonly config: Config,
private readonly adapterHost: HttpAdapterHost,
private readonly check: SetupMiddleware
) {}
onModuleInit() {
const staticPath = join(this.config.projectRoot, 'static');
// in command line mode
if (!this.adapterHost.httpAdapter) {
return;
}
const app = this.adapterHost.httpAdapter.getInstance<Application>();
const basePath = this.config.server.path;
app.get(basePath + '/admin/index.html', (_req, res) => {
res.redirect(basePath + '/admin');
});
app.use(
basePath + '/admin',
serveStatic(join(staticPath, 'admin'), {
redirect: false,
index: false,
})
);
app.get(
[basePath + '/admin', basePath + '/admin/*'],
this.check.use,
(_req, res) => {
res.sendFile(join(staticPath, 'admin', 'index.html'));
}
);
app.get(basePath + '/index.html', (_req, res) => {
res.redirect(basePath);
});
app.use(
basePath,
serveStatic(staticPath, {
redirect: false,
index: false,
})
);
app.get('*', this.check.use, (_req, res) => {
res.sendFile(join(staticPath, 'index.html'));
});
}
}

View File

@@ -1,11 +0,0 @@
import { Module } from '@nestjs/common';
import { AuthModule } from '../auth';
import { UserModule } from '../user';
import { CustomSetupController } from './controller';
@Module({
imports: [AuthModule, UserModule],
controllers: [CustomSetupController],
})
export class CustomSetupModule {}

View File

@@ -1,328 +0,0 @@
import { applyDecorators, Logger } from '@nestjs/common';
import {
ConnectedSocket,
MessageBody,
OnGatewayConnection,
OnGatewayDisconnect,
SubscribeMessage as RawSubscribeMessage,
WebSocketGateway,
WebSocketServer,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { encodeStateAsUpdate, encodeStateVector } from 'yjs';
import {
CallTimer,
Config,
DocNotFound,
GatewayErrorWrapper,
metrics,
NotInWorkspace,
VersionRejected,
WorkspaceAccessDenied,
} from '../../../fundamentals';
import { Auth, CurrentUser } from '../../auth';
import { DocManager } from '../../doc';
import { DocID } from '../../utils/doc';
import { PermissionService } from '../../workspaces/permission';
import { Permission } from '../../workspaces/types';
const SubscribeMessage = (event: string) =>
applyDecorators(
GatewayErrorWrapper(event),
CallTimer('socketio', 'event_duration', { event }),
RawSubscribeMessage(event)
);
type EventResponse<Data = any> = Data extends never
? {
data?: never;
}
: {
data: Data;
};
function Sync(workspaceId: string): `${string}:sync` {
return `${workspaceId}:sync`;
}
function Awareness(workspaceId: string): `${string}:awareness` {
return `${workspaceId}:awareness`;
}
@WebSocketGateway()
export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect {
protected logger = new Logger(EventsGateway.name);
private connectionCount = 0;
constructor(
private readonly config: Config,
private readonly docManager: DocManager,
private readonly permissions: PermissionService
) {}
@WebSocketServer()
server!: Server;
handleConnection() {
this.connectionCount++;
metrics.socketio.gauge('realtime_connections').record(this.connectionCount);
}
handleDisconnect() {
this.connectionCount--;
metrics.socketio.gauge('realtime_connections').record(this.connectionCount);
}
async assertVersion(client: Socket, version?: string) {
const shouldCheckClientVersion = await this.config.runtime.fetch(
'flags/syncClientVersionCheck'
);
if (
// @todo(@darkskygit): remove this flag after 0.12 goes stable
shouldCheckClientVersion &&
version !== AFFiNE.version
) {
client.emit('server-version-rejected', {
currentVersion: version,
requiredVersion: AFFiNE.version,
reason: `Client version${
version ? ` ${version}` : ''
} is outdated, please update to ${AFFiNE.version}`,
});
throw new VersionRejected({
version: version || 'unknown',
serverVersion: AFFiNE.version,
});
}
}
async joinWorkspace(
client: Socket,
room: `${string}:${'sync' | 'awareness'}`
) {
await client.join(room);
}
async leaveWorkspace(
client: Socket,
room: `${string}:${'sync' | 'awareness'}`
) {
await client.leave(room);
}
assertInWorkspace(client: Socket, room: `${string}:${'sync' | 'awareness'}`) {
if (!client.rooms.has(room)) {
throw new NotInWorkspace({ workspaceId: room.split(':')[0] });
}
}
async assertWorkspaceAccessible(
workspaceId: string,
userId: string,
permission: Permission = Permission.Read
) {
if (
!(await this.permissions.isWorkspaceMember(
workspaceId,
userId,
permission
))
) {
throw new WorkspaceAccessDenied({ workspaceId });
}
}
@Auth()
@SubscribeMessage('client-handshake-sync')
async handleClientHandshakeSync(
@CurrentUser() user: CurrentUser,
@MessageBody('workspaceId') workspaceId: string,
@MessageBody('version') version: string | undefined,
@ConnectedSocket() client: Socket
): Promise<EventResponse<{ clientId: string }>> {
await this.assertVersion(client, version);
await this.assertWorkspaceAccessible(
workspaceId,
user.id,
Permission.Write
);
await this.joinWorkspace(client, Sync(workspaceId));
return {
data: {
clientId: client.id,
},
};
}
@Auth()
@SubscribeMessage('client-handshake-awareness')
async handleClientHandshakeAwareness(
@CurrentUser() user: CurrentUser,
@MessageBody('workspaceId') workspaceId: string,
@MessageBody('version') version: string | undefined,
@ConnectedSocket() client: Socket
): Promise<EventResponse<{ clientId: string }>> {
await this.assertVersion(client, version);
await this.assertWorkspaceAccessible(
workspaceId,
user.id,
Permission.Write
);
await this.joinWorkspace(client, Awareness(workspaceId));
return {
data: {
clientId: client.id,
},
};
}
@SubscribeMessage('client-leave-sync')
async handleLeaveSync(
@MessageBody() workspaceId: string,
@ConnectedSocket() client: Socket
): Promise<EventResponse> {
this.assertInWorkspace(client, Sync(workspaceId));
await this.leaveWorkspace(client, Sync(workspaceId));
return {};
}
@SubscribeMessage('client-leave-awareness')
async handleLeaveAwareness(
@MessageBody() workspaceId: string,
@ConnectedSocket() client: Socket
): Promise<EventResponse> {
this.assertInWorkspace(client, Awareness(workspaceId));
await this.leaveWorkspace(client, Awareness(workspaceId));
return {};
}
@SubscribeMessage('client-pre-sync')
async loadDocStats(
@ConnectedSocket() client: Socket,
@MessageBody()
{ workspaceId, timestamp }: { workspaceId: string; timestamp?: number }
): Promise<EventResponse<Record<string, number>>> {
this.assertInWorkspace(client, Sync(workspaceId));
const stats = await this.docManager.getDocTimestamps(
workspaceId,
timestamp
);
return {
data: stats,
};
}
@SubscribeMessage('client-update-v2')
async handleClientUpdateV2(
@MessageBody()
{
workspaceId,
guid,
updates,
}: {
workspaceId: string;
guid: string;
updates: string[];
},
@ConnectedSocket() client: Socket
): Promise<EventResponse<{ accepted: true; timestamp?: number }>> {
this.assertInWorkspace(client, Sync(workspaceId));
const docId = new DocID(guid, workspaceId);
const buffers = updates.map(update => Buffer.from(update, 'base64'));
const timestamp = await this.docManager.batchPush(
docId.workspace,
docId.guid,
buffers
);
client
.to(Sync(workspaceId))
.emit('server-updates', { workspaceId, guid, updates, timestamp });
return {
data: {
accepted: true,
timestamp,
},
};
}
@SubscribeMessage('doc-load-v2')
async loadDocV2(
@ConnectedSocket() client: Socket,
@MessageBody()
{
workspaceId,
guid,
stateVector,
}: {
workspaceId: string;
guid: string;
stateVector?: string;
}
): Promise<
EventResponse<{ missing: string; state?: string; timestamp: number }>
> {
this.assertInWorkspace(client, Sync(workspaceId));
const docId = new DocID(guid, workspaceId);
const res = await this.docManager.get(docId.workspace, docId.guid);
if (!res) {
throw new DocNotFound({ workspaceId, docId: docId.guid });
}
const missing = Buffer.from(
encodeStateAsUpdate(
res.doc,
stateVector ? Buffer.from(stateVector, 'base64') : undefined
)
).toString('base64');
const state = Buffer.from(encodeStateVector(res.doc)).toString('base64');
return {
data: {
missing,
state,
timestamp: res.timestamp,
},
};
}
@SubscribeMessage('awareness-init')
async handleInitAwareness(
@MessageBody() workspaceId: string,
@ConnectedSocket() client: Socket
): Promise<EventResponse<{ clientId: string }>> {
this.assertInWorkspace(client, Awareness(workspaceId));
client.to(Awareness(workspaceId)).emit('new-client-awareness-init');
return {
data: {
clientId: client.id,
},
};
}
@SubscribeMessage('awareness-update')
async handleHelpGatheringAwareness(
@MessageBody()
{
workspaceId,
awarenessUpdate,
}: { workspaceId: string; awarenessUpdate: string },
@ConnectedSocket() client: Socket
): Promise<EventResponse> {
this.assertInWorkspace(client, Awareness(workspaceId));
client
.to(Awareness(workspaceId))
.emit('server-awareness-broadcast', { workspaceId, awarenessUpdate });
return {};
}
}

View File

@@ -1,11 +0,0 @@
import { Module } from '@nestjs/common';
import { DocModule } from '../../doc';
import { PermissionService } from '../../workspaces/permission';
import { EventsGateway } from './events.gateway';
@Module({
imports: [DocModule],
providers: [EventsGateway, PermissionService],
})
export class EventsModule {}

View File

@@ -0,0 +1,665 @@
import { applyDecorators, Logger } from '@nestjs/common';
import {
ConnectedSocket,
MessageBody,
OnGatewayConnection,
OnGatewayDisconnect,
SubscribeMessage as RawSubscribeMessage,
WebSocketGateway,
} from '@nestjs/websockets';
import { Socket } from 'socket.io';
import { diffUpdate, encodeStateVectorFromUpdate } from 'yjs';
import {
AlreadyInSpace,
CallTimer,
Config,
DocNotFound,
GatewayErrorWrapper,
metrics,
NotInSpace,
SpaceAccessDenied,
VersionRejected,
} from '../../fundamentals';
import { CurrentUser } from '../auth';
import {
DocStorageAdapter,
PgUserspaceDocStorageAdapter,
PgWorkspaceDocStorageAdapter,
} from '../doc';
import { Permission, PermissionService } from '../permission';
import { DocID } from '../utils/doc';
const SubscribeMessage = (event: string) =>
applyDecorators(
GatewayErrorWrapper(event),
CallTimer('socketio', 'event_duration', { event }),
RawSubscribeMessage(event)
);
type EventResponse<Data = any> = Data extends never
? {
data?: never;
}
: {
data: Data;
};
type RoomType = 'sync' | `${string}:awareness`;
function Room(
spaceId: string,
type: RoomType = 'sync'
): `${string}:${RoomType}` {
return `${spaceId}:${type}`;
}
enum SpaceType {
Workspace = 'workspace',
Userspace = 'userspace',
}
interface JoinSpaceMessage {
spaceType: SpaceType;
spaceId: string;
clientVersion: string;
}
interface JoinSpaceAwarenessMessage {
spaceType: SpaceType;
spaceId: string;
docId: string;
clientVersion: string;
}
interface LeaveSpaceMessage {
spaceType: SpaceType;
spaceId: string;
}
interface LeaveSpaceAwarenessMessage {
spaceType: SpaceType;
spaceId: string;
docId: string;
}
interface PushDocUpdatesMessage {
spaceType: SpaceType;
spaceId: string;
docId: string;
updates: string[];
}
interface LoadDocMessage {
spaceType: SpaceType;
spaceId: string;
docId: string;
stateVector?: string;
}
interface LoadDocTimestampsMessage {
spaceType: SpaceType;
spaceId: string;
timestamp?: number;
}
interface LoadSpaceAwarenessesMessage {
spaceType: SpaceType;
spaceId: string;
docId: string;
}
interface UpdateAwarenessMessage {
spaceType: SpaceType;
spaceId: string;
docId: string;
awarenessUpdate: string;
}
@WebSocketGateway()
export class SpaceSyncGateway
implements OnGatewayConnection, OnGatewayDisconnect
{
protected logger = new Logger(SpaceSyncGateway.name);
private connectionCount = 0;
constructor(
private readonly config: Config,
private readonly permissions: PermissionService,
private readonly workspace: PgWorkspaceDocStorageAdapter,
private readonly userspace: PgUserspaceDocStorageAdapter
) {}
handleConnection() {
this.connectionCount++;
metrics.socketio.gauge('realtime_connections').record(this.connectionCount);
}
handleDisconnect() {
this.connectionCount--;
metrics.socketio.gauge('realtime_connections').record(this.connectionCount);
}
selectAdapter(client: Socket, spaceType: SpaceType): SyncSocketAdapter {
let adapters: Record<SpaceType, SyncSocketAdapter> = (client as any)
.affineSyncAdapters;
if (!adapters) {
const workspace = new WorkspaceSyncAdapter(
client,
this.workspace,
this.permissions
);
const userspace = new UserspaceSyncAdapter(client, this.userspace);
adapters = { workspace, userspace };
(client as any).affineSyncAdapters = adapters;
}
return adapters[spaceType];
}
async assertVersion(client: Socket, version?: string) {
const shouldCheckClientVersion = await this.config.runtime.fetch(
'flags/syncClientVersionCheck'
);
if (
// @todo(@darkskygit): remove this flag after 0.12 goes stable
shouldCheckClientVersion &&
version !== AFFiNE.version
) {
client.emit('server-version-rejected', {
currentVersion: version,
requiredVersion: AFFiNE.version,
reason: `Client version${
version ? ` ${version}` : ''
} is outdated, please update to ${AFFiNE.version}`,
});
throw new VersionRejected({
version: version || 'unknown',
serverVersion: AFFiNE.version,
});
}
}
async joinWorkspace(
client: Socket,
room: `${string}:${'sync' | 'awareness'}`
) {
await client.join(room);
}
async leaveWorkspace(
client: Socket,
room: `${string}:${'sync' | 'awareness'}`
) {
await client.leave(room);
}
assertInWorkspace(client: Socket, room: `${string}:${'sync' | 'awareness'}`) {
if (!client.rooms.has(room)) {
throw new NotInSpace({ spaceId: room.split(':')[0] });
}
}
// v3
@SubscribeMessage('space:join')
async onJoinSpace(
@CurrentUser() user: CurrentUser,
@ConnectedSocket() client: Socket,
@MessageBody()
{ spaceType, spaceId, clientVersion }: JoinSpaceMessage
): Promise<EventResponse<{ clientId: string; success: true }>> {
await this.assertVersion(client, clientVersion);
await this.selectAdapter(client, spaceType).join(user.id, spaceId);
return { data: { clientId: client.id, success: true } };
}
@SubscribeMessage('space:leave')
async onLeaveSpace(
@ConnectedSocket() client: Socket,
@MessageBody() { spaceType, spaceId }: LeaveSpaceMessage
): Promise<EventResponse<{ clientId: string; success: true }>> {
await this.selectAdapter(client, spaceType).leave(spaceId);
return { data: { clientId: client.id, success: true } };
}
@SubscribeMessage('space:load-doc')
async onLoadSpaceDoc(
@ConnectedSocket() client: Socket,
@MessageBody()
{ spaceType, spaceId, docId, stateVector }: LoadDocMessage
): Promise<
EventResponse<{ missing: string; state?: string; timestamp: number }>
> {
const adapter = this.selectAdapter(client, spaceType);
adapter.assertIn(spaceId);
const doc = await adapter.get(spaceId, docId);
if (!doc) {
throw new DocNotFound({ spaceId, docId });
}
const missing = Buffer.from(
stateVector
? diffUpdate(doc.bin, Buffer.from(stateVector, 'base64'))
: doc.bin
).toString('base64');
const state = Buffer.from(encodeStateVectorFromUpdate(doc.bin)).toString(
'base64'
);
return {
data: {
missing,
state,
timestamp: doc.timestamp,
},
};
}
@SubscribeMessage('space:push-doc-updates')
async onReceiveDocUpdates(
@ConnectedSocket() client: Socket,
@CurrentUser() user: CurrentUser,
@MessageBody()
message: PushDocUpdatesMessage
): Promise<EventResponse<{ accepted: true; timestamp?: number }>> {
const { spaceType, spaceId, docId, updates } = message;
const adapter = this.selectAdapter(client, spaceType);
// TODO(@forehalo): we might need to check write permission before push updates
const timestamp = await adapter.push(
spaceId,
docId,
updates.map(update => Buffer.from(update, 'base64')),
user.id
);
// could be put in [adapter.push]
// but the event should be kept away from adapter
// so
client
.to(adapter.room(spaceId))
.emit('space:broadcast-doc-updates', { ...message, timestamp });
// TODO(@forehalo): remove backward compatibility
if (spaceType === SpaceType.Workspace) {
const id = new DocID(docId, spaceId);
client.to(adapter.room(spaceId)).emit('server-updates', {
workspaceId: spaceId,
guid: id.guid,
updates,
timestamp,
});
}
return {
data: {
accepted: true,
timestamp,
},
};
}
@SubscribeMessage('space:load-doc-timestamps')
async onLoadDocTimestamps(
@ConnectedSocket() client: Socket,
@MessageBody()
{ spaceType, spaceId, timestamp }: LoadDocTimestampsMessage
): Promise<EventResponse<Record<string, number>>> {
const adapter = this.selectAdapter(client, spaceType);
const stats = await adapter.getTimestamps(spaceId, timestamp);
return {
data: stats ?? {},
};
}
@SubscribeMessage('space:join-awareness')
async onJoinAwareness(
@ConnectedSocket() client: Socket,
@CurrentUser() user: CurrentUser,
@MessageBody()
{ spaceType, spaceId, docId, clientVersion }: JoinSpaceAwarenessMessage
) {
await this.assertVersion(client, clientVersion);
await this.selectAdapter(client, spaceType).join(
user.id,
spaceId,
`${docId}:awareness`
);
return { data: { clientId: client.id, success: true } };
}
@SubscribeMessage('space:leave-awareness')
async onLeaveAwareness(
@ConnectedSocket() client: Socket,
@MessageBody()
{ spaceType, spaceId, docId }: LeaveSpaceAwarenessMessage
) {
await this.selectAdapter(client, spaceType).leave(
spaceId,
`${docId}:awareness`
);
return { data: { clientId: client.id, success: true } };
}
@SubscribeMessage('space:load-awarenesses')
async onLoadAwareness(
@ConnectedSocket() client: Socket,
@MessageBody()
{ spaceType, spaceId, docId }: LoadSpaceAwarenessesMessage
) {
const adapter = this.selectAdapter(client, spaceType);
const roomType = `${docId}:awareness` as const;
adapter.assertIn(spaceId, roomType);
client
.to(adapter.room(spaceId, roomType))
.emit('space:collect-awareness', { spaceType, spaceId, docId });
// TODO(@forehalo): remove backward compatibility
if (spaceType === SpaceType.Workspace) {
client
.to(adapter.room(spaceId, roomType))
.emit('new-client-awareness-init');
}
return { data: { clientId: client.id } };
}
@SubscribeMessage('space:update-awareness')
async onUpdateAwareness(
@ConnectedSocket() client: Socket,
@MessageBody() message: UpdateAwarenessMessage
) {
const { spaceType, spaceId, docId } = message;
const adapter = this.selectAdapter(client, spaceType);
const roomType = `${docId}:awareness` as const;
adapter.assertIn(spaceId, roomType);
client
.to(adapter.room(spaceId, roomType))
.emit('space:broadcast-awareness-update', message);
// TODO(@forehalo): remove backward compatibility
if (spaceType === SpaceType.Workspace) {
client
.to(adapter.room(spaceId, roomType))
.emit('server-awareness-broadcast', {
workspaceId: spaceId,
awarenessUpdate: message.awarenessUpdate,
});
}
return {};
}
// TODO(@forehalo): remove
// deprecated section
@SubscribeMessage('client-handshake-sync')
async handleClientHandshakeSync(
@CurrentUser() user: CurrentUser,
@MessageBody('workspaceId') workspaceId: string,
@MessageBody('version') version: string,
@ConnectedSocket() client: Socket
): Promise<EventResponse<{ clientId: string }>> {
await this.assertVersion(client, version);
return this.onJoinSpace(user, client, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
clientVersion: version,
});
}
@SubscribeMessage('client-leave-sync')
async handleLeaveSync(
@MessageBody() workspaceId: string,
@ConnectedSocket() client: Socket
): Promise<EventResponse> {
return this.onLeaveSpace(client, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
});
}
@SubscribeMessage('client-pre-sync')
async loadDocStats(
@ConnectedSocket() client: Socket,
@MessageBody()
{ workspaceId, timestamp }: { workspaceId: string; timestamp?: number }
): Promise<EventResponse<Record<string, number>>> {
return this.onLoadDocTimestamps(client, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
timestamp,
});
}
@SubscribeMessage('client-update-v2')
async handleClientUpdateV2(
@CurrentUser() user: CurrentUser,
@MessageBody()
{
workspaceId,
guid,
updates,
}: {
workspaceId: string;
guid: string;
updates: string[];
},
@ConnectedSocket() client: Socket
): Promise<EventResponse<{ accepted: true; timestamp?: number }>> {
return this.onReceiveDocUpdates(client, user, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
docId: guid,
updates,
});
}
@SubscribeMessage('doc-load-v2')
async loadDocV2(
@ConnectedSocket() client: Socket,
@MessageBody()
{
workspaceId,
guid,
stateVector,
}: {
workspaceId: string;
guid: string;
stateVector?: string;
}
): Promise<
EventResponse<{ missing: string; state?: string; timestamp: number }>
> {
return this.onLoadSpaceDoc(client, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
docId: guid,
stateVector,
});
}
@SubscribeMessage('client-handshake-awareness')
async handleClientHandshakeAwareness(
@ConnectedSocket() client: Socket,
@CurrentUser() user: CurrentUser,
@MessageBody('workspaceId') workspaceId: string,
@MessageBody('version') version: string
): Promise<EventResponse<{ clientId: string }>> {
return this.onJoinAwareness(client, user, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
docId: workspaceId,
clientVersion: version,
});
}
@SubscribeMessage('client-leave-awareness')
async handleLeaveAwareness(
@MessageBody() workspaceId: string,
@ConnectedSocket() client: Socket
): Promise<EventResponse> {
return this.onLeaveAwareness(client, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
docId: workspaceId,
});
}
@SubscribeMessage('awareness-init')
async handleInitAwareness(
@MessageBody() workspaceId: string,
@ConnectedSocket() client: Socket
): Promise<EventResponse<{ clientId: string }>> {
return this.onLoadAwareness(client, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
docId: workspaceId,
});
}
@SubscribeMessage('awareness-update')
async handleHelpGatheringAwareness(
@MessageBody()
{
workspaceId,
awarenessUpdate,
}: { workspaceId: string; awarenessUpdate: string },
@ConnectedSocket() client: Socket
): Promise<EventResponse> {
return this.onUpdateAwareness(client, {
spaceType: SpaceType.Workspace,
spaceId: workspaceId,
docId: workspaceId,
awarenessUpdate,
});
}
}
abstract class SyncSocketAdapter {
constructor(
private readonly spaceType: SpaceType,
public readonly client: Socket,
public readonly storage: DocStorageAdapter
) {}
room(spaceId: string, roomType: RoomType = 'sync') {
return `${this.spaceType}:${Room(spaceId, roomType)}`;
}
async join(userId: string, spaceId: string, roomType: RoomType = 'sync') {
this.assertNotIn(spaceId, roomType);
await this.assertAccessible(spaceId, userId, Permission.Read);
return this.client.join(this.room(spaceId, roomType));
}
async leave(spaceId: string, roomType: RoomType = 'sync') {
this.assertIn(spaceId, roomType);
return this.client.leave(this.room(spaceId, roomType));
}
in(spaceId: string, roomType: RoomType = 'sync') {
return this.client.rooms.has(this.room(spaceId, roomType));
}
assertNotIn(spaceId: string, roomType: RoomType = 'sync') {
if (this.client.rooms.has(this.room(spaceId, roomType))) {
throw new AlreadyInSpace({ spaceId });
}
}
assertIn(spaceId: string, roomType: RoomType = 'sync') {
if (!this.client.rooms.has(this.room(spaceId, roomType))) {
throw new NotInSpace({ spaceId });
}
}
abstract assertAccessible(
spaceId: string,
userId: string,
permission?: Permission
): Promise<void>;
push(spaceId: string, docId: string, updates: Buffer[], editorId: string) {
this.assertIn(spaceId);
return this.storage.pushDocUpdates(spaceId, docId, updates, editorId);
}
get(spaceId: string, docId: string) {
this.assertIn(spaceId);
return this.storage.getDoc(spaceId, docId);
}
getTimestamps(spaceId: string, timestamp?: number) {
this.assertIn(spaceId);
return this.storage.getSpaceDocTimestamps(spaceId, timestamp);
}
}
class WorkspaceSyncAdapter extends SyncSocketAdapter {
constructor(
client: Socket,
storage: DocStorageAdapter,
private readonly permission: PermissionService
) {
super(SpaceType.Workspace, client, storage);
}
override push(
spaceId: string,
docId: string,
updates: Buffer[],
editorId: string
) {
const id = new DocID(docId, spaceId);
return super.push(spaceId, id.guid, updates, editorId);
}
override get(spaceId: string, docId: string) {
const id = new DocID(docId, spaceId);
return this.storage.getDoc(spaceId, id.guid);
}
async assertAccessible(
spaceId: string,
userId: string,
permission: Permission = Permission.Read
) {
if (
!(await this.permission.isWorkspaceMember(spaceId, userId, permission))
) {
throw new SpaceAccessDenied({ spaceId });
}
}
}
class UserspaceSyncAdapter extends SyncSocketAdapter {
constructor(client: Socket, storage: DocStorageAdapter) {
super(SpaceType.Userspace, client, storage);
}
async assertAccessible(
spaceId: string,
userId: string,
_permission: Permission = Permission.Read
) {
if (spaceId !== userId) {
throw new SpaceAccessDenied({ spaceId });
}
}
}

View File

@@ -1,8 +1,11 @@
import { Module } from '@nestjs/common';
import { EventsModule } from './events/events.module';
import { DocStorageModule } from '../doc';
import { PermissionModule } from '../permission';
import { SpaceSyncGateway } from './gateway';
@Module({
imports: [EventsModule],
imports: [DocStorageModule, PermissionModule],
providers: [SpaceSyncGateway],
})
export class SyncModule {}

View File

@@ -18,9 +18,9 @@ import {
Throttle,
UserNotFound,
} from '../../fundamentals';
import { CurrentUser } from '../auth/current-user';
import { Public } from '../auth/guard';
import { sessionUser } from '../auth/service';
import { CurrentUser } from '../auth/session';
import { Admin } from '../common';
import { AvatarStorage } from '../storage';
import { validators } from '../utils/validators';

View File

@@ -56,11 +56,6 @@ export class UserService {
async createUser(data: CreateUserInput) {
validators.assertValidEmail(data.email);
const user = await this.findUserByEmail(data.email);
if (user) {
throw new EmailAlreadyUsed();
}
if (data.password) {
const config = await this.config.runtime.fetchAll({
@@ -77,6 +72,12 @@ export class UserService {
}
async createUser_without_verification(data: CreateUserInput) {
const user = await this.findUserByEmail(data.email);
if (user) {
throw new EmailAlreadyUsed();
}
if (data.password) {
data.password = await this.crypto.encryptPassword(data.password);
}
@@ -158,9 +159,7 @@ export class UserService {
async fulfillUser(
email: string,
data: Partial<
Pick<Prisma.UserCreateInput, 'emailVerifiedAt' | 'registered'>
>
data: Omit<Partial<Prisma.UserCreateInput>, 'id'>
) {
const user = await this.findUserByEmail(email);
if (!user) {
@@ -180,7 +179,6 @@ export class UserService {
if (Object.keys(data).length) {
return await this.prisma.user.update({
select: this.defaultUserSelect,
where: { id: user.id },
data,
});

View File

@@ -8,7 +8,7 @@ import {
import type { User } from '@prisma/client';
import type { Payload } from '../../fundamentals/event/def';
import { CurrentUser } from '../auth/current-user';
import { type CurrentUser } from '../auth/session';
@ObjectType()
export class UserType implements CurrentUser {

View File

@@ -21,7 +21,7 @@ export class DocID {
static parse(raw: string): DocID | null {
try {
return new DocID(raw);
} catch (e) {
} catch {
return null;
}
}

View File

@@ -12,11 +12,10 @@ import {
InvalidHistoryTimestamp,
} from '../../fundamentals';
import { CurrentUser, Public } from '../auth';
import { DocHistoryManager, DocManager } from '../doc';
import { PgWorkspaceDocStorageAdapter } from '../doc';
import { Permission, PermissionService, PublicPageMode } from '../permission';
import { WorkspaceBlobStorage } from '../storage';
import { DocID } from '../utils/doc';
import { PermissionService, PublicPageMode } from './permission';
import { Permission } from './types';
@Controller('/api/workspaces')
export class WorkspacesController {
@@ -24,8 +23,7 @@ export class WorkspacesController {
constructor(
private readonly storage: WorkspaceBlobStorage,
private readonly permission: PermissionService,
private readonly docManager: DocManager,
private readonly historyManager: DocHistoryManager,
private readonly workspace: PgWorkspaceDocStorageAdapter,
private readonly prisma: PrismaClient
) {}
@@ -57,7 +55,7 @@ export class WorkspacesController {
if (!body) {
throw new BlobNotFound({
workspaceId,
spaceId: workspaceId,
blobId: name,
});
}
@@ -97,14 +95,14 @@ export class WorkspacesController {
throw new AccessDenied();
}
const binResponse = await this.docManager.getBinary(
const binResponse = await this.workspace.getDoc(
docId.workspace,
docId.guid
);
if (!binResponse) {
throw new DocNotFound({
workspaceId: docId.workspace,
spaceId: docId.workspace,
docId: docId.guid,
});
}
@@ -126,7 +124,7 @@ export class WorkspacesController {
}
res.setHeader('content-type', 'application/octet-stream');
res.send(binResponse.binary);
res.send(binResponse.bin);
}
@Get('/:id/docs/:guid/histories/:timestamp')
@@ -142,7 +140,7 @@ export class WorkspacesController {
let ts;
try {
ts = new Date(timestamp);
} catch (e) {
} catch {
throw new InvalidHistoryTimestamp({ timestamp });
}
@@ -153,19 +151,19 @@ export class WorkspacesController {
Permission.Write
);
const history = await this.historyManager.get(
const history = await this.workspace.getDocHistory(
docId.workspace,
docId.guid,
ts
ts.getTime()
);
if (history) {
res.setHeader('content-type', 'application/octet-stream');
res.setHeader('cache-control', 'private, max-age=2592000, immutable');
res.send(history.blob);
res.send(history.bin);
} else {
throw new DocHistoryNotFound({
workspaceId: docId.workspace,
spaceId: docId.workspace,
docId: guid,
timestamp: ts.getTime(),
});

View File

@@ -1,13 +1,13 @@
import { Module } from '@nestjs/common';
import { DocModule } from '../doc';
import { DocStorageModule } from '../doc';
import { FeatureModule } from '../features';
import { PermissionModule } from '../permission';
import { QuotaModule } from '../quota';
import { StorageModule } from '../storage';
import { UserModule } from '../user';
import { WorkspacesController } from './controller';
import { WorkspaceManagementResolver } from './management';
import { PermissionService } from './permission';
import {
DocHistoryResolver,
PagePermissionResolver,
@@ -16,17 +16,22 @@ import {
} from './resolvers';
@Module({
imports: [DocModule, FeatureModule, QuotaModule, StorageModule, UserModule],
imports: [
DocStorageModule,
FeatureModule,
QuotaModule,
StorageModule,
UserModule,
PermissionModule,
],
controllers: [WorkspacesController],
providers: [
WorkspaceResolver,
WorkspaceManagementResolver,
PermissionService,
PagePermissionResolver,
DocHistoryResolver,
WorkspaceBlobResolver,
],
exports: [PermissionService],
})
export class WorkspaceModule {}

View File

@@ -12,7 +12,7 @@ import { ActionForbidden } from '../../fundamentals';
import { CurrentUser } from '../auth';
import { Admin } from '../common';
import { FeatureManagementService, FeatureType } from '../features';
import { PermissionService } from './permission';
import { PermissionService } from '../permission';
import { WorkspaceType } from './types';
@Resolver(() => WorkspaceType)
@@ -61,7 +61,7 @@ export class WorkspaceManagementResolver {
const owner = await this.permission.getWorkspaceOwner(workspaceId);
const availableFeatures = await this.availableFeatures(user);
if (owner.user.id !== user.id || !availableFeatures.includes(feature)) {
if (owner.id !== user.id || !availableFeatures.includes(feature)) {
throw new ActionForbidden();
}

View File

@@ -19,10 +19,10 @@ import {
PreventCache,
} from '../../../fundamentals';
import { CurrentUser } from '../../auth';
import { Permission, PermissionService } from '../../permission';
import { QuotaManagementService } from '../../quota';
import { WorkspaceBlobStorage } from '../../storage';
import { PermissionService } from '../permission';
import { Permission, WorkspaceBlobSizes, WorkspaceType } from '../types';
import { WorkspaceBlobSizes, WorkspaceType } from '../types';
@UseGuards(CloudThrottlerGuard)
@Resolver(() => WorkspaceType)

View File

@@ -12,10 +12,11 @@ import {
import type { SnapshotHistory } from '@prisma/client';
import { CurrentUser } from '../../auth';
import { DocHistoryManager } from '../../doc';
import { PgWorkspaceDocStorageAdapter } from '../../doc';
import { Permission, PermissionService } from '../../permission';
import { DocID } from '../../utils/doc';
import { PermissionService } from '../permission';
import { Permission, WorkspaceType } from '../types';
import { WorkspaceType } from '../types';
import { EditorType } from './workspace';
@ObjectType()
class DocHistoryType implements Partial<SnapshotHistory> {
@@ -27,12 +28,15 @@ class DocHistoryType implements Partial<SnapshotHistory> {
@Field(() => GraphQLISODateTime)
timestamp!: Date;
@Field(() => EditorType, { nullable: true })
editor!: EditorType | null;
}
@Resolver(() => WorkspaceType)
export class DocHistoryResolver {
constructor(
private readonly historyManager: DocHistoryManager,
private readonly workspace: PgWorkspaceDocStorageAdapter,
private readonly permission: PermissionService
) {}
@@ -47,17 +51,20 @@ export class DocHistoryResolver {
): Promise<DocHistoryType[]> {
const docId = new DocID(guid, workspace.id);
return this.historyManager
.list(workspace.id, docId.guid, timestamp, take)
.then(rows =>
rows.map(({ timestamp }) => {
return {
workspaceId: workspace.id,
id: docId.guid,
timestamp,
};
})
);
const histories = await this.workspace.listDocHistories(
workspace.id,
docId.guid,
{ before: timestamp.getTime(), limit: take }
);
return histories.map(history => {
return {
workspaceId: workspace.id,
id: docId.guid,
timestamp: new Date(history.timestamp),
editor: history.editor,
};
});
}
@Mutation(() => Date)
@@ -76,6 +83,13 @@ export class DocHistoryResolver {
Permission.Write
);
return this.historyManager.recover(docId.workspace, docId.guid, timestamp);
await this.workspace.rollbackDoc(
docId.workspace,
docId.guid,
timestamp.getTime(),
user.id
);
return timestamp;
}
}

View File

@@ -17,9 +17,13 @@ import {
PageIsNotPublic,
} from '../../../fundamentals';
import { CurrentUser } from '../../auth';
import {
Permission,
PermissionService,
PublicPageMode,
} from '../../permission';
import { DocID } from '../../utils/doc';
import { PermissionService, PublicPageMode } from '../permission';
import { Permission, WorkspaceType } from '../types';
import { WorkspaceType } from '../types';
registerEnumType(PublicPageMode, {
name: 'PublicPageMode',

View File

@@ -1,8 +1,10 @@
import { Logger } from '@nestjs/common';
import {
Args,
Field,
Int,
Mutation,
ObjectType,
Parent,
Query,
ResolveField,
@@ -15,33 +17,57 @@ import { applyUpdate, Doc } from 'yjs';
import type { FileUpload } from '../../../fundamentals';
import {
CantChangeWorkspaceOwner,
CantChangeSpaceOwner,
DocNotFound,
EventEmitter,
InternalServerError,
MailService,
MemberQuotaExceeded,
MutexService,
RequestMutex,
SpaceAccessDenied,
SpaceNotFound,
Throttle,
TooManyRequest,
UserNotFound,
WorkspaceAccessDenied,
WorkspaceNotFound,
WorkspaceOwnerNotFound,
} from '../../../fundamentals';
import { CurrentUser, Public } from '../../auth';
import type { Editor } from '../../doc';
import { Permission, PermissionService } from '../../permission';
import { QuotaManagementService, QuotaQueryType } from '../../quota';
import { WorkspaceBlobStorage } from '../../storage';
import { UserService, UserType } from '../../user';
import { PermissionService } from '../permission';
import {
InvitationType,
InviteUserType,
Permission,
UpdateWorkspaceInput,
WorkspaceType,
} from '../types';
import { defaultWorkspaceAvatar } from '../utils';
@ObjectType()
export class EditorType implements Partial<Editor> {
@Field()
name!: string;
@Field(() => String, { nullable: true })
avatarUrl!: string | null;
}
@ObjectType()
class WorkspacePageMeta {
@Field(() => Date)
createdAt!: Date;
@Field(() => Date)
updatedAt!: Date;
@Field(() => EditorType, { nullable: true })
createdBy!: EditorType | null;
@Field(() => EditorType, { nullable: true })
updatedBy!: EditorType | null;
}
/**
* Workspace resolver
* Public apis rate limit: 10 req/m
@@ -59,7 +85,7 @@ export class WorkspaceResolver {
private readonly users: UserService,
private readonly event: EventEmitter,
private readonly blobStorage: WorkspaceBlobStorage,
private readonly mutex: MutexService
private readonly mutex: RequestMutex
) {}
@ResolveField(() => Permission, {
@@ -78,7 +104,7 @@ export class WorkspaceResolver {
const permission = await this.permissions.get(workspace.id, user.id);
if (!permission) {
throw new WorkspaceAccessDenied({ workspaceId: workspace.id });
throw new SpaceAccessDenied({ spaceId: workspace.id });
}
return permission;
@@ -89,11 +115,22 @@ export class WorkspaceResolver {
complexity: 2,
})
memberCount(@Parent() workspace: WorkspaceType) {
return this.prisma.workspaceUserPermission.count({
where: {
workspaceId: workspace.id,
},
});
return this.permissions.getWorkspaceMemberCount(workspace.id);
}
@ResolveField(() => Boolean, {
description: 'is current workspace initialized',
complexity: 2,
})
async initialized(@Parent() workspace: WorkspaceType) {
return this.prisma.snapshot
.count({
where: {
id: workspace.id,
workspaceId: workspace.id,
},
})
.then(count => count > 0);
}
@ResolveField(() => UserType, {
@@ -101,9 +138,7 @@ export class WorkspaceResolver {
complexity: 2,
})
async owner(@Parent() workspace: WorkspaceType) {
const data = await this.permissions.getWorkspaceOwner(workspace.id);
return data.user;
return this.permissions.getWorkspaceOwner(workspace.id);
}
@ResolveField(() => [InviteUserType], {
@@ -144,6 +179,35 @@ export class WorkspaceResolver {
}));
}
@ResolveField(() => WorkspacePageMeta, {
description: 'Cloud page metadata of workspace',
complexity: 2,
})
async pageMeta(
@Parent() workspace: WorkspaceType,
@Args('pageId') pageId: string
) {
const metadata = await this.prisma.snapshot.findFirst({
where: { workspaceId: workspace.id, id: pageId },
select: {
createdAt: true,
updatedAt: true,
createdByUser: { select: { name: true, avatarUrl: true } },
updatedByUser: { select: { name: true, avatarUrl: true } },
},
});
if (!metadata) {
throw new DocNotFound({ spaceId: workspace.id, docId: pageId });
}
return {
createdAt: metadata.createdAt,
updatedAt: metadata.updatedAt,
createdBy: metadata.createdByUser || null,
updatedBy: metadata.updatedByUser || null,
};
}
@ResolveField(() => QuotaQueryType, {
name: 'quota',
description: 'quota of workspace',
@@ -197,7 +261,7 @@ export class WorkspaceResolver {
const workspace = await this.prisma.workspace.findUnique({ where: { id } });
if (!workspace) {
throw new WorkspaceNotFound({ workspaceId: id });
throw new SpaceNotFound({ spaceId: id });
}
return workspace;
@@ -308,7 +372,7 @@ export class WorkspaceResolver {
);
if (permission === Permission.Owner) {
throw new CantChangeWorkspaceOwner();
throw new CantChangeSpaceOwner();
}
try {
@@ -320,13 +384,8 @@ export class WorkspaceResolver {
}
// member limit check
const [memberCount, quota] = await Promise.all([
this.prisma.workspaceUserPermission.count({
where: { workspaceId },
}),
this.quota.getWorkspaceUsage(workspaceId),
]);
if (memberCount >= quota.memberLimit) {
const quota = await this.quota.getWorkspaceUsage(workspaceId);
if (quota.memberCount >= quota.memberLimit) {
return new MemberQuotaExceeded();
}
@@ -449,7 +508,7 @@ export class WorkspaceResolver {
avatar: avatar || defaultWorkspaceAvatar,
id: workspaceId,
},
user: owner.user,
user: owner,
invitee: invitee.user,
};
}
@@ -507,12 +566,8 @@ export class WorkspaceResolver {
const owner = await this.permissions.getWorkspaceOwner(workspaceId);
if (!owner.user) {
throw new WorkspaceOwnerNotFound({ workspaceId: workspaceId });
}
if (sendLeaveMail) {
await this.mailer.sendLeaveWorkspaceEmail(owner.user.email, {
await this.mailer.sendLeaveWorkspaceEmail(owner.email, {
workspaceName,
inviteeName: user.name,
});

View File

@@ -11,15 +11,9 @@ import {
import type { Workspace } from '@prisma/client';
import { SafeIntResolver } from 'graphql-scalars';
import { Permission } from '../permission';
import { UserType } from '../user/types';
export enum Permission {
Read = 0,
Write = 1,
Admin = 10,
Owner = 99,
}
registerEnumType(Permission, {
name: 'Permission',
description: 'User permission in workspace',

View File

@@ -1,17 +1,17 @@
import Keyv from 'keyv';
import Keyv, { KeyvOptions } from 'keyv';
import type { Cache, CacheSetOptions } from './def';
export class LocalCache implements Cache {
private readonly kv: Keyv;
constructor(opts: Keyv.Options<any> = {}) {
constructor(opts: KeyvOptions = {}) {
this.kv = new Keyv(opts);
}
// standard operation
async get<T = unknown>(key: string): Promise<T | undefined> {
return this.kv.get(key).catch(() => undefined);
return this.kv.get<T>(key).catch(() => undefined);
}
async set<T = unknown>(
@@ -74,14 +74,14 @@ export class LocalCache implements Cache {
// list operations
private async getArray<T = unknown>(key: string) {
const raw = await this.kv.get(key, { raw: true });
const raw = await this.kv.get<T[]>(key, { raw: true });
if (raw && !Array.isArray(raw.value)) {
throw new Error(
`Expect an Array keyed by ${key}, but found ${raw.value}`
);
}
return raw as Keyv.DeserializedData<T[]>;
return raw;
}
private async setArray<T = unknown>(
@@ -97,7 +97,9 @@ export class LocalCache implements Cache {
let ttl: number | undefined = undefined;
const raw = await this.getArray(key);
if (raw) {
list = raw.value;
if (raw.value) {
list = raw.value;
}
if (raw.expires) {
ttl = raw.expires - Date.now();
}
@@ -112,7 +114,9 @@ export class LocalCache implements Cache {
let ttl: number | undefined = undefined;
const raw = await this.getArray(key);
if (raw) {
list = raw.value;
if (raw.value) {
list = raw.value;
}
if (raw.expires) {
ttl = raw.expires - Date.now();
}
@@ -123,7 +127,7 @@ export class LocalCache implements Cache {
}
async len(key: string): Promise<number> {
return this.getArray(key).then(v => v?.value.length ?? 0);
return this.getArray<any[]>(key).then(v => v?.value?.length ?? 0);
}
/**
@@ -147,7 +151,7 @@ export class LocalCache implements Cache {
private async trim<T = unknown>(key: string, start: number, end: number) {
const raw = await this.getArray<T>(key);
if (raw) {
if (raw && raw.value) {
start = (raw.value.length + start) % raw.value.length;
// make negative end index work, and end indice is inclusive
end = ((raw.value.length + end) % raw.value.length) + 1;
@@ -173,7 +177,7 @@ export class LocalCache implements Cache {
// map operations
private async getMap<T = unknown>(map: string) {
const raw = await this.kv.get(map, { raw: true });
const raw = await this.kv.get<Record<string, T>>(map, { raw: true });
if (raw) {
if (typeof raw.value !== 'object') {
@@ -187,7 +191,7 @@ export class LocalCache implements Cache {
}
}
return raw as Keyv.DeserializedData<Record<string, T>>;
return raw;
}
private async setMap<T = unknown>(
@@ -263,7 +267,7 @@ export class LocalCache implements Cache {
async mapKeys(map: string): Promise<string[]> {
const raw = await this.getMap(map);
if (raw) {
if (raw?.value) {
return Object.keys(raw.value);
}
@@ -277,6 +281,6 @@ export class LocalCache implements Cache {
async mapLen(map: string): Promise<number> {
const raw = await this.getMap(map);
return raw ? Object.keys(raw.value).length : 0;
return raw?.value ? Object.keys(raw.value).length : 0;
}
}

View File

@@ -17,6 +17,7 @@ export interface PreDefinedAFFiNEConfig {
ENV_MAP: Record<string, ConfigPaths | [ConfigPaths, EnvConfigType?]>;
serverId: string;
serverName: string;
readonly projectRoot: string;
readonly AFFINE_ENV: AFFINE_ENV;
readonly NODE_ENV: NODE_ENV;
readonly version: string;

View File

@@ -1,3 +1,6 @@
import { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import pkg from '../../../package.json' assert { type: 'json' };
import {
AFFINE_ENV,
@@ -62,6 +65,7 @@ function getPredefinedAFFiNEConfig(): PreDefinedAFFiNEConfig {
affine,
node,
deploy: !node.dev && !node.test,
projectRoot: resolve(fileURLToPath(import.meta.url), '../../../../'),
};
}

View File

@@ -198,6 +198,10 @@ export const USER_FRIENDLY_ERRORS = {
type: 'too_many_requests',
message: 'Too many requests.',
},
not_found: {
type: 'resource_not_found',
message: 'Resource not found.',
},
// User Errors
user_not_found: {
@@ -279,6 +283,10 @@ export const USER_FRIENDLY_ERRORS = {
type: 'invalid_input',
message: 'An invalid email token provided.',
},
link_expired: {
type: 'bad_request',
message: 'The link has expired.',
},
// Authentication & Permission Errors
authentication_required: {
@@ -298,45 +306,49 @@ export const USER_FRIENDLY_ERRORS = {
message: 'You must verify your email before accessing this resource.',
},
// Workspace & Doc & Sync errors
workspace_not_found: {
// Workspace & Userspace & Doc & Sync errors
space_not_found: {
type: 'resource_not_found',
args: { workspaceId: 'string' },
message: ({ workspaceId }) => `Workspace ${workspaceId} not found.`,
args: { spaceId: 'string' },
message: ({ spaceId }) => `Space ${spaceId} not found.`,
},
not_in_workspace: {
not_in_space: {
type: 'action_forbidden',
args: { workspaceId: 'string' },
message: ({ workspaceId }) =>
`You should join in workspace ${workspaceId} before broadcasting messages.`,
args: { spaceId: 'string' },
message: ({ spaceId }) =>
`You should join in Space ${spaceId} before broadcasting messages.`,
},
workspace_access_denied: {
already_in_space: {
type: 'action_forbidden',
args: { spaceId: 'string' },
message: ({ spaceId }) => `You have already joined in Space ${spaceId}.`,
},
space_access_denied: {
type: 'no_permission',
args: { workspaceId: 'string' },
message: ({ workspaceId }) =>
`You do not have permission to access workspace ${workspaceId}.`,
args: { spaceId: 'string' },
message: ({ spaceId }) =>
`You do not have permission to access Space ${spaceId}.`,
},
workspace_owner_not_found: {
space_owner_not_found: {
type: 'internal_server_error',
args: { workspaceId: 'string' },
message: ({ workspaceId }) =>
`Owner of workspace ${workspaceId} not found.`,
args: { spaceId: 'string' },
message: ({ spaceId }) => `Owner of Space ${spaceId} not found.`,
},
cant_change_workspace_owner: {
cant_change_space_owner: {
type: 'action_forbidden',
message: 'You are not allowed to change the owner of a workspace.',
message: 'You are not allowed to change the owner of a Space.',
},
doc_not_found: {
type: 'resource_not_found',
args: { workspaceId: 'string', docId: 'string' },
message: ({ workspaceId, docId }) =>
`Doc ${docId} under workspace ${workspaceId} not found.`,
args: { spaceId: 'string', docId: 'string' },
message: ({ spaceId, docId }) =>
`Doc ${docId} under Space ${spaceId} not found.`,
},
doc_access_denied: {
type: 'no_permission',
args: { workspaceId: 'string', docId: 'string' },
message: ({ workspaceId, docId }) =>
`You do not have permission to access doc ${docId} under workspace ${workspaceId}.`,
args: { spaceId: 'string', docId: 'string' },
message: ({ spaceId, docId }) =>
`You do not have permission to access doc ${docId} under Space ${spaceId}.`,
},
version_rejected: {
type: 'action_forbidden',
@@ -351,28 +363,36 @@ export const USER_FRIENDLY_ERRORS = {
},
doc_history_not_found: {
type: 'resource_not_found',
args: { workspaceId: 'string', docId: 'string', timestamp: 'number' },
message: ({ workspaceId, docId, timestamp }) =>
`History of ${docId} at ${timestamp} under workspace ${workspaceId}.`,
args: { spaceId: 'string', docId: 'string', timestamp: 'number' },
message: ({ spaceId, docId, timestamp }) =>
`History of ${docId} at ${timestamp} under Space ${spaceId}.`,
},
blob_not_found: {
type: 'resource_not_found',
args: { workspaceId: 'string', blobId: 'string' },
message: ({ workspaceId, blobId }) =>
`Blob ${blobId} not found in workspace ${workspaceId}.`,
args: { spaceId: 'string', blobId: 'string' },
message: ({ spaceId, blobId }) =>
`Blob ${blobId} not found in Space ${spaceId}.`,
},
expect_to_publish_page: {
type: 'invalid_input',
message: 'Expected to publish a page, not a workspace.',
message: 'Expected to publish a page, not a Space.',
},
expect_to_revoke_public_page: {
type: 'invalid_input',
message: 'Expected to revoke a public page, not a workspace.',
message: 'Expected to revoke a public page, not a Space.',
},
page_is_not_public: {
type: 'bad_request',
message: 'Page is not public.',
},
failed_to_save_updates: {
type: 'internal_server_error',
message: 'Failed to store doc updates.',
},
failed_to_upsert_snapshot: {
type: 'internal_server_error',
message: 'Failed to store doc snapshot.',
},
// Subscription Errors
failed_to_checkout: {
@@ -506,4 +526,10 @@ export const USER_FRIENDLY_ERRORS = {
type: 'action_forbidden',
message: 'Cannot delete own account.',
},
// captcha errors
captcha_verification_failed: {
type: 'bad_request',
message: 'Captcha verification failed.',
},
} satisfies Record<string, UserFriendlyErrorOptions>;

View File

@@ -16,6 +16,12 @@ export class TooManyRequest extends UserFriendlyError {
}
}
export class NotFound extends UserFriendlyError {
constructor(message?: string) {
super('resource_not_found', 'not_found', message);
}
}
export class UserNotFound extends UserFriendlyError {
constructor(message?: string) {
super('resource_not_found', 'user_not_found', message);
@@ -137,6 +143,12 @@ export class InvalidEmailToken extends UserFriendlyError {
}
}
export class LinkExpired extends UserFriendlyError {
constructor(message?: string) {
super('bad_request', 'link_expired', message);
}
}
export class AuthenticationRequired extends UserFriendlyError {
constructor(message?: string) {
super('authentication_required', 'authentication_required', message);
@@ -161,54 +173,64 @@ export class EmailVerificationRequired extends UserFriendlyError {
}
}
@ObjectType()
class WorkspaceNotFoundDataType {
@Field() workspaceId!: string
class SpaceNotFoundDataType {
@Field() spaceId!: string
}
export class WorkspaceNotFound extends UserFriendlyError {
constructor(args: WorkspaceNotFoundDataType, message?: string | ((args: WorkspaceNotFoundDataType) => string)) {
super('resource_not_found', 'workspace_not_found', message, args);
export class SpaceNotFound extends UserFriendlyError {
constructor(args: SpaceNotFoundDataType, message?: string | ((args: SpaceNotFoundDataType) => string)) {
super('resource_not_found', 'space_not_found', message, args);
}
}
@ObjectType()
class NotInWorkspaceDataType {
@Field() workspaceId!: string
class NotInSpaceDataType {
@Field() spaceId!: string
}
export class NotInWorkspace extends UserFriendlyError {
constructor(args: NotInWorkspaceDataType, message?: string | ((args: NotInWorkspaceDataType) => string)) {
super('action_forbidden', 'not_in_workspace', message, args);
export class NotInSpace extends UserFriendlyError {
constructor(args: NotInSpaceDataType, message?: string | ((args: NotInSpaceDataType) => string)) {
super('action_forbidden', 'not_in_space', message, args);
}
}
@ObjectType()
class WorkspaceAccessDeniedDataType {
@Field() workspaceId!: string
class AlreadyInSpaceDataType {
@Field() spaceId!: string
}
export class WorkspaceAccessDenied extends UserFriendlyError {
constructor(args: WorkspaceAccessDeniedDataType, message?: string | ((args: WorkspaceAccessDeniedDataType) => string)) {
super('no_permission', 'workspace_access_denied', message, args);
export class AlreadyInSpace extends UserFriendlyError {
constructor(args: AlreadyInSpaceDataType, message?: string | ((args: AlreadyInSpaceDataType) => string)) {
super('action_forbidden', 'already_in_space', message, args);
}
}
@ObjectType()
class WorkspaceOwnerNotFoundDataType {
@Field() workspaceId!: string
class SpaceAccessDeniedDataType {
@Field() spaceId!: string
}
export class WorkspaceOwnerNotFound extends UserFriendlyError {
constructor(args: WorkspaceOwnerNotFoundDataType, message?: string | ((args: WorkspaceOwnerNotFoundDataType) => string)) {
super('internal_server_error', 'workspace_owner_not_found', message, args);
export class SpaceAccessDenied extends UserFriendlyError {
constructor(args: SpaceAccessDeniedDataType, message?: string | ((args: SpaceAccessDeniedDataType) => string)) {
super('no_permission', 'space_access_denied', message, args);
}
}
@ObjectType()
class SpaceOwnerNotFoundDataType {
@Field() spaceId!: string
}
export class SpaceOwnerNotFound extends UserFriendlyError {
constructor(args: SpaceOwnerNotFoundDataType, message?: string | ((args: SpaceOwnerNotFoundDataType) => string)) {
super('internal_server_error', 'space_owner_not_found', message, args);
}
}
export class CantChangeWorkspaceOwner extends UserFriendlyError {
export class CantChangeSpaceOwner extends UserFriendlyError {
constructor(message?: string) {
super('action_forbidden', 'cant_change_workspace_owner', message);
super('action_forbidden', 'cant_change_space_owner', message);
}
}
@ObjectType()
class DocNotFoundDataType {
@Field() workspaceId!: string
@Field() spaceId!: string
@Field() docId!: string
}
@@ -219,7 +241,7 @@ export class DocNotFound extends UserFriendlyError {
}
@ObjectType()
class DocAccessDeniedDataType {
@Field() workspaceId!: string
@Field() spaceId!: string
@Field() docId!: string
}
@@ -251,7 +273,7 @@ export class InvalidHistoryTimestamp extends UserFriendlyError {
}
@ObjectType()
class DocHistoryNotFoundDataType {
@Field() workspaceId!: string
@Field() spaceId!: string
@Field() docId!: string
@Field() timestamp!: number
}
@@ -263,7 +285,7 @@ export class DocHistoryNotFound extends UserFriendlyError {
}
@ObjectType()
class BlobNotFoundDataType {
@Field() workspaceId!: string
@Field() spaceId!: string
@Field() blobId!: string
}
@@ -291,6 +313,18 @@ export class PageIsNotPublic extends UserFriendlyError {
}
}
export class FailedToSaveUpdates extends UserFriendlyError {
constructor(message?: string) {
super('internal_server_error', 'failed_to_save_updates', message);
}
}
export class FailedToUpsertSnapshot extends UserFriendlyError {
constructor(message?: string) {
super('internal_server_error', 'failed_to_upsert_snapshot', message);
}
}
export class FailedToCheckout extends UserFriendlyError {
constructor(message?: string) {
super('internal_server_error', 'failed_to_checkout', message);
@@ -499,9 +533,16 @@ export class CannotDeleteOwnAccount extends UserFriendlyError {
super('action_forbidden', 'cannot_delete_own_account', message);
}
}
export class CaptchaVerificationFailed extends UserFriendlyError {
constructor(message?: string) {
super('bad_request', 'captcha_verification_failed', message);
}
}
export enum ErrorNames {
INTERNAL_SERVER_ERROR,
TOO_MANY_REQUEST,
NOT_FOUND,
USER_NOT_FOUND,
USER_AVATAR_NOT_FOUND,
EMAIL_ALREADY_USED,
@@ -520,15 +561,17 @@ export enum ErrorNames {
SIGN_UP_FORBIDDEN,
EMAIL_TOKEN_NOT_FOUND,
INVALID_EMAIL_TOKEN,
LINK_EXPIRED,
AUTHENTICATION_REQUIRED,
ACTION_FORBIDDEN,
ACCESS_DENIED,
EMAIL_VERIFICATION_REQUIRED,
WORKSPACE_NOT_FOUND,
NOT_IN_WORKSPACE,
WORKSPACE_ACCESS_DENIED,
WORKSPACE_OWNER_NOT_FOUND,
CANT_CHANGE_WORKSPACE_OWNER,
SPACE_NOT_FOUND,
NOT_IN_SPACE,
ALREADY_IN_SPACE,
SPACE_ACCESS_DENIED,
SPACE_OWNER_NOT_FOUND,
CANT_CHANGE_SPACE_OWNER,
DOC_NOT_FOUND,
DOC_ACCESS_DENIED,
VERSION_REJECTED,
@@ -538,6 +581,8 @@ export enum ErrorNames {
EXPECT_TO_PUBLISH_PAGE,
EXPECT_TO_REVOKE_PUBLIC_PAGE,
PAGE_IS_NOT_PUBLIC,
FAILED_TO_SAVE_UPDATES,
FAILED_TO_UPSERT_SNAPSHOT,
FAILED_TO_CHECKOUT,
SUBSCRIPTION_ALREADY_EXISTS,
SUBSCRIPTION_NOT_EXISTS,
@@ -565,7 +610,8 @@ export enum ErrorNames {
INVALID_RUNTIME_CONFIG_TYPE,
MAILER_SERVICE_IS_NOT_CONFIGURED,
CANNOT_DELETE_ALL_ADMIN_ACCOUNT,
CANNOT_DELETE_OWN_ACCOUNT
CANNOT_DELETE_OWN_ACCOUNT,
CAPTCHA_VERIFICATION_FAILED
}
registerEnumType(ErrorNames, {
name: 'ErrorNames'
@@ -574,5 +620,5 @@ registerEnumType(ErrorNames, {
export const ErrorDataUnionType = createUnionType({
name: 'ErrorDataUnion',
types: () =>
[UnknownOauthProviderDataType, MissingOauthQueryParameterDataType, InvalidPasswordLengthDataType, WorkspaceNotFoundDataType, NotInWorkspaceDataType, WorkspaceAccessDeniedDataType, WorkspaceOwnerNotFoundDataType, DocNotFoundDataType, DocAccessDeniedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderSideErrorDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType] as const,
[UnknownOauthProviderDataType, MissingOauthQueryParameterDataType, InvalidPasswordLengthDataType, SpaceNotFoundDataType, NotInSpaceDataType, AlreadyInSpaceDataType, SpaceAccessDeniedDataType, SpaceOwnerNotFoundDataType, DocNotFoundDataType, DocAccessDeniedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderSideErrorDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType] as const,
});

View File

@@ -40,5 +40,3 @@ export class ErrorModule implements OnModuleInit {
export { UserFriendlyError } from './def';
export * from './errors.gen';
export * from './payment-required';
export * from './too-many-requests';

View File

@@ -1,10 +0,0 @@
import { HttpException, HttpStatus } from '@nestjs/common';
export class PaymentRequiredException extends HttpException {
constructor(desc?: string, code: string = 'Payment Required') {
super(
HttpException.createBody(desc ?? code, code, HttpStatus.PAYMENT_REQUIRED),
HttpStatus.PAYMENT_REQUIRED
);
}
}

View File

@@ -1,14 +0,0 @@
import { HttpException, HttpStatus } from '@nestjs/common';
export class TooManyRequestsException extends HttpException {
constructor(desc?: string, code: string = 'Too Many Requests') {
super(
HttpException.createBody(
desc ?? code,
code,
HttpStatus.TOO_MANY_REQUESTS
),
HttpStatus.TOO_MANY_REQUESTS
);
}
}

View File

@@ -0,0 +1,50 @@
import {
applyDecorators,
CanActivate,
ExecutionContext,
Injectable,
SetMetadata,
UseGuards,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { GUARD_PROVIDER, NamedGuards } from './provider';
const BasicGuardSymbol = Symbol('BasicGuard');
@Injectable()
export class BasicGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
async canActivate(context: ExecutionContext) {
// get registered guard name
const providerName = this.reflector.get<string>(
BasicGuardSymbol,
context.getHandler()
);
const provider = GUARD_PROVIDER[providerName as NamedGuards];
if (provider) {
return await provider.canActivate(context);
}
return true;
}
}
/**
* This guard is used to protect routes/queries/mutations that use a registered guard
*
* @example
*
* ```typescript
* \@UseNamedGuard('captcha') // use captcha guard
* \@Auth()
* \@Query(() => UserType)
* user(@CurrentUser() user: CurrentUser) {
* return user;
* }
* ```
*/
export const UseNamedGuard = (name: NamedGuards) =>
applyDecorators(UseGuards(BasicGuard), SetMetadata(BasicGuardSymbol, name));

View File

@@ -0,0 +1,2 @@
export { UseNamedGuard } from './guard';
export { GuardProvider, type RegisterGuardName } from './provider';

View File

@@ -0,0 +1,26 @@
import {
CanActivate,
ExecutionContext,
Injectable,
Logger,
OnModuleInit,
} from '@nestjs/common';
export interface RegisterGuardName {}
export type NamedGuards = keyof RegisterGuardName;
export const GUARD_PROVIDER: Partial<Record<NamedGuards, GuardProvider>> = {};
@Injectable()
export abstract class GuardProvider implements OnModuleInit, CanActivate {
private readonly logger = new Logger(GuardProvider.name);
abstract name: NamedGuards;
onModuleInit() {
GUARD_PROVIDER[this.name] = this;
this.logger.log(`Guard provider [${this.name}] registered`);
}
abstract canActivate(context: ExecutionContext): boolean | Promise<boolean>;
}

View File

@@ -89,7 +89,7 @@ export class URLHelper {
if (!['http:', 'https:'].includes(url.protocol)) return false;
if (!url.hostname) return false;
return true;
} catch (_) {
} catch {
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More