Compare commits

...

122 Commits

Author SHA1 Message Date
李华桥
a5dfcc7874 chore: v0.10.4-beta.2 2023-12-12 11:30:20 +08:00
李华桥
9eb10a76c9 chore: v0.10.4-beta.1 2023-12-12 11:10:10 +08:00
李华桥
c89ebab596 Merge branch 'canary' into stable 2023-12-12 11:04:33 +08:00
EYHN
68e7577841 fix(core): fix editor sidebar open on resize (#5262) 2023-12-12 11:02:33 +08:00
JimmFly
38e46bc3b2 fix(core): adjust share edgeless display error (#5263)
close #5261

https://github.com/toeverything/AFFiNE/assets/102217452/8a7c4347-96df-45a3-973a-806876e5703d
2023-12-11 10:55:23 +00:00
liuyi
62f4421b7c fix(server): avoid updates persist forever (#5258) 2023-12-11 17:42:25 +08:00
liuyi
30ecee483d fix(server): avoid updates persist forever (#5258) 2023-12-11 09:17:49 +00:00
JimmFly
feb7bd9fef fix(cli): fix storybook build error (#5257)
<img width="1036" alt="image" src="https://github.com/toeverything/AFFiNE/assets/102217452/477d653e-80b5-4364-a073-e3386cd7ab17">
2023-12-11 08:07:43 +00:00
LongYinan
681d25c67c chore: bump up @electron-forge/maker-base version to v7.2.0 (#5191)
[![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-forge/maker-base](https://togithub.com/electron/forge) | [`7.1.0` -> `7.2.0`](https://renovatebot.com/diffs/npm/@electron-forge%2fmaker-base/7.1.0/7.2.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@electron-forge%2fmaker-base/7.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@electron-forge%2fmaker-base/7.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@electron-forge%2fmaker-base/7.1.0/7.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@electron-forge%2fmaker-base/7.1.0/7.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>electron/forge (@&#8203;electron-forge/maker-base)</summary>

### [`v7.2.0`](https://togithub.com/electron/forge/releases/tag/v7.2.0)

[Compare Source](https://togithub.com/electron/forge/compare/v7.1.0...v7.2.0)

#### What's Changed

##### Features

-   feat: add support for sequential groups of webpack builds by [@&#8203;MarshallOfSound](https://togithub.com/MarshallOfSound) in [https://github.com/electron/forge/pull/3435](https://togithub.com/electron/forge/pull/3435)

##### Fixes

-   fix: handle webpack configs exported as default by [@&#8203;MarshallOfSound](https://togithub.com/MarshallOfSound) in [https://github.com/electron/forge/pull/3427](https://togithub.com/electron/forge/pull/3427)
-   fix: set empty publicPath for preload scripts by [@&#8203;MarshallOfSound](https://togithub.com/MarshallOfSound) in [https://github.com/electron/forge/pull/3428](https://togithub.com/electron/forge/pull/3428)
-   fix: ensure that webpack is run once per arch for universal builds by [@&#8203;MarshallOfSound](https://togithub.com/MarshallOfSound) in [https://github.com/electron/forge/pull/3433](https://togithub.com/electron/forge/pull/3433)

##### Documentation

-   docs: remove mention of v5 -> v6 migration by [@&#8203;erickzhao](https://togithub.com/erickzhao) in [https://github.com/electron/forge/pull/3412](https://togithub.com/electron/forge/pull/3412)
-   docs: add notes on publishing a new monorepo package by [@&#8203;erickzhao](https://togithub.com/erickzhao) in [https://github.com/electron/forge/pull/3415](https://togithub.com/electron/forge/pull/3415)

##### Other Changes

-   build(docs): enable API documentation builds for Forge v7 by [@&#8203;erickzhao](https://togithub.com/erickzhao) in [https://github.com/electron/forge/pull/3413](https://togithub.com/electron/forge/pull/3413)
-   ci: allow manual API documentation publish by [@&#8203;dsanders11](https://togithub.com/dsanders11) in [https://github.com/electron/forge/pull/3414](https://togithub.com/electron/forge/pull/3414)
-   refactor: dedupe key resolver for static publishers by [@&#8203;MarshallOfSound](https://togithub.com/MarshallOfSound) in [https://github.com/electron/forge/pull/3421](https://togithub.com/electron/forge/pull/3421)
-   chore: bump electronjs/node to 2.1.0 (main) by [@&#8203;electron-roller](https://togithub.com/electron-roller) in [https://github.com/electron/forge/pull/3422](https://togithub.com/electron/forge/pull/3422)
-   chore: update deps to clear some audit warnings by [@&#8203;dsanders11](https://togithub.com/dsanders11) in [https://github.com/electron/forge/pull/3429](https://togithub.com/electron/forge/pull/3429)

**Full Changelog**: https://github.com/electron/forge/compare/v7.1.0...v7.2.0

![image](https://togithub.com/electron/forge/assets/33054982/9c4d7096-4942-419a-96b1-123c197e5cf6)

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-11 07:43:15 +00:00
LongYinan
6a46ea85e7 chore: upgrade rustup toolchain (#5246) 2023-12-11 07:28:09 +00:00
LongYinan
73c2750596 chore: upgrade to yarn@4.0.2 (#5245) 2023-12-11 07:28:07 +00:00
LongYinan
8a22fbbec2 chore: bump up marked version to v11 (#5200)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [marked](https://marked.js.org) ([source](https://togithub.com/markedjs/marked)) | [`^9.1.2` -> `^11.0.0`](https://renovatebot.com/diffs/npm/marked/9.1.6/11.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/marked/11.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/marked/11.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/marked/9.1.6/11.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/marked/9.1.6/11.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

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

### [`v11.0.0`](https://togithub.com/markedjs/marked/releases/tag/v11.0.0)

[Compare Source](https://togithub.com/markedjs/marked/compare/v10.0.0...v11.0.0)

##### Bug Fixes

-   clean up rules so they can be typed ([#&#8203;3087](https://togithub.com/markedjs/marked/issues/3087)) ([175fc0c](175fc0c321))
-   fix marked types ([#&#8203;3103](https://togithub.com/markedjs/marked/issues/3103)) ([edae309](edae309505))

##### BREAKING CHANGES

-   Lexer.rules object has been changed so it can be properly types. Some intermediate rules have been removed.

### [`v10.0.0`](https://togithub.com/markedjs/marked/releases/tag/v10.0.0)

[Compare Source](https://togithub.com/markedjs/marked/compare/v9.1.6...v10.0.0)

##### Bug Fixes

-   run spec tests with testutils ([#&#8203;3017](https://togithub.com/markedjs/marked/issues/3017)) ([014d4e6](014d4e61f6))

##### BREAKING CHANGES

-   drop support for node v16

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-11 07:13:01 +00:00
LongYinan
4de832d69d chore: bump up vite-plugin-static-copy version to v1 (#5205)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [vite-plugin-static-copy](https://togithub.com/sapphi-red/vite-plugin-static-copy) | [`^0.17.1` -> `^1.0.0`](https://renovatebot.com/diffs/npm/vite-plugin-static-copy/0.17.1/1.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite-plugin-static-copy/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite-plugin-static-copy/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite-plugin-static-copy/0.17.1/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite-plugin-static-copy/0.17.1/1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>sapphi-red/vite-plugin-static-copy (vite-plugin-static-copy)</summary>

### [`v1.0.0`](https://togithub.com/sapphi-red/vite-plugin-static-copy/blob/HEAD/CHANGELOG.md#100)

[Compare Source](https://togithub.com/sapphi-red/vite-plugin-static-copy/compare/v0.17.1...vite-plugin-static-copy@1.0.0)

##### Major Changes

-   [`252f62c`](252f62ce6c) Thanks [@&#8203;sapphi-red](https://togithub.com/sapphi-red)! - drop support for Vite 3 and 4

-   [`252f62c`](252f62ce6c) Thanks [@&#8203;sapphi-red](https://togithub.com/sapphi-red)! - drop CJS build. See https://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only for how to migrate from CJS to ESM.

-   [`252f62c`](252f62ce6c) Thanks [@&#8203;sapphi-red](https://togithub.com/sapphi-red)! - drop node 14.18/16/17/19 support

##### Patch Changes

-   [#&#8203;67](https://togithub.com/sapphi-red/vite-plugin-static-copy/pull/67) [`8707d84`](8707d84d47) Thanks [@&#8203;sapphi-red](https://togithub.com/sapphi-red)! - copy only once even if multiple bundles are generated

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODcuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-11 06:55:17 +00:00
JimmFly
e7a7796ef3 feat(core): adjust empty collection style (#5239)
<img width="270" alt="image" src="https://github.com/toeverything/AFFiNE/assets/102217452/18ac2de8-51c0-447e-9c81-787f579eab4e">
2023-12-11 06:30:09 +00:00
Peng Xiao
cfd200528f fix(component): revert theme flickering (#5238) (#5256)
This reverts commit e8cfc807ea.
2023-12-11 06:05:16 +00:00
Peng Xiao
e8cfc807ea fix(electron): use tree-kill for electron dev (#5252)
electron process sometimes do not get re-spawned because of some child process not being closed.
use tree-kill instead.
2023-12-11 04:26:19 +00:00
李华桥
42383dbd29 Merge branch 'canary' into stable 2023-12-10 21:04:15 +08:00
LongYinan
f0c70b92f4 chore: bump up google-github-actions/setup-gcloud action to v2 (#5241)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [google-github-actions/setup-gcloud](https://togithub.com/google-github-actions/setup-gcloud) | action | major | `v1` -> `v2` |

---

### Release Notes

<details>
<summary>google-github-actions/setup-gcloud (google-github-actions/setup-gcloud)</summary>

### [`v2`](https://togithub.com/google-github-actions/setup-gcloud/releases/tag/v2)

[Compare Source](https://togithub.com/google-github-actions/setup-gcloud/compare/v1...v2)

**⚠️ This version requires Node 20 or later!**

Floating v2 alias

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44Ny4yIiwidXBkYXRlZEluVmVyIjoiMzcuODcuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-10 07:33:07 +00:00
LongYinan
255d25d20c chore: bump up @opentelemetry/host-metrics version to ^0.34.0 (#5234)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@opentelemetry/host-metrics](https://togithub.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/opentelemetry-host-metrics#readme) ([source](https://togithub.com/open-telemetry/opentelemetry-js-contrib)) | [`^0.33.2` -> `^0.34.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fhost-metrics/0.33.2/0.34.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2fhost-metrics/0.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2fhost-metrics/0.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2fhost-metrics/0.33.2/0.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2fhost-metrics/0.33.2/0.34.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>open-telemetry/opentelemetry-js-contrib (@&#8203;opentelemetry/host-metrics)</summary>

### [`v0.34.0`](607d375595...c7e7000b7b)

[Compare Source](607d375595...c7e7000b7b)

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44Ny4yIiwidXBkYXRlZEluVmVyIjoiMzcuODcuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-10 07:20:58 +00:00
Joooye_34
c1bb467013 refactor(core): use debug log replace console when command registry (#5237) 2023-12-09 07:42:04 +00:00
Nadeshiko Manju
a066dfb108 chore: add sha512sum for the released files (#5242) 2023-12-09 15:41:20 +08:00
EYHN
3e9f8e06be chore(env): fix lint error (#5240) 2023-12-09 04:45:13 +00:00
Peng Xiao
5979162a5c fix(component): theme flickering (#5238)
Add color-scheme to html so that the web will use system scheme when scripts has not being loaded;
Use `(prefers-color-scheme: dark)` so that the css vars do not defer load based on `data-theme`, which is set by next-themes (which is deferred).
2023-12-08 10:12:20 +00:00
LongYinan
feed400462 chore: bump up vite version to v5 (#5203)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [vite](https://vitejs.dev) ([source](https://togithub.com/vitejs/vite/tree/HEAD/packages/vite)) | [`^4.4.11` -> `^5.0.0`](https://renovatebot.com/diffs/npm/vite/4.5.1/5.0.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite/5.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/5.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/4.5.1/5.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/4.5.1/5.0.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

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

### [`v5.0.6`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small506-2023-12-06-small)

[Compare Source](https://togithub.com/vitejs/vite/compare/v5.0.5...v5.0.6)

-   perf: in-memory public files check ([#&#8203;15195](https://togithub.com/vitejs/vite/issues/15195)) ([0f9e1bf](https://togithub.com/vitejs/vite/commit/0f9e1bf)), closes [#&#8203;15195](https://togithub.com/vitejs/vite/issues/15195)
-   chore: remove unneccessary eslint-disable-next-line regexp/no-unused-capturing-group ([#&#8203;15247](https://togithub.com/vitejs/vite/issues/15247)) ([35a5bcf](https://togithub.com/vitejs/vite/commit/35a5bcf)), closes [#&#8203;15247](https://togithub.com/vitejs/vite/issues/15247)

### [`v5.0.5`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small505-2023-12-04-small)

[Compare Source](https://togithub.com/vitejs/vite/compare/v5.0.4...v5.0.5)

-   fix: emit `vite:preloadError` for chunks without deps ([#&#8203;15203](https://togithub.com/vitejs/vite/issues/15203)) ([d8001c5](https://togithub.com/vitejs/vite/commit/d8001c5)), closes [#&#8203;15203](https://togithub.com/vitejs/vite/issues/15203)
-   fix: esbuild glob import resolve error ([#&#8203;15140](https://togithub.com/vitejs/vite/issues/15140)) ([676804d](https://togithub.com/vitejs/vite/commit/676804d)), closes [#&#8203;15140](https://togithub.com/vitejs/vite/issues/15140)
-   fix: json error with position ([#&#8203;15225](https://togithub.com/vitejs/vite/issues/15225)) ([14be75f](https://togithub.com/vitejs/vite/commit/14be75f)), closes [#&#8203;15225](https://togithub.com/vitejs/vite/issues/15225)
-   fix: proxy html path should be encoded ([#&#8203;15223](https://togithub.com/vitejs/vite/issues/15223)) ([5b85040](https://togithub.com/vitejs/vite/commit/5b85040)), closes [#&#8203;15223](https://togithub.com/vitejs/vite/issues/15223)
-   fix(deps): update all non-major dependencies ([#&#8203;15233](https://togithub.com/vitejs/vite/issues/15233)) ([ad3adda](https://togithub.com/vitejs/vite/commit/ad3adda)), closes [#&#8203;15233](https://togithub.com/vitejs/vite/issues/15233)
-   fix(hmr): don't consider CSS dep as a circular dep ([#&#8203;15229](https://togithub.com/vitejs/vite/issues/15229)) ([5f2cdec](https://togithub.com/vitejs/vite/commit/5f2cdec)), closes [#&#8203;15229](https://togithub.com/vitejs/vite/issues/15229)
-   feat: add '\*.mov' to client.d.ts ([#&#8203;15189](https://togithub.com/vitejs/vite/issues/15189)) ([d93a211](https://togithub.com/vitejs/vite/commit/d93a211)), closes [#&#8203;15189](https://togithub.com/vitejs/vite/issues/15189)
-   feat(server): allow disabling built-in shortcuts ([#&#8203;15218](https://togithub.com/vitejs/vite/issues/15218)) ([7fd7c6c](https://togithub.com/vitejs/vite/commit/7fd7c6c)), closes [#&#8203;15218](https://togithub.com/vitejs/vite/issues/15218)
-   chore: replace 'some' with 'includes' in resolveEnvPrefix ([#&#8203;15220](https://togithub.com/vitejs/vite/issues/15220)) ([ee12f30](https://togithub.com/vitejs/vite/commit/ee12f30)), closes [#&#8203;15220](https://togithub.com/vitejs/vite/issues/15220)
-   chore: update the website url for homepage in package.json ([#&#8203;15181](https://togithub.com/vitejs/vite/issues/15181)) ([282bd8f](https://togithub.com/vitejs/vite/commit/282bd8f)), closes [#&#8203;15181](https://togithub.com/vitejs/vite/issues/15181)
-   chore: update vitest to 1.0.0-beta.6 ([#&#8203;15194](https://togithub.com/vitejs/vite/issues/15194)) ([2fce647](https://togithub.com/vitejs/vite/commit/2fce647)), closes [#&#8203;15194](https://togithub.com/vitejs/vite/issues/15194)
-   refactor: make HMR agnostic to environment ([#&#8203;15179](https://togithub.com/vitejs/vite/issues/15179)) ([0571b7c](https://togithub.com/vitejs/vite/commit/0571b7c)), closes [#&#8203;15179](https://togithub.com/vitejs/vite/issues/15179)
-   refactor: use dedicated regex methods ([#&#8203;15228](https://togithub.com/vitejs/vite/issues/15228)) ([0348137](https://togithub.com/vitejs/vite/commit/0348137)), closes [#&#8203;15228](https://togithub.com/vitejs/vite/issues/15228)
-   perf: remove debug only prettifyUrl call ([#&#8203;15204](https://togithub.com/vitejs/vite/issues/15204)) ([73e971f](https://togithub.com/vitejs/vite/commit/73e971f)), closes [#&#8203;15204](https://togithub.com/vitejs/vite/issues/15204)
-   perf: skip computing sourceRoot in injectSourcesContent ([#&#8203;15207](https://togithub.com/vitejs/vite/issues/15207)) ([1df1fd1](https://togithub.com/vitejs/vite/commit/1df1fd1)), closes [#&#8203;15207](https://togithub.com/vitejs/vite/issues/15207)

### [`v5.0.4`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small504-2023-11-29-small)

[Compare Source](https://togithub.com/vitejs/vite/compare/v5.0.3...v5.0.4)

-   fix: bindCLIShortcuts to proper server ([#&#8203;15162](https://togithub.com/vitejs/vite/issues/15162)) ([67ac572](https://togithub.com/vitejs/vite/commit/67ac572)), closes [#&#8203;15162](https://togithub.com/vitejs/vite/issues/15162)
-   fix: revert "fix: js fallback sourcemap content should be using original content ([#&#8203;15135](https://togithub.com/vitejs/vite/issues/15135))" ([#&#8203;15178](https://togithub.com/vitejs/vite/issues/15178)) ([d2a2493](https://togithub.com/vitejs/vite/commit/d2a2493)), closes [#&#8203;15135](https://togithub.com/vitejs/vite/issues/15135) [#&#8203;15178](https://togithub.com/vitejs/vite/issues/15178)
-   fix(define): allow define process.env ([#&#8203;15173](https://togithub.com/vitejs/vite/issues/15173)) ([ec401da](https://togithub.com/vitejs/vite/commit/ec401da)), closes [#&#8203;15173](https://togithub.com/vitejs/vite/issues/15173)
-   fix(resolve): respect order of browser in mainFields when resolving ([#&#8203;15137](https://togithub.com/vitejs/vite/issues/15137)) ([4a111aa](https://togithub.com/vitejs/vite/commit/4a111aa)), closes [#&#8203;15137](https://togithub.com/vitejs/vite/issues/15137)
-   feat: preserve vite.middlewares connect instance after restarts ([#&#8203;15166](https://togithub.com/vitejs/vite/issues/15166)) ([9474c4b](https://togithub.com/vitejs/vite/commit/9474c4b)), closes [#&#8203;15166](https://togithub.com/vitejs/vite/issues/15166)
-   refactor: align with Promise.withResolvers() ([#&#8203;15171](https://togithub.com/vitejs/vite/issues/15171)) ([642f9bc](https://togithub.com/vitejs/vite/commit/642f9bc)), closes [#&#8203;15171](https://togithub.com/vitejs/vite/issues/15171)

### [`v5.0.3`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small503-2023-11-28-small)

[Compare Source](https://togithub.com/vitejs/vite/compare/v5.0.2...v5.0.3)

-   fix: `generateCodeFrame` infinite loop ([#&#8203;15093](https://togithub.com/vitejs/vite/issues/15093)) ([6619de7](https://togithub.com/vitejs/vite/commit/6619de7)), closes [#&#8203;15093](https://togithub.com/vitejs/vite/issues/15093)
-   fix: js fallback sourcemap content should be using original content ([#&#8203;15135](https://togithub.com/vitejs/vite/issues/15135)) ([227d56d](https://togithub.com/vitejs/vite/commit/227d56d)), closes [#&#8203;15135](https://togithub.com/vitejs/vite/issues/15135)
-   fix(css): render correct asset url when CSS chunk name is nested ([#&#8203;15154](https://togithub.com/vitejs/vite/issues/15154)) ([ef403c0](https://togithub.com/vitejs/vite/commit/ef403c0)), closes [#&#8203;15154](https://togithub.com/vitejs/vite/issues/15154)
-   fix(css): use non-nested chunk name if facadeModule is not CSS file ([#&#8203;15155](https://togithub.com/vitejs/vite/issues/15155)) ([811e392](https://togithub.com/vitejs/vite/commit/811e392)), closes [#&#8203;15155](https://togithub.com/vitejs/vite/issues/15155)
-   fix(dev): bind plugin context functions ([#&#8203;14569](https://togithub.com/vitejs/vite/issues/14569)) ([cb3243c](https://togithub.com/vitejs/vite/commit/cb3243c)), closes [#&#8203;14569](https://togithub.com/vitejs/vite/issues/14569)
-   chore(deps): update all non-major dependencies ([#&#8203;15145](https://togithub.com/vitejs/vite/issues/15145)) ([7ff2c0a](https://togithub.com/vitejs/vite/commit/7ff2c0a)), closes [#&#8203;15145](https://togithub.com/vitejs/vite/issues/15145)
-   build: handle latest json-stable-stringify replacement ([#&#8203;15049](https://togithub.com/vitejs/vite/issues/15049)) ([bcc4a61](https://togithub.com/vitejs/vite/commit/bcc4a61)), closes [#&#8203;15049](https://togithub.com/vitejs/vite/issues/15049)

### [`v5.0.2`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small502-2023-11-21-small)

[Compare Source](https://togithub.com/vitejs/vite/compare/v5.0.1...v5.0.2)

-   fix: make htmlFallback more permissive ([#&#8203;15059](https://togithub.com/vitejs/vite/issues/15059)) ([6fcceeb](https://togithub.com/vitejs/vite/commit/6fcceeb)), closes [#&#8203;15059](https://togithub.com/vitejs/vite/issues/15059)

### [`v5.0.1`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small501-2023-11-21-small)

-   test: avoid read check when running as root ([#&#8203;14884](https://togithub.com/vitejs/vite/issues/14884)) ([1d9516c](https://togithub.com/vitejs/vite/commit/1d9516c)), closes [#&#8203;14884](https://togithub.com/vitejs/vite/issues/14884)
-   perf(hmr): skip traversed modules when checking circular imports ([#&#8203;15034](https://togithub.com/vitejs/vite/issues/15034)) ([41e437f](https://togithub.com/vitejs/vite/commit/41e437f)), closes [#&#8203;15034](https://togithub.com/vitejs/vite/issues/15034)
-   fix: run htmlFallbackMiddleware for no accept header requests ([#&#8203;15025](https://togithub.com/vitejs/vite/issues/15025)) ([b93dfe3](https://togithub.com/vitejs/vite/commit/b93dfe3)), closes [#&#8203;15025](https://togithub.com/vitejs/vite/issues/15025)
-   fix: update type CSSModulesOptions interface ([#&#8203;14987](https://togithub.com/vitejs/vite/issues/14987)) ([d0b2153](https://togithub.com/vitejs/vite/commit/d0b2153)), closes [#&#8203;14987](https://togithub.com/vitejs/vite/issues/14987)
-   fix(legacy): error in build with --watch and manifest enabled ([#&#8203;14450](https://togithub.com/vitejs/vite/issues/14450)) ([b9ee620](https://togithub.com/vitejs/vite/commit/b9ee620)), closes [#&#8203;14450](https://togithub.com/vitejs/vite/issues/14450)
-   chore: add comment about crossorigin attribute for script module ([#&#8203;15040](https://togithub.com/vitejs/vite/issues/15040)) ([03c371e](https://togithub.com/vitejs/vite/commit/03c371e)), closes [#&#8203;15040](https://togithub.com/vitejs/vite/issues/15040)
-   chore: cleanup v5 beta changelog ([#&#8203;14694](https://togithub.com/vitejs/vite/issues/14694)) ([531d3cb](https://togithub.com/vitejs/vite/commit/531d3cb)), closes [#&#8203;14694](https://togithub.com/vitejs/vite/issues/14694)

### [`v5.0.0`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#500-2023-11-16)

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODcuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-08 09:57:11 +00:00
LongYinan
2269e68bd9 chore: bump up p-queue version to v8 (#5235)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

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

---

### Release Notes

<details>
<summary>sindresorhus/p-queue (p-queue)</summary>

### [`v8.0.0`](https://togithub.com/sindresorhus/p-queue/releases/tag/v8.0.0)

[Compare Source](https://togithub.com/sindresorhus/p-queue/compare/v7.4.1...v8.0.0)

##### Breaking

-   Require Node.js 18  [`68dfe95`](https://togithub.com/sindresorhus/p-queue/commit/68dfe95)
-   Removed the `AbortError` export. It now throws the built-in DOMException when using the `signal` option. [`68dfe95`](https://togithub.com/sindresorhus/p-queue/commit/68dfe95)
-   TypeScript: Rename `DefaultAddOptions` type to `QueueAddOptions`

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44Ny4yIiwidXBkYXRlZEluVmVyIjoiMzcuODcuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-08 08:06:46 +00:00
LongYinan
285fd367eb chore: bump up undici version to v6 (#5204)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [undici](https://undici.nodejs.org) ([source](https://togithub.com/nodejs/undici)) | [`^5.27.2` -> `^6.0.0`](https://renovatebot.com/diffs/npm/undici/5.28.0/6.0.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/undici/6.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/undici/6.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/undici/5.28.0/6.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/undici/5.28.0/6.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

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

### [`v6.0.1`](https://togithub.com/nodejs/undici/releases/tag/v6.0.1)

[Compare Source](https://togithub.com/nodejs/undici/compare/v6.0.0...v6.0.1)

#### What's Changed

-   fix: stream error timings by [@&#8203;ronag](https://togithub.com/ronag) in [https://github.com/nodejs/undici/pull/2497](https://togithub.com/nodejs/undici/pull/2497)

**Full Changelog**: https://github.com/nodejs/undici/compare/v6.0.0...v6.0.1

### [`v6.0.0`](https://togithub.com/nodejs/undici/releases/tag/v6.0.0)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.28.2...v6.0.0)

#### What's Changed

-   16 eol by [@&#8203;ronag](https://togithub.com/ronag) in [https://github.com/nodejs/undici/pull/2480](https://togithub.com/nodejs/undici/pull/2480)
-   update spec & wpts by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [https://github.com/nodejs/undici/pull/2482](https://togithub.com/nodejs/undici/pull/2482)
-   version cleanup by [@&#8203;KhafraDev](https://togithub.com/KhafraDev) in [https://github.com/nodejs/undici/pull/2483](https://togithub.com/nodejs/undici/pull/2483)
-   perf: avoid Response initialization by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2489](https://togithub.com/nodejs/undici/pull/2489)
-   perf: optimize `parseHeaders` by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2492](https://togithub.com/nodejs/undici/pull/2492)
-   chore: fix typo by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2490](https://togithub.com/nodejs/undici/pull/2490)
-   feat: print attempted addresses on ConnectTimeoutError by [@&#8203;fengmk2](https://togithub.com/fengmk2) in [https://github.com/nodejs/undici/pull/2494](https://togithub.com/nodejs/undici/pull/2494)
-   Expose HTTP errors that are not meant to be retried by [@&#8203;MzUgM](https://togithub.com/MzUgM) in [https://github.com/nodejs/undici/pull/2496](https://togithub.com/nodejs/undici/pull/2496)

**Full Changelog**: https://github.com/nodejs/undici/compare/v5.28.2...v6.0.0

### [`v5.28.2`](https://togithub.com/nodejs/undici/releases/tag/v5.28.2)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.28.1...v5.28.2)

#### What's Changed

-   fix: remove optional chainning for compatible with Nodejs12 and below by [@&#8203;bugb](https://togithub.com/bugb) in [https://github.com/nodejs/undici/pull/2470](https://togithub.com/nodejs/undici/pull/2470)
-   fix: remove `node:` prefix by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2471](https://togithub.com/nodejs/undici/pull/2471)
-   perf: avoid Headers initialization by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2468](https://togithub.com/nodejs/undici/pull/2468)
-   fix: handle SharedArrayBuffer correctly by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2466](https://togithub.com/nodejs/undici/pull/2466)
-   fix: Add `null` type to `signal` in `RequestInit` by [@&#8203;gebsh](https://togithub.com/gebsh) in [https://github.com/nodejs/undici/pull/2455](https://togithub.com/nodejs/undici/pull/2455)
-   fix: correctly handle data URL with hashes. by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2475](https://togithub.com/nodejs/undici/pull/2475)
-   fix: check response for timinginfo allow flag by [@&#8203;ToshB](https://togithub.com/ToshB) in [https://github.com/nodejs/undici/pull/2477](https://togithub.com/nodejs/undici/pull/2477)
-   Make call to onBodySent conditional in RetryHandler by [@&#8203;MzUgM](https://togithub.com/MzUgM) in [https://github.com/nodejs/undici/pull/2478](https://togithub.com/nodejs/undici/pull/2478)
-   refactor: better integrity check by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2462](https://togithub.com/nodejs/undici/pull/2462)
-   fix: Added support for inline URL username:password proxy auth by [@&#8203;matt-way](https://togithub.com/matt-way) in [https://github.com/nodejs/undici/pull/2473](https://togithub.com/nodejs/undici/pull/2473)
-   build(deps-dev): bump jsdom from 22.1.0 to 23.0.0 by [@&#8203;dependabot](https://togithub.com/dependabot) in [https://github.com/nodejs/undici/pull/2472](https://togithub.com/nodejs/undici/pull/2472)
-   build(deps-dev): bump sinon from 16.1.3 to 17.0.1 by [@&#8203;dependabot](https://togithub.com/dependabot) in [https://github.com/nodejs/undici/pull/2405](https://togithub.com/nodejs/undici/pull/2405)
-   build(deps): bump ossf/scorecard-action from 2.2.0 to 2.3.1 by [@&#8203;dependabot](https://togithub.com/dependabot) in [https://github.com/nodejs/undici/pull/2396](https://togithub.com/nodejs/undici/pull/2396)
-   build(deps): bump actions/setup-node from 3.8.1 to 4.0.0 by [@&#8203;dependabot](https://togithub.com/dependabot) in [https://github.com/nodejs/undici/pull/2395](https://togithub.com/nodejs/undici/pull/2395)
-   build(deps): bump step-security/harden-runner from 2.5.0 to 2.6.0 by [@&#8203;dependabot](https://togithub.com/dependabot) in [https://github.com/nodejs/undici/pull/2392](https://togithub.com/nodejs/undici/pull/2392)
-   build(deps-dev): bump formdata-node from 4.4.1 to 6.0.3 by [@&#8203;dependabot](https://togithub.com/dependabot) in [https://github.com/nodejs/undici/pull/2389](https://togithub.com/nodejs/undici/pull/2389)
-   build(deps): bump actions/upload-artifact from 3.1.2 to 3.1.3 by [@&#8203;dependabot](https://togithub.com/dependabot) in [https://github.com/nodejs/undici/pull/2302](https://togithub.com/nodejs/undici/pull/2302)

#### New Contributors

-   [@&#8203;bugb](https://togithub.com/bugb) made their first contribution in [https://github.com/nodejs/undici/pull/2470](https://togithub.com/nodejs/undici/pull/2470)
-   [@&#8203;gebsh](https://togithub.com/gebsh) made their first contribution in [https://github.com/nodejs/undici/pull/2455](https://togithub.com/nodejs/undici/pull/2455)
-   [@&#8203;ToshB](https://togithub.com/ToshB) made their first contribution in [https://github.com/nodejs/undici/pull/2477](https://togithub.com/nodejs/undici/pull/2477)
-   [@&#8203;MzUgM](https://togithub.com/MzUgM) made their first contribution in [https://github.com/nodejs/undici/pull/2478](https://togithub.com/nodejs/undici/pull/2478)
-   [@&#8203;matt-way](https://togithub.com/matt-way) made their first contribution in [https://github.com/nodejs/undici/pull/2473](https://togithub.com/nodejs/undici/pull/2473)

**Full Changelog**: https://github.com/nodejs/undici/compare/v5.28.1...v5.28.2

### [`v5.28.1`](https://togithub.com/nodejs/undici/releases/tag/v5.28.1)

[Compare Source](https://togithub.com/nodejs/undici/compare/v5.28.0...v5.28.1)

#### What's Changed

-   perf: Improve `normalizeMethod` by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2456](https://togithub.com/nodejs/undici/pull/2456)
-   fix: dispatch error handling by [@&#8203;ronag](https://togithub.com/ronag) in [https://github.com/nodejs/undici/pull/2459](https://togithub.com/nodejs/undici/pull/2459)
-   perf(request): optimize if headers are given by [@&#8203;tsctx](https://togithub.com/tsctx) in [https://github.com/nodejs/undici/pull/2454](https://togithub.com/nodejs/undici/pull/2454)

**Full Changelog**: https://github.com/nodejs/undici/compare/v5.28.0...v5.28.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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODcuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-08 06:57:56 +00:00
LongYinan
0be087b5d7 ci: fix rust build during deployment (#5233) 2023-12-08 06:39:16 +00:00
LongYinan
37a32d1f7d chore: bump up rollup version to v4 (#5202)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [rollup](https://rollupjs.org/) ([source](https://togithub.com/rollup/rollup)) | [`^3.29.4` -> `^4.0.0`](https://renovatebot.com/diffs/npm/rollup/3.29.4/4.6.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/rollup/4.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/rollup/4.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/rollup/3.29.4/4.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/rollup/3.29.4/4.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>rollup/rollup (rollup)</summary>

### [`v4.6.1`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#461)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.6.0...v4.6.1)

*2023-11-30*

##### Bug Fixes

-   Resolve a situation where declaring the same `var` several times was considered a conflict ([#&#8203;5276](https://togithub.com/rollup/rollup/issues/5276))

##### Pull Requests

-   [#&#8203;5275](https://togithub.com/rollup/rollup/pull/5275): Add TNG as special sponsor ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5276](https://togithub.com/rollup/rollup/pull/5276): Allow to redeclare parameters multiple times in nested scopes ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.6.0`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#460)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.5.2...v4.6.0)

*2023-11-26*

##### Features

-   Allow `this.addWatchFile` in all plugin hooks ([#&#8203;5270](https://togithub.com/rollup/rollup/issues/5270))

##### Bug Fixes

-   Show helpful error when native binaries are not installed due to an `npm` issue ([#&#8203;5267](https://togithub.com/rollup/rollup/issues/5267))
-   Do not access `this` context in `this.addWatchFile` so it does not need to be bound when passed around ([#&#8203;5270](https://togithub.com/rollup/rollup/issues/5270))

##### Pull Requests

-   [#&#8203;5267](https://togithub.com/rollup/rollup/pull/5267): Add friendly error for npm bug ([@&#8203;sapphi-red](https://togithub.com/sapphi-red))
-   [#&#8203;5270](https://togithub.com/rollup/rollup/pull/5270): Allow this.addWatchFile in all hooks ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5272](https://togithub.com/rollup/rollup/pull/5272): Debug deployed graphs ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.5.2`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#452)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.5.1...v4.5.2)

*2023-11-24*

##### Bug Fixes

-   Handle files with UTF-8 BOM when using the commonjs plugin ([#&#8203;5268](https://togithub.com/rollup/rollup/issues/5268))

##### Pull Requests

-   [#&#8203;5268](https://togithub.com/rollup/rollup/pull/5268): fix: strip BOM before calling transform hook ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5269](https://togithub.com/rollup/rollup/pull/5269): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])

### [`v4.5.1`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#451)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.5.0...v4.5.1)

*2023-11-21*

##### Bug Fixes

-   Do not error when a function expression uses the same name for a parameter and its id ([#&#8203;5262](https://togithub.com/rollup/rollup/issues/5262))

##### Pull Requests

-   [#&#8203;5257](https://togithub.com/rollup/rollup/pull/5257): Fix graphs in docs, improve REPL colors ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5262](https://togithub.com/rollup/rollup/pull/5262): Allow function expression parameters to shadow the function id ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.5.0`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#450)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.4.1...v4.5.0)

*2023-11-18*

##### Bug Fixes

-   Show a proper error when using native Rollup on armv7 musl Linux ([#&#8203;5255](https://togithub.com/rollup/rollup/issues/5255))

##### Pull Requests

-   [#&#8203;5251](https://togithub.com/rollup/rollup/pull/5251): doc fix import assertions to attributes in API plugin development page ([@&#8203;lhapaipai](https://togithub.com/lhapaipai))
-   [#&#8203;5253](https://togithub.com/rollup/rollup/pull/5253): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5255](https://togithub.com/rollup/rollup/pull/5255): Error for armv7 musl build ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.4.1`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#441)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.4.0...v4.4.1)

*2023-11-14*

##### Bug Fixes

-   Do not flag duplicate function declarations in function scopes as syntax errors ([#&#8203;5248](https://togithub.com/rollup/rollup/issues/5248))

##### Pull Requests

-   [#&#8203;5248](https://togithub.com/rollup/rollup/pull/5248): Allow functions to redeclare vars and functions in function scopes ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.4.0`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#440)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.3.1...v4.4.0)

*2023-11-12*

##### Features

-   Replace SWC linting with faster internal linting to error on duplicate declarations etc. ([#&#8203;5207](https://togithub.com/rollup/rollup/issues/5207))

##### Bug Fixes

-   Show proper error when an entry exports non-existing bindings ([#&#8203;5207](https://togithub.com/rollup/rollup/issues/5207))

##### Pull Requests

-   [#&#8203;5207](https://togithub.com/rollup/rollup/pull/5207): perf: run lint while constructing nodes ([@&#8203;sapphi-red](https://togithub.com/sapphi-red))

### [`v4.3.1`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#431)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.3.0...v4.3.1)

*2023-11-11*

##### Bug Fixes

-   Fix rename error when handling errors in watch mode ([#&#8203;5240](https://togithub.com/rollup/rollup/issues/5240))
-   Prevent warning when using `--forceExit` ([#&#8203;5245](https://togithub.com/rollup/rollup/issues/5245))

##### Pull Requests

-   [#&#8203;5240](https://togithub.com/rollup/rollup/pull/5240): fix: allow the name of Rollup Error to be modified ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5243](https://togithub.com/rollup/rollup/pull/5243): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5245](https://togithub.com/rollup/rollup/pull/5245): Ensure --forceExit works without warning ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.3.0`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#430)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.2.0...v4.3.0)

*2023-11-03*

##### Features

-   Add `forceExit` CLI flag for situations where the CLI does not exit gracefully ([#&#8203;5195](https://togithub.com/rollup/rollup/issues/5195))

##### Bug Fixes

-   Properly catch errors when removing a temporary config file fails ([#&#8203;5198](https://togithub.com/rollup/rollup/issues/5198))

##### Pull Requests

-   [#&#8203;5195](https://togithub.com/rollup/rollup/pull/5195): Add `forceExit` CLI flag ([@&#8203;raphael-theriault-swi](https://togithub.com/raphael-theriault-swi))
-   [#&#8203;5198](https://togithub.com/rollup/rollup/pull/5198): fix: prevent `ENOENT` error on temp config removal ([@&#8203;jzempel](https://togithub.com/jzempel))
-   [#&#8203;5237](https://togithub.com/rollup/rollup/pull/5237): chore: remove unused files and deps ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5238](https://togithub.com/rollup/rollup/pull/5238): chore(deps): update dependency eslint-plugin-unicorn to v49 ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5239](https://togithub.com/rollup/rollup/pull/5239): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])

### [`v4.2.0`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#420)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.1.6...v4.2.0)

*2023-10-31*

##### Features

-   Run parsing in multiple threads and introduce `parseAstAsync` helper function ([#&#8203;5202](https://togithub.com/rollup/rollup/issues/5202))

##### Pull Requests

-   [#&#8203;5202](https://togithub.com/rollup/rollup/pull/5202): perf: introduce `parseAstAsync` and parallelize parsing AST ([@&#8203;sapphi-red](https://togithub.com/sapphi-red))

### [`v4.1.6`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#416)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.1.5...v4.1.6)

*2023-10-31*

##### Bug Fixes

-   Fix a bug where emtpy block comments in certain positions could freeze Rollup ([#&#8203;5231](https://togithub.com/rollup/rollup/issues/5231))

##### Pull Requests

-   [#&#8203;5228](https://togithub.com/rollup/rollup/pull/5228): build: ensure rust toolchain components for linting are installed ([@&#8203;jerome-benoit](https://togithub.com/jerome-benoit))
-   [#&#8203;5231](https://togithub.com/rollup/rollup/pull/5231): Render emtpy block comments after tree-shaken statements ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5232](https://togithub.com/rollup/rollup/pull/5232): Revert specifying rustfmt and clippy in toolchain file as it breaks REPL build ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.1.5`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#415)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.1.4...v4.1.5)

*2023-10-28*

##### Bug Fixes

-   Fix an issue where actual entries that were also implicit entries could remain implicit ([#&#8203;5220](https://togithub.com/rollup/rollup/issues/5220))

##### Pull Requests

-   [#&#8203;5209](https://togithub.com/rollup/rollup/pull/5209): Document Vite workaround for browser build ([@&#8203;curran](https://togithub.com/curran))
-   [#&#8203;5215](https://togithub.com/rollup/rollup/pull/5215): chore(deps): update dependency lint-staged to v15 ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5216](https://togithub.com/rollup/rollup/pull/5216): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5218](https://togithub.com/rollup/rollup/pull/5218): Update license plugin ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5219](https://togithub.com/rollup/rollup/pull/5219): Fix error highlight in REPL ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5220](https://togithub.com/rollup/rollup/pull/5220): Fix race condition when emitting implicitly dependent entries ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5224](https://togithub.com/rollup/rollup/pull/5224): chore(deps): update actions/setup-node action to v4 ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5225](https://togithub.com/rollup/rollup/pull/5225): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])

### [`v4.1.4`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#414)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.1.3...v4.1.4)

*2023-10-16*

##### Bug Fixes

-   Reduce sizes [@&#8203;rollup/browser](https://togithub.com/rollup/browser) and [@&#8203;rollup/wasm-node](https://togithub.com/rollup/wasm-node) WASM artifacts ([#&#8203;5204](https://togithub.com/rollup/rollup/issues/5204))

##### Pull Requests

-   [#&#8203;5204](https://togithub.com/rollup/rollup/pull/5204): perf: shrink wasm size by avoid importing browserslist ([@&#8203;sapphi-red](https://togithub.com/sapphi-red))

### [`v4.1.3`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#413)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.1.1...v4.1.3)

*2023-10-15*

##### Bug Fixes

-   Fix WASM build as hash function was not exported ([#&#8203;5203](https://togithub.com/rollup/rollup/issues/5203))

##### Pull Requests

-   [#&#8203;5203](https://togithub.com/rollup/rollup/pull/5203): fix: export xxhashBase64Url from wasm ([@&#8203;sapphi-red](https://togithub.com/sapphi-red))

### [`v4.1.1`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#411)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.1.0...v4.1.1)

*2023-10-15*

##### Bug Fixes

-   Improve Node parsing performance ([#&#8203;5201](https://togithub.com/rollup/rollup/issues/5201))

##### Pull Requests

-   [#&#8203;5201](https://togithub.com/rollup/rollup/pull/5201): perf: use mimalloc for bindings_napi ([@&#8203;sapphi-red](https://togithub.com/sapphi-red))

### [`v4.1.0`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#410)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.0.2...v4.1.0)

*2023-10-14*

##### Features

-   Reduce memory usage of Rollup builds ([#&#8203;5133](https://togithub.com/rollup/rollup/issues/5133))

##### Pull Requests

-   [#&#8203;5133](https://togithub.com/rollup/rollup/pull/5133): perf: reducing ast node memory overhead ([@&#8203;thebanjomatic](https://togithub.com/thebanjomatic))
-   [#&#8203;5177](https://togithub.com/rollup/rollup/pull/5177): chore: explicitly set rust toolchain channel ([@&#8203;cijiugechu](https://togithub.com/cijiugechu))
-   [#&#8203;5179](https://togithub.com/rollup/rollup/pull/5179): Update migration guide for Rollup 4 ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5180](https://togithub.com/rollup/rollup/pull/5180): Resolve clippy errors ([@&#8203;cijiugechu](https://togithub.com/cijiugechu))
-   [#&#8203;5183](https://togithub.com/rollup/rollup/pull/5183): Add clippy to pipeline and fix remaining issues ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5184](https://togithub.com/rollup/rollup/pull/5184): docs: fix code example for `onLog` ([@&#8203;tjenkinson](https://togithub.com/tjenkinson))
-   [#&#8203;5186](https://togithub.com/rollup/rollup/pull/5186): Improve wording for native artifacts in migration guide ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5190](https://togithub.com/rollup/rollup/pull/5190): test: add verifyAst type ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5196](https://togithub.com/rollup/rollup/pull/5196): chore(deps): update dependency rollup to v4 ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5197](https://togithub.com/rollup/rollup/pull/5197): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])

### [`v4.0.2`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#402)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.0.1...v4.0.2)

*2023-10-06*

##### Bug Fixes

-   Fix annotation detection logic to not fail when a non-ASCII character precedes a double underscore ([#&#8203;5178](https://togithub.com/rollup/rollup/issues/5178))

##### Pull Requests

-   [#&#8203;5178](https://togithub.com/rollup/rollup/pull/5178): Handle special characters before double underscores ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.0.1`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#401)

[Compare Source](https://togithub.com/rollup/rollup/compare/v4.0.0...v4.0.1)

*2023-10-06*

##### Bug Fixes

-   Do not panic on trailing semicolons after class methods ([#&#8203;5173](https://togithub.com/rollup/rollup/issues/5173))
-   Add artifact for arm64 linux musl target ([#&#8203;5176](https://togithub.com/rollup/rollup/issues/5176))

##### Pull Requests

-   [#&#8203;5172](https://togithub.com/rollup/rollup/pull/5172): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5173](https://togithub.com/rollup/rollup/pull/5173): fix: ignores empty statements in class body that is returned by SWC parser ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5176](https://togithub.com/rollup/rollup/pull/5176): Fix linux arm musl build ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

### [`v4.0.0`](https://togithub.com/rollup/rollup/blob/HEAD/CHANGELOG.md#400)

[Compare Source](https://togithub.com/rollup/rollup/compare/v3.29.4...v4.0.0)

*2023-10-05*

##### BREAKING CHANGES

##### General Changes

-   The minimal required Node version is now 18.0.0 ([#&#8203;5142](https://togithub.com/rollup/rollup/issues/5142))
-   The browser build now relies on a WASM artifact that needs to be provided as well ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   The NodeJS build now relies on an optional native binary; for unsupported platforms, users can use the `@rollup/wasm-node` package that has the same interface as Rollup but relies on WASM artifacts ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   The `INVALID_IMPORT_ASSERTION` error code has been replaced with `INVALID_IMPORT_ATTRIBUTE` ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   Rollup will now warn for `@__PURE__` and `@__NO_SIDE_EFFECTS__` annotations in invalid locations ([#&#8203;5165](https://togithub.com/rollup/rollup/issues/5165))
-   If an entry module starts with a shebang comment `#!...`, this comment will be prepended to the output for `es` and `cjs` formats ([#&#8203;5163](https://togithub.com/rollup/rollup/issues/5163))
-   File hashes will now use url-safe base64 encoded hashes ([#&#8203;5155](https://togithub.com/rollup/rollup/issues/5155))
-   The maximum hash length has been reduced to 22 characters ([#&#8203;5155](https://togithub.com/rollup/rollup/issues/5155))
-   The `RollupWarning` type has been removed in favor of the `RollupLog` type ([#&#8203;5147](https://togithub.com/rollup/rollup/issues/5147))

##### Changes to Rollup Options

-   Acorn plugins are no longer supported, the `acornInjectPlugins` option has been removed ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   The `acorn` option has been removed ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   `output.externalImportAssertions` has been deprecated in favor of `output.externalImportAttributes` ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   `inlineDynamicImports`, `manualChunks` and `preserveModules` have been removed on input option level: Please use the corresponding output options of the same names ([#&#8203;5143](https://togithub.com/rollup/rollup/issues/5143))
-   Removed output options ([#&#8203;5143](https://togithub.com/rollup/rollup/issues/5143)):
    -   `output.experimentalDeepDynamicChunkOptimization`: This option is no longer needed as Rollup now always runs the full chunking algorithm
    -   `output.dynamicImportFunction`: Use the `renderDynamicImport` plugin hook instead
    -   `output.namespaceToStringTag`: Use `output.generatedCode.symbols` instead
    -   `output.preferConst`: Use `output.generatedCode.constBindings` instead

##### Plugin API Changes

-   For `this.resolve`, the default of the `skipSelf` option is now `true` ([#&#8203;5142](https://togithub.com/rollup/rollup/issues/5142))
-   `this.parse` now only supports the `allowReturnOutsideFunction` option for now ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   Import assertions now use the [new import attribute AST structure](https://togithub.com/estree/estree/blob/master/experimental/import-attributes.md) ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   "assertions" have been replaced with "attributes" in various places of the plugin interface ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   If the import of a module id is handled by the `load` hook of a plugin, `rollup.watch` no longer watches the actual file if the module id corresponds to a real path; if this is intended, then the plugin is responsible for calling `this.addWatchFile` for any dependency files ([#&#8203;5150](https://togithub.com/rollup/rollup/issues/5150))
-   The normalized input options provided by `buildStart` and other hooks no longer contain an `onwarn` handler; plugins should use `onLog` instead ([#&#8203;5147](https://togithub.com/rollup/rollup/issues/5147))
-   `this.moduleIds` has been removed from the plugin context: Use `this.getModuleIds()` instead ([#&#8203;5143](https://togithub.com/rollup/rollup/issues/5143))
-   The `hasModuleSideEffects` flag has been removed from the `ModuleInfo` returned by `this.getModuleInfo()`: Use `moduleSideEffects` on the `ModuleInfo` instead ([#&#8203;5143](https://togithub.com/rollup/rollup/issues/5143))

##### Features

-   Improve parsing speed by switching to a native SWC-based parser ([#&#8203;5073](https://togithub.com/rollup/rollup/issues/5073))
-   Rollup will now warn for `@__PURE__` and `@__NO_SIDE_EFFECTS__` annotations in invalid locations ([#&#8203;5165](https://togithub.com/rollup/rollup/issues/5165))
-   The parser is now exposed as a separate export `parseAst` ([#&#8203;5169](https://togithub.com/rollup/rollup/issues/5169))

##### Bug Fixes

-   Rollup no longer tries to watch virtual files if their name corresponds to an actual file name; instead, plugins handle watching via `this.addWatchFile()` ([#&#8203;5150](https://togithub.com/rollup/rollup/issues/5150))

##### Pull Requests

-   [#&#8203;5073](https://togithub.com/rollup/rollup/pull/5073): \[v4.0] Switch parser to SWC and introduce native/WASM code ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5142](https://togithub.com/rollup/rollup/pull/5142): \[v4.0] Set the default of skipSelf to true ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5143](https://togithub.com/rollup/rollup/pull/5143): \[v4.0] Remove deprecated features ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5144](https://togithub.com/rollup/rollup/pull/5144): \[v4.0] Imporve the performance of generating ast and rollup ast nodes ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5147](https://togithub.com/rollup/rollup/pull/5147): \[v4.0] Remove onwarn from normalized input options ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5150](https://togithub.com/rollup/rollup/pull/5150): \[v4.0] feat: Do not watch files anymore if their content is returned by the load hook ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5154](https://togithub.com/rollup/rollup/pull/5154): \[v4.0] Add parse option to allow return outside function ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5155](https://togithub.com/rollup/rollup/pull/5155): \[v4.0] feat: implement hashing content in Rust ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5157](https://togithub.com/rollup/rollup/pull/5157): \[v4.0] Handle empty exports ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5160](https://togithub.com/rollup/rollup/pull/5160): chore(deps): lock file maintenance minor/patch updates ([@&#8203;renovate](https://togithub.com/renovate)\[bot])
-   [#&#8203;5163](https://togithub.com/rollup/rollup/pull/5163): \[v4.0] feat: preserve shebang in entry module for CJS and ESM outputs ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5164](https://togithub.com/rollup/rollup/pull/5164): \[v4.0] fix: also strip BOM from code strings in JS ([@&#8203;TrickyPi](https://togithub.com/TrickyPi))
-   [#&#8203;5165](https://togithub.com/rollup/rollup/pull/5165): \[v4.0] warn for invalid annotations ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5168](https://togithub.com/rollup/rollup/pull/5168): \[v4.0] Ensure we support new import attribute "with" syntax ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))
-   [#&#8203;5169](https://togithub.com/rollup/rollup/pull/5169): \[v4.0] Expose parser ([@&#8203;lukastaegert](https://togithub.com/lukastaegert))

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODcuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-08 06:08:54 +00:00
LongYinan
e93b497231 chore: also set version to helm charts in set-version.sh (#5100) 2023-12-08 13:53:23 +08:00
EYHN
df439877bd fix(core): add requestidlecallback polyfill for safari (#5231) 2023-12-08 05:21:03 +00:00
liuyi
17d584b336 refactor(server): use events system (#5149) 2023-12-08 05:00:58 +00:00
JimmFly
52cfe4521a feat(core): add present to edgeless sharing (#5140) 2023-12-08 04:44:08 +00:00
Peng Xiao
f88e67f5ab fix(core): flaky local avartar test (#5229)
it seems we should not reopen workspace card list just after created a new workspace
2023-12-08 04:01:36 +00:00
Peng Xiao
fcd43033fe fix(electron): sync settings from localStorage -> atom -> electron (#5020)
- moved `appSettingAtom` to infra since we now have different packages that depends on it. There is no better place to fit in for now
- use atomEffect to sync setting changes to updater related configs to Electron side
- refactored how Electron reacts to updater config changes.
2023-12-08 03:20:02 +00:00
Umar Faiz
453d4db713 fix: close font calt to avoid render twinkle (#4969) 2023-12-08 03:08:59 +00:00
Rakhee Singh
780ffd94dc feat(core): added new filter for last n days (#5167)
Co-authored-by: rakhee28 <rakhee@strings.ai>
Co-authored-by: EYHN <cneyhn@gmail.com>
2023-12-08 11:08:15 +08:00
Peng Xiao
5352736eba feat(component): new right sidebar (#5169)
Refactor AFFiNE layout to support new right sidebar.

The new layout:
![image](https://github.com/toeverything/AFFiNE/assets/584378/678a05f5-bd48-4dbe-ad78-7a0bcc979918)

**Highlights:**
- new sidebar UI/UX
- favoring top-down UI components that are composed by basic building blocks in each route, instead of creating universal component like `WorkspaceHeader` that renders every possible cases (which I think is really hard to maintain)
- remove plugin based solution

**Pros/cons for current plugin-based solution:**

The current solution is somewhat a Dependency Injection (DI) approach, where the layout is defined at the top and UI items can be injected using Jotai atom slots.
This approach works well if we want a fully configurable system with everything being handled by plugins. It provides flexibility for custom extensions.
However, this solution is more suitable for single-page applications where the UI is completely controlled by configuration. It becomes challenging to achieve an optimized and visually appealing UI that remains under our control. An example of such a scenario would be a customizable dashboard like Grafana.
Another drawback of the existing solution is that we need to use Jotai and hooks to access context values, resulting in an unclear data flow within the component hierarchy.

**Alternatively, our approach in this PR** provides layout building blocks such as headers and sidebars, which can then be composed in individual route components. The good is that we have cleaner biz component instead of vague all-in-one layout component (like `<WorkspaceHeader />`).

**Issues of the implementation in this PR:**
Some UI layouts that that seems to be defined at the root layout are now defined in individual route component instead.
New 3-col layout component like the right sidebar still needs some abstraction and they are right now just for the detail editor only.
2023-12-08 01:03:48 +00:00
Peng Xiao
980831f9f1 fix(electron): add debug flag for helper process (#5223) 2023-12-07 15:56:09 +00:00
Peng Xiao
ed8e526f71 fix(core): remove duplicate loading component (#5168) 2023-12-07 15:34:10 +00:00
Peng Xiao
352bb548f0 fix(core): update noise image (#5219)
seems https://github.com/toeverything/AFFiNE/pull/4946 not in latest canary.
2023-12-07 15:11:00 +00:00
Joooye_34
761c3c2551 fix(electron): only update db after data changed (#5226) 2023-12-07 12:27:53 +00:00
Joooye_34
70c376fac8 chore(core): skip cloud migration testing until page level upgrade implemented (#5227) 2023-12-07 11:50:24 +00:00
Yifeng Wang
d507c24570 feat: bump blocksuite (#5228) 2023-12-07 19:28:49 +08:00
Yifeng Wang
819f0243d5 feat: bump blocksuite (#5218)
Co-authored-by: LongYinan <lynweklm@gmail.com>
2023-12-07 18:24:23 +08:00
LongYinan
febe5cc2ae ci: fix ts-node scripts (#5225)
- Ref: https://github.com/TypeStrong/ts-node/issues/2094
2023-12-07 09:13:00 +00:00
LongYinan
467d313730 test(server): remove flaky assertion (#5224) 2023-12-07 07:28:24 +00:00
JimmFly
7ec8e49b3b feat(core): add responsive styles to registration page (#5044)
The responsive style of the login and registration page has been adjusted, with special treatment given to the input.
work for #4843
2023-12-06 10:43:14 +00:00
LongYinan
3e92942bb5 ci: remove cache cleanup job because we are sharing cache cross branches (#5214) 2023-12-06 10:32:22 +00:00
LongYinan
1d9454118a ci: reduce cache pressure on non-Linux platform (#5213) 2023-12-06 10:32:18 +00:00
Yifeng Wang
6cbf5b2a92 feat: bump blocksuite (#5194)
Co-authored-by: AyushAgrawal-A2 <ayushagl06@gmail.com>
2023-12-06 18:15:03 +08:00
LongYinan
2dcb5a3030 chore: bump up google-github-actions/auth action to v2 (#5197)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [google-github-actions/auth](https://togithub.com/google-github-actions/auth) | action | major | `v1` -> `v2` |

---

### Release Notes

<details>
<summary>google-github-actions/auth (google-github-actions/auth)</summary>

### [`v2`](https://togithub.com/google-github-actions/auth/releases/tag/v2)

[Compare Source](https://togithub.com/google-github-actions/auth/compare/v1...v2)

Floating v2 alias

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-06 09:57:17 +00:00
LongYinan
93a0349fbc chore: bump up vite version to v4.5.1 [SECURITY] (#5211)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [vite](https://vitejs.dev) ([source](https://togithub.com/vitejs/vite/tree/HEAD/packages/vite)) | [`4.5.0` -> `4.5.1`](https://renovatebot.com/diffs/npm/vite/4.5.0/4.5.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/vite/4.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/4.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/4.5.0/4.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/4.5.0/4.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

### GitHub Vulnerability Alerts

#### [CVE-2023-49293](https://togithub.com/vitejs/vite/security/advisories/GHSA-92r3-m2mg-pj97)

### Summary
When Vite's HTML transformation is invoked manually via `server.transformIndexHtml`, the original request URL is passed in unmodified, and the `html` being transformed contains inline module scripts (`<script type="module">...</script>`), it is possible to inject arbitrary HTML into the transformed output by supplying a malicious URL query string to `server.transformIndexHtml`.

### Impact
Only apps using `appType: 'custom'` and using the default Vite HTML middleware are affected. The HTML entry must also contain an inline script. The attack requires a user to click on a malicious URL while running the dev server. Restricted files aren't exposed to the attacker.

### Patches
Fixed in vite@5.0.5, vite@4.5.1, vite@4.4.12

### Details
Suppose `index.html` contains an inline module script:

```html
<script type="module">
  // Inline script
</script>
```

This script is transformed into a proxy script like

```html
<script type="module" src="/index.html?html-proxy&index=0.js"></script>
```

due to Vite's HTML plugin:

7fd7c6cebf/packages/vite/src/node/plugins/html.ts (L429-L465)

When `appType: 'spa' | 'mpa'`, Vite serves HTML itself, and `htmlFallbackMiddleware` rewrites `req.url` to the canonical path of `index.html`,

73ef074b80/packages/vite/src/node/server/middlewares/htmlFallback.ts (L44-L47)

so the `url` passed to `server.transformIndexHtml` is `/index.html`.

However, if `appType: 'custom'`, HTML is served manually, and if `server.transformIndexHtml` is called with the unmodified request URL (as the SSR docs suggest), then the path of the transformed `html-proxy` script varies with the request URL. For example, a request with path `/` produces

```html
<script type="module" src="/@&#8203;id/__x00__/index.html?html-proxy&index=0.js"></script>
```

It is possible to abuse this behavior by crafting a request URL to contain a malicious payload like

```
"></script><script>alert('boom')</script>
```

so a request to http://localhost:5173/?%22%3E%3C/script%3E%3Cscript%3Ealert(%27boom%27)%3C/script%3E produces HTML output like

```html
<script type="module" src="/@&#8203;id/__x00__/?"></script><script>alert("boom")</script>?html-proxy&index=0.js"></script>
```

which demonstrates XSS.

### PoC

- Example 1. Serving HTML from `vite dev` middleware with `appType: 'custom'`
    - Go to https://stackblitz.com/edit/vitejs-vite-9xhma4?file=main.js&terminal=dev-html
    - "Open in New Tab"
    - Edit URL to set query string to `?%22%3E%3C/script%3E%3Cscript%3Ealert(%27boom%27)%3C/script%3E` and navigate
    - Witness XSS:
    - ![image](https://user-images.githubusercontent.com/2456381/287434281-13757894-7a63-4a73-b1e9-d2b024c19d14.png)
- Example 2. Serving HTML from SSR-style Express server (Vite dev server runs in middleware mode):
    - Go to https://stackblitz.com/edit/vitejs-vite-9xhma4?file=main.js&terminal=server
    - (Same steps as above)
- Example 3. Plain `vite dev` (this shows that vanilla `vite dev` is _not_ vulnerable, provided `htmlFallbackMiddleware` is used)
    - Go to https://stackblitz.com/edit/vitejs-vite-9xhma4?file=main.js&terminal=dev
    - (Same steps as above)
    - You should _not_ see the alert box in this case

### Detailed Impact

This will probably predominantly affect [development-mode SSR](https://vitejs.dev/guide/ssr#setting-up-the-dev-server), where `vite.transformHtml` is called using the original `req.url`, per the docs:

7fd7c6cebf/docs/guide/ssr.md (L114-L126)

However, since this vulnerability affects `server.transformIndexHtml`, the scope of impact may be higher to also include other ad-hoc calls to `server.transformIndexHtml` from outside of Vite's own codebase.

My best guess at bisecting which versions are vulnerable involves the following test script

```js
import fs from 'node:fs/promises';
import * as vite from 'vite';

const html = `
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <script type="module">
      // Inline script
    </script>
  </body>
</html>
`;
const server = await vite.createServer({ appType: 'custom' });
const transformed = await server.transformIndexHtml('/?%22%3E%3C/script%3E%3Cscript%3Ealert(%27boom%27)%3C/script%3E', html);
console.log(transformed);
await server.close();
```

and using it I was able to narrow down to #&#8203;13581. If this is correct, then vulnerable Vite versions are 4.4.0-beta.2 and higher (which includes 4.4.0).

---

### Release Notes

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

### [`v4.5.1`](https://togithub.com/vitejs/vite/releases/tag/v4.5.1)

[Compare Source](https://togithub.com/vitejs/vite/compare/v4.5.0...v4.5.1)

Please refer to [CHANGELOG.md](https://togithub.com/vitejs/vite/blob/v4.5.1/packages/vite/CHANGELOG.md) for details.

</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 these updates again.

---

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

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-06 08:55:32 +00:00
Peng Xiao
2b53430539 feat(core): allow core modules to import itself (#5207) 2023-12-06 08:45:54 +00:00
liuyi
e0cada49f5 refactor(server): do not force init binary when creating workspace (#5146) 2023-12-06 08:35:48 +00:00
liuyi
4cb26cd3e5 feat(server): events system (#5145) 2023-12-06 08:35:45 +00:00
JimmFly
b32a427ecd chore: adjust banner content text (#5153)
![image](https://github.com/toeverything/AFFiNE/assets/102217452/86a77f1f-1be5-4d05-bdfa-9e1b321c0d9e)
2023-12-06 08:13:56 +00:00
LongYinan
e5f8a58330 ci: refactor workflow (#5139)
Merge tests job into single one, reuse job as much as possible
2023-12-06 08:03:05 +00:00
Joooye_34
48f4d6a06c fix(core): error page 500 status dark mode (#5180)
close #5155
2023-12-05 10:40:48 +00:00
LongYinan
246fbd8d4f ci: fix auto labeler config 2023-12-05 18:21:32 +08:00
LongYinan
bd414b7f44 ci: fix auto labeler job (#5206) 2023-12-05 18:00:42 +08:00
Peng Xiao
1e01ed0b0f fix(component): modal blurness (#5177)
moved https://github.com/toeverything/design/pull/108

Do not use transform to center the modal. It has know issue to cause modal to have blurred texts.

https://github.com/radix-ui/website/issues/383

fix https://github.com/toeverything/AFFiNE/issues/5176
2023-12-05 09:18:49 +00:00
LongYinan
37b1a54ec6 chore: bump up idb version to v8 (#5198)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

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

---

### Release Notes

<details>
<summary>jakearchibald/idb (idb)</summary>

### [`v8.0.0`](https://togithub.com/jakearchibald/idb/compare/v7.1.1...v8.0.0)

[Compare Source](https://togithub.com/jakearchibald/idb/compare/v7.1.1...v8.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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-05 08:38:04 +00:00
JimmFly
1c88e1fb8b fix(core): unable to create share page link (#5175)
For some reasons, our `spaceDoc.guid` and `page.id` may not necessarily be the same, so we switched to using the more accurate `page.id`.
2023-12-05 07:21:18 +00:00
Cats Juice
1cd8de9d60 fix(component): clear page list operation's link style (#5148)
- before
  ![CleanShot 2023-12-01 at 12 03 24@2x](https://github.com/toeverything/AFFiNE/assets/39363750/6951ee61-d3c3-43b3-8949-fe6ed9ceb99e)
- after
  ![CleanShot 2023-12-01 at 12 08 02@2x](https://github.com/toeverything/AFFiNE/assets/39363750/2a85e5f7-9156-4aef-81a2-76d66a673ebd)
2023-12-05 07:01:42 +00:00
LongYinan
51e42af317 chore: bump up actions/labeler action to v5 (#5192)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/labeler](https://togithub.com/actions/labeler) | action | major | `v4` -> `v5` |

---

### Release Notes

<details>
<summary>actions/labeler (actions/labeler)</summary>

### [`v5`](https://togithub.com/actions/labeler/compare/v4...v5)

[Compare Source](https://togithub.com/actions/labeler/compare/v4...v5)

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-05 06:41:21 +00:00
LongYinan
e4c6db2d02 chore: bump up ava version to v6 (#5195)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

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

---

### Release Notes

<details>
<summary>avajs/ava (ava)</summary>

### [`v6.0.0`](https://togithub.com/avajs/ava/releases/tag/v6.0.0)

[Compare Source](https://togithub.com/avajs/ava/compare/v5.3.1...v6.0.0)

#### Breaking Changes

-   AVA now requires Node.js versions 18.18, 20.8 or 21. Versions 14 and 16 are no longer supported. [#&#8203;3251](https://togithub.com/avajs/ava/issues/3251) [#&#8203;3216](https://togithub.com/avajs/ava/issues/3216)

-   When tests finish, worker threads or child processes are no longer exited through `proces.exit()`. If your test file does not exit on its own, the test run will time out. [#&#8203;3260](https://togithub.com/avajs/ava/issues/3260)

-   Changes to watch mode [#&#8203;3218](https://togithub.com/avajs/ava/issues/3218):
    -   Watch mode can no longer be started via the `ava.config.*` or `package.json` configuration.
    -   The `ignoredByWatcher` configuration has moved to the `watchMode` object, under the `ignoreChanges` key.
    -   Watch mode now uses the built-in [`fs.watch()`](https://nodejs.org/api/fs.html#fswatchfilename-options-listener) in recursive mode. This is supported on Linux in Node.js 20 or newer, and MacOS and Windows in Node.js 18 as well. There are [caveats](https://nodejs.org/api/fs.html#caveats) to keep in mind.

-   Failed assertions now throw, meaning that any subsequent code is not executed. This also impacts the type definitions. [#&#8203;3246](https://togithub.com/avajs/ava/issues/3246)

-   [Only native errors](https://nodejs.org/api/util.html#utiltypesisnativeerrorvalue) are now considered errors by the `t.throws()` and `t.throwsAsync()` assertions. [`Object.create(Error.prototype)` is **not** a native error](Object.create\(Error.prototype\)). [#&#8203;3229](https://togithub.com/avajs/ava/issues/3229)

-   Changes to modules loaded through the `require` configuration [#&#8203;3184](https://togithub.com/avajs/ava/issues/3184):
    -   If such modules export a default function, this function is now invoked.
    -   Local files are loaded through `@ava/typescript` if necessary.

#### Improvements

##### Rewritten watcher

The watcher has been rewritten. It’s now built on [`fs.watch()`](https://nodejs.org/api/fs.html#fswatchfilename-options-listener) in recursive mode.

[`@vercel/nft`](https://togithub.com/vercel/nft)  is used to perform static dependency analysis, supporting ESM and CJS imports for JavaScript & TypeScript source files. This is a huge improvement over the previous runtime tracking of CJS imports, which did not support ESM.

Integration with [`@ava/typescript`](https://togithub.com/avajs/typescript) has been improved. The watcher can now detect a change to a TypeScript source file, then wait for the corresponding build output to change before re-running tests.

The ignoredByWatcher configuration has moved to the watchMode object, under the ignoreChanges key.

See [#&#8203;3218](https://togithub.com/avajs/ava/issues/3218) and [#&#8203;3257](https://togithub.com/avajs/ava/issues/3257).

##### Failed assertions now throw

Assertions now throw a `TestFailure` error when they fail. This error is not exported or documented and should not be used or thrown manually. You cannot catch this error in order to recover from a failure, use `t.try()` instead.

All assertions except for `t.throws()` and `t.throwsAsync()` now return `true` when they pass. This is useful for some of the assertions in TypeScript where they can be used as a type guard.

Committing a failed `t.try()` result now also throws.

See [#&#8203;3246](https://togithub.com/avajs/ava/issues/3246).

##### `t.throws()` and `t.throwsAsync()` can now expect any error

By default, the thrown error (or rejection reason) must be a native error. You can change the assertion to expect any kind of error by setting `any: true` in the expectation object:

```js
t.throws(() => { throw 'error' }, {any: true})
```

See [#&#8203;3245](https://togithub.com/avajs/ava/issues/3245) by [@&#8203;adiSuper94](https://togithub.com/adiSuper94).

##### The `require` configuration is now more powerful

It now loads ES modules.

Local files are loaded through `@ava/typescript` if necessary, so you can also write these in TypeScript.

If there is a default export function, it is invoked after loading. The function is awaited so it can do asynchronous setup before further modules are loaded. Arguments from the configuration can be passed to the function (as a \[[structured clone](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone)]\(https://developer.mozilla.org/en-US/docs/Web/API/structuredClone)).

See [#&#8203;3184](https://togithub.com/avajs/ava/issues/3184) by [@&#8203;sculpt0r](https://togithub.com/sculpt0r).

##### Other changes worth noting

-   Internal events can now be observed (experimentally). See [#&#8203;3247](https://togithub.com/avajs/ava/issues/3247) by [@&#8203;codetheweb](https://togithub.com/codetheweb). It’s experimental and undocumented.
-   You can now use `t.timeout.clear()` to restore a previous `t.timeout()`. [#&#8203;3221](https://togithub.com/avajs/ava/issues/3221)
-   Code coverage is flushed to disk at opportune moments. [#&#8203;3220](https://togithub.com/avajs/ava/issues/3220)

#### New Contributors

-   [@&#8203;sculpt0r](https://togithub.com/sculpt0r) made their first contribution in [https://github.com/avajs/ava/pull/3184](https://togithub.com/avajs/ava/pull/3184)
-   [@&#8203;ZachHaber](https://togithub.com/ZachHaber) made their first contribution in [https://github.com/avajs/ava/pull/3233](https://togithub.com/avajs/ava/pull/3233)
-   [@&#8203;adiSuper94](https://togithub.com/adiSuper94) made their first contribution in [https://github.com/avajs/ava/pull/3245](https://togithub.com/avajs/ava/pull/3245)
-   [@&#8203;bricker](https://togithub.com/bricker) made their first contribution in [https://github.com/avajs/ava/pull/3250](https://togithub.com/avajs/ava/pull/3250)

**Full Changelog**: https://github.com/avajs/ava/compare/v5.3.1...v6.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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-05 06:19:00 +00:00
Anthony
56ace48226 feat: add new page to the sidebar #5095 (#5128)
Co-authored-by: 李华桥 <joooye1991@gmail.com>
2023-12-05 14:18:21 +08:00
LongYinan
2b7c6714eb chore: bump up Helm release postgresql to v13 (#5190)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [postgresql](https://bitnami.com) ([source](https://togithub.com/bitnami/charts/tree/HEAD/bitnami/postgresql)) | major | `12.5.8` -> `13.2.23` |

---

### 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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-05 04:26:32 +00:00
LongYinan
1dacb21178 chore: bump up @dnd-kit/modifiers version to v7 (#5189)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@dnd-kit/modifiers](https://togithub.com/clauderic/dnd-kit) ([source](https://togithub.com/clauderic/dnd-kit/tree/HEAD/packages/modifiers)) | [`^6.0.1` -> `^7.0.0`](https://renovatebot.com/diffs/npm/@dnd-kit%2fmodifiers/6.0.1/7.0.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@dnd-kit%2fmodifiers/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@dnd-kit%2fmodifiers/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@dnd-kit%2fmodifiers/6.0.1/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@dnd-kit%2fmodifiers/6.0.1/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>clauderic/dnd-kit (@&#8203;dnd-kit/modifiers)</summary>

### [`v7.0.0`](https://togithub.com/clauderic/dnd-kit/blob/HEAD/packages/modifiers/CHANGELOG.md#700)

[Compare Source](https://togithub.com/clauderic/dnd-kit/compare/@dnd-kit/modifiers@6.0.1...@dnd-kit/modifiers@7.0.0)

##### Patch Changes

-   Updated dependencies \[[`bc588c7`](bc588c7f7b), [`b417f0f`](b417f0f94b), [`f342d5e`](f342d5efd9)]:
    -   [@&#8203;dnd-kit/core](https://togithub.com/dnd-kit/core)[@&#8203;6](https://togithub.com/6).1.0
    -   [@&#8203;dnd-kit/utilities](https://togithub.com/dnd-kit/utilities)[@&#8203;3](https://togithub.com/3).2.2

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-05 04:05:29 +00:00
LongYinan
f3e717ee5f chore: bump up @opentelemetry/instrumentation-ioredis version to ^0.36.0 (#5186)
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@opentelemetry/instrumentation-ioredis](https://togithub.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-ioredis#readme) ([source](https://togithub.com/open-telemetry/opentelemetry-js-contrib)) | [`^0.35.3` -> `^0.36.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-ioredis/0.35.3/0.36.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@opentelemetry%2finstrumentation-ioredis/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@opentelemetry%2finstrumentation-ioredis/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@opentelemetry%2finstrumentation-ioredis/0.35.3/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@opentelemetry%2finstrumentation-ioredis/0.35.3/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>open-telemetry/opentelemetry-js-contrib (@&#8203;opentelemetry/instrumentation-ioredis)</summary>

### [`v0.36.0`](607d375595...a757b5e443)

[Compare Source](607d375595...a757b5e443)

</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 has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy44MS4zIiwidXBkYXRlZEluVmVyIjoiMzcuODEuMyIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSJ9-->
2023-12-05 03:46:25 +00:00
LongYinan
9e8668de6b ci: add electron-forge deps group (#5185) 2023-12-05 03:27:36 +00:00
LongYinan
eb93ae04e0 ci: exclude @blocksuite/icons from blocksuite nightly update group (#5184) 2023-12-05 02:45:55 +00:00
LongYinan
a9b021bafe ci: use renovate to replace dependabot since depedabot has never worked (#5182)
https://github.com/toeverything/AFFiNE/network/updates/757631626 dependabot update jobs keep timeout
2023-12-05 00:47:40 +00:00
LongYinan
56b37c481e chore: bump @adobe/css-tools from 4.3.1 to 4.3.2 (#5181)
Bumps [@adobe/css-tools](https://github.com/adobe/css-tools) from 4.3.1 to 4.3.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/adobe/css-tools/blob/main/History.md"><code>@​adobe/css-tools</code>'s changelog</a>.</em></p>
<blockquote>
<h1>4.3.2 / 2023-11-28</h1>
<ul>
<li>Fix redos vulnerability with specific crafted css string - CVE-2023-48631</li>
<li>Fix Problem parsing with :is() and nested :nth-child() <a href="https://redirect.github.com/adobe/css-tools/issues/211">#211</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/adobe/css-tools/commits">compare view</a></li>
</ul>
</details>
<br />

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@adobe/css-tools&package-manager=npm_and_yarn&previous-version=4.3.1&new-version=4.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/toeverything/AFFiNE/network/alerts).

</details>
2023-12-04 14:59:50 +00:00
Flrande
a2784c352f chore: bump blocksuite (#5138) 2023-12-04 12:02:35 +00:00
EYHN
7878ce5c2c feat(workspace): priority load opened page (#5156) 2023-12-04 11:32:10 +00:00
liuyi
b4b4a3b625 fix(server): avoid snapshot write conflict (#5174) 2023-12-04 11:12:16 +00:00
Cats Juice
d911d21d1c feat(component): add storybook (#5079) 2023-12-04 08:32:19 +00:00
Cats Juice
9c50dbc362 feat(core): remove all imports from design/component (#5078)
feat(core): remove all imports from design/component

feat(plugin): remove imports from design-components

feat(storybook): remove design-components imoprts

feat(core): remove

fix(component): remove design/component import in local-demo-tip
2023-12-04 08:32:16 +00:00
Cats Juice
0abadbe7bb refactor(component): migrate design components (#5000)
```[tasklist]
### Tasks
- [x] Migrate components from [design](https://github.com/toeverything/design)
- [x] Replace all imports from `@toeverything/components`
- [x] Clean up `@toeverything/components` dependencies
- [x] Storybook
```

### Influence

Here are all the components that are influenced by `@toeverything/components`

- `@affine/component`
    - App update `Button` `Tooltip`
    - App sidebar header `IconButton`, `Tooltip`
    - Back `Button`
    - Auth
      - Change email page save `Button`
      - Change password page all `Button`s (Save, Later, Open)
      - Confirm change email `Button`
      - Set password page `Button`
      - Sign in success page `Button`
      - Sign up page `Button`
      - Auth `Modal`
    - Workspace card `Avatar`, `Divider`, `Tooltip`, `IconButton`
    - Share
      - Disable shared public link `Modal`
    - Import page `IconButton`, `Tooltip`
    - Accept invite page `Avatar`, `Button`
    - Invite member `Modal`
    - 404 Page `Avatar`, `Button`, `IconButton`, `Tooltip`
    - Notification center `IconButton`
    - Page list
      - operation cell `IconButton`, `Menu`, `ConfirmModal`, `Tooltip`
      - tags more `Menu`
      - favorite `IconButton`, `Tooltip`
      - new page dropdown `Menu`
      - filter `Menu`, `Button`, `IconButton`
    - Page operation `Menu`
      - export `MenuItem`
      - move to trash `MenuItem`, `ConfirmModal`
    - Workspace header filter `Menu`, `Button`
    - Collection bar `Button`, `Tooltip` (*⚠️ seems not used*)
    - Collection operation `Menu`, `MenuItem`
      - Create collection `Modal`, `Button`
      - Edit collection `Modal`, `Button`
      - Page mode filter `Menu`
      - Page mode `Button`, `Menu`
    - Setting modal
      - storage usage progress `Button`, `Tooltip`
    - On boarding tour `Modal`
- `@affine/core`
  - Bookmark `Menu`
  - Affine error boundary `Button`
  - After sign in send email `Button`
  - After sign up send email `Button`
  - Send email `Button`
  - Sign in `Button`
  - Subscription redirect `Loading`, `Button`
  - Setting `Modal`
    - User plan button `Tooltip`
    - Members `Avatar`, `Button`, `IconButton`, `Loading`, `Tooltip`, `Menu`
    - Profile `Button`, `Avatar`
    - Workspace
      - publish panel `Button`, `Tooltip`
      - export panel `Button`
      - storage panel `Button`, `Tooltip`
      - delete `ConfirmModal`
    - Language `Menu`
    - Account setting `Avatar`, `Button`
    - Date format setting `Menu`
    - Billing `Button`, `IconButton`, `Loading`
    - Payment plans `Button`, `ConfirmModal`, `Modal`, `Tooltip`
  - Create workspace `Modal`, `ConfirmModal`, `Button`
  - Payment disabled `ConfirmModal`
  - Share/Export `Menu`, `Button`, `Divider`
  - Sign out `ConfirmModal`
  - Temp disable affine cloud `Modal`
  - Page detail operation `Menu`
  - Blocksuite mode switch `Tooltip`
  - Login card `Avatar`
  - Help island `Tooltip`
- `plugin`
  - copilot
  - hello world
  - image preview
  - outline
2023-12-04 08:32:12 +00:00
LongYinan
33c53217c3 chore: move cargo fmt to lint-staged from pre-commit (#5150) 2023-12-04 06:42:54 +00:00
EYHN
91f3149148 fix(workspace): fix svg display on browser (#5158) 2023-12-02 17:27:07 +00:00
Rakhee Singh
661b4a91ba style(core): add page list header emptypage (#5162)
Co-authored-by: rakhee28 <rakhee@strings.ai>
2023-12-02 23:39:51 +08:00
Peng Xiao
512504e177 fix(electron): do not restore window on get window (#5163)
fix https://github.com/toeverything/AFFiNE/issues/5161

Looks like I used window.restore incorrectly.
2023-12-02 15:13:48 +00:00
LongYinan
1f7654e80f chore: bump @adobe/css-tools from 4.3.1 to 4.3.2 (#5154)
Bumps [@adobe/css-tools](https://github.com/adobe/css-tools) from 4.3.1 to 4.3.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/adobe/css-tools/blob/main/History.md"><code>@​adobe/css-tools</code>'s changelog</a>.</em></p>
<blockquote>
<h1>4.3.2 / 2023-11-28</h1>
<ul>
<li>Fix redos vulnerability with specific crafted css string - CVE-2023-48631</li>
<li>Fix Problem parsing with :is() and nested :nth-child() <a href="https://redirect.github.com/adobe/css-tools/issues/211">#211</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/adobe/css-tools/commits">compare view</a></li>
</ul>
</details>
<br />

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@adobe/css-tools&package-manager=npm_and_yarn&previous-version=4.3.1&new-version=4.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/toeverything/AFFiNE/network/alerts).

</details>
2023-12-01 08:52:40 +00:00
李华桥
120e7397ba Merge branch 'canary' into stable 2023-12-01 16:12:17 +08:00
Joooye_34
eb7d293aaa fix(core): implement editor timeout and report error from boundary (#5105) (#5151)
fix(core): implement editor timeout and report error from boundary (#5105)

ci: add sentry env when frontend assets build (#5131)

fix(core): expose catched editor load error (#5133)

fix(infra): use blocksuite api to check compatibility (#5137)

fix(infra): compatibility logic follow blocksuite (#5143)

fix(core): rerender error boundary when route change and improve sentry report (#5147)
2023-12-01 07:25:08 +00:00
李华桥
24123ad01c Revert "Revert "Merge remote-tracking branch 'origin/canary' into stable""
This reverts commit 89197bacef.
2023-12-01 13:29:43 +08:00
LongYinan
99f98fb9d3 ci: remove publish job (#5135) 2023-11-30 04:24:43 +00:00
JimmFly
3e662f358d fix(core): adjust ui styles (#5094) 2023-11-30 12:23:57 +08:00
Peng Xiao
6661e8bd9a fix(core): language display names (#5123) 2023-11-30 12:23:03 +08:00
JimmFly
23518cae16 feat(core): add manual check for updates (#4957)
work for #4523

add `appBuildType` to `runtimeConfig`
add `useAppUpdater` to manage client updates

<!--
copilot:summary
-->
### <samp>🤖[[deprecated]](https://githubnext.com/copilot-for-prs-sunset) Generated by Copilot at cdd012c</samp>

This pull request refactors and enhances the update functionality for the frontend. It introduces a new custom hook `useAppUpdater` that simplifies the update logic and state management, and uses it in various components and commands. It also adds more options and feedback for the user to control and monitor the update process, such as manual download, auto-check, and auto-download toggles, and update status and progress indicators. It also updates the `AboutAffine` component to show the app icon, version, and build type. It also adds new translations, dependencies, types, and schemas related to the update functionality.

<img width="1073" alt="image" src="https://github.com/toeverything/AFFiNE/assets/102217452/16ae7a6a-0035-4e57-902b-6b8f63169501">
2023-11-29 13:31:25 +00:00
LongYinan
906d224fa9 chore(native): fix useless import (#5130) 2023-11-29 10:11:40 +00:00
LongYinan
6fca1b43f0 chore: add rust-toolchain file (#5129) 2023-11-29 10:11:38 +00:00
LongYinan
3fc515491b chore: remove useless circular command (#5127) 2023-11-29 10:11:36 +00:00
LongYinan
2a4741e9ab chore: add lint-staged command to pre-commit file (#5126) 2023-11-29 10:11:34 +00:00
LongYinan
feddfdc5c9 ci: upgrade setup-node action (#5125) 2023-11-29 10:11:32 +00:00
LongYinan
a2b8a073cc ci: pr title lint job does not need to install all dependencies (#5124) 2023-11-29 09:51:14 +00:00
liuyi
89f267a3fe refactor(server): simplify metrics creation and usage (#5115) 2023-11-29 08:05:08 +00:00
LongYinan
7a7cbc45d7 fix: add prefer-readonly rule (#5122) 2023-11-29 15:19:00 +08:00
LongYinan
e9ea67bd38 fix: add prefer-for-of rule (#5121) 2023-11-29 15:18:52 +08:00
LongYinan
acf2de813a fix: add unified-signatures rule (#5120) 2023-11-29 04:44:18 +00:00
LongYinan
db3039fbf4 fix: add require-array-sort-compare rule (#5119) 2023-11-29 04:44:14 +00:00
LongYinan
eadf8a085b fix: add prefer-blob-reading-methods rule (#5118) 2023-11-29 04:44:10 +00:00
LongYinan
cb2c659f52 fix: add no-new-array rule (#5117) 2023-11-29 04:44:06 +00:00
LongYinan
68caf5027d fix: add new-for-builtins rule (#5116) 2023-11-29 04:44:02 +00:00
LongYinan
19c61e051d fix: add no-typeof-undefined rule (#5114) 2023-11-29 04:43:59 +00:00
LongYinan
bd488262fa fix: add prefer-date-now rule (#5113) 2023-11-29 04:43:55 +00:00
LongYinan
4dddbbdaee fix: add prefer-dom-node-remove rule (#5112) 2023-11-29 04:43:51 +00:00
LongYinan
45690c2756 fix: add no-useless-promise-resolve-reject rule (#5111) 2023-11-29 04:43:47 +00:00
LongYinan
d267029761 fix: add prefer-array-some rule (#5109) 2023-11-29 04:43:43 +00:00
LongYinan
23cfc58fe2 fix: add prefer-dom-node-append rule (#5108) 2023-11-29 04:43:39 +00:00
LongYinan
123f091e5b fix: add prefer-dom-node-dataset rule (#5107) 2023-11-29 04:43:35 +00:00
LongYinan
923844f302 fix: add eqeqeq lint rule (#5106) 2023-11-29 04:43:31 +00:00
LongYinan
a843dcd851 fix: resolve cycle imports and prevent it by oxlint (#5103) 2023-11-29 04:43:27 +00:00
LongYinan
b73e87e4ad chore: upgrade typescript-eslint (#5110) 2023-11-29 04:43:23 +00:00
JimmFly
c78eb96507 feat(core): show searched result with results group and add duplicate commands (#5073)
[TOV-65](https://linear.app/affine-design/issue/TOV-65/should-show-searched-result-without-categories)

https://github.com/toeverything/AFFiNE/assets/102217452/50fba70b-7efa-4e47-ba8a-de21e400166c
2023-11-29 02:35:13 +00:00
JimmFly
469a18f794 feat(component): default collapse and float sidebar on mobile (#5077)
work for #4843

https://github.com/toeverything/AFFiNE/assets/102217452/c658dbab-4db8-4065-a3a6-3e20274b6cb9
2023-11-29 02:12:13 +00:00
LongYinan
c1cf25d2d5 style: add no-self-compare rule (#5092) 2023-11-28 08:55:50 +00:00
Peng Xiao
890e3e4435 fix(core): should not refetch avatar when url does not change (#5070)
blob resources are in fact immutable. We do not need to refetch it by swr policies (mount/visibilitychange/etc)
2023-11-28 08:01:19 +00:00
LongYinan
0ee2ecc1e9 ci: always perform fresh build in deployment job (#5066) 2023-11-28 06:59:50 +00:00
LongYinan
aaaed5ac14 fix(core): nx cache configuration (#5065) 2023-11-28 06:59:48 +00:00
532 changed files with 14521 additions and 7358 deletions

View File

@@ -126,6 +126,8 @@ const config = {
'no-cond-assign': 'off',
'no-constant-binary-expression': 'error',
'no-constructor-return': 'error',
'no-self-compare': 'error',
eqeqeq: ['error', 'always', { null: 'ignore' }],
'react/prop-types': 'off',
'react/jsx-no-useless-fragment': 'error',
'@typescript-eslint/consistent-type-imports': 'error',
@@ -133,6 +135,9 @@ const config = {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/require-array-sort-compare': 'error',
'@typescript-eslint/unified-signatures': 'error',
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/no-unused-vars': [
'error',
{
@@ -204,6 +209,17 @@ const config = {
},
],
'unicorn/no-unnecessary-await': 'error',
'unicorn/no-useless-fallback-in-spread': 'error',
'unicorn/prefer-dom-node-dataset': 'error',
'unicorn/prefer-dom-node-append': 'error',
'unicorn/prefer-dom-node-remove': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-date-now': 'error',
'unicorn/prefer-blob-reading-methods': 'error',
'unicorn/no-typeof-undefined': 'error',
'unicorn/no-useless-promise-resolve-reject': 'error',
'unicorn/no-new-array': 'error',
'unicorn/new-for-builtins': 'error',
'sonarjs/no-all-duplicated-branches': 'error',
'sonarjs/no-element-overwrite': 'error',
'sonarjs/no-empty-collection': 'error',
@@ -254,6 +270,7 @@ const config = {
},
],
'@typescript-eslint/no-misused-promises': ['error'],
'@typescript-eslint/prefer-readonly': 'error',
'i/no-extraneous-dependencies': ['error'],
'react-hooks/exhaustive-deps': [
'warn',

View File

@@ -14,14 +14,28 @@ inputs:
runs:
using: 'composite'
steps:
- name: Print rustup toolchain version
shell: bash
id: rustup-version
run: |
export RUST_TOOLCHAIN_VERSION="$(grep 'channel' rust-toolchain.toml | head -1 | awk -F '"' '{print $2}')"
echo "Rust toolchain version: $RUST_TOOLCHAIN_VERSION"
echo "RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION" >> "$GITHUB_OUTPUT"
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
toolchain: '${{ steps.rustup-version.outputs.RUST_TOOLCHAIN_VERSION }}'
targets: ${{ inputs.target }}
env:
CARGO_INCREMENTAL: '1'
- name: Set CC
if: ${{ contains(inputs.target, 'linux') && inputs.package != '@affine/native' }}
shell: bash
run: |
echo "CC=clang" >> "$GITHUB_ENV"
echo "TARGET_CC=clang" >> "$GITHUB_ENV"
- name: Cache cargo
uses: actions/cache@v3
with:
@@ -29,47 +43,13 @@ runs:
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
.cargo-cache
~/.napi-rs
target/${{ inputs.target }}
key: stable-${{ inputs.target }}-cargo-cache
- name: Build
if: ${{ inputs.target != 'x86_64-unknown-linux-gnu' && inputs.target != 'aarch64-unknown-linux-gnu' }}
shell: bash
run: |
yarn workspace ${{ inputs.package }} nx build ${{ inputs.package }} --target ${{ inputs.target }}
yarn workspace ${{ inputs.package }} nx build ${{ inputs.package }} --target ${{ inputs.target }} --use-napi-cross
env:
NX_CLOUD_ACCESS_TOKEN: ${{ inputs.nx_token }}
- name: Build
if: ${{ inputs.target == 'x86_64-unknown-linux-gnu' }}
uses: addnab/docker-run-action@v3
with:
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
options: --user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build -e NX_CLOUD_ACCESS_TOKEN=${{ inputs.nx_token }}
run: |
export CC=x86_64-unknown-linux-gnu-gcc
export CC_x86_64_unknown_linux_gnu=x86_64-unknown-linux-gnu-gcc
export RUSTFLAGS="-C debuginfo=1"
yarn workspace ${{ inputs.package }} nx build ${{ inputs.package }} --target ${{ inputs.target }}
if [ -d "node_modules/.cache" ]; then
chmod -R 777 node_modules/.cache
fi
if [ -d "target" ]; then
chmod -R 777 target;
fi
- name: Build
if: ${{ inputs.target == 'aarch64-unknown-linux-gnu' }}
uses: addnab/docker-run-action@v3
with:
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
options: --user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build -e NX_CLOUD_ACCESS_TOKEN=${{ inputs.nx_token }}
run: |
export RUSTFLAGS="-C debuginfo=1"
yarn workspace ${{ inputs.package }} nx build ${{ inputs.package }} --target ${{ inputs.target }}
if [ -d "node_modules/.cache" ]; then
chmod -R 777 node_modules/.cache
fi
if [ -d "target" ]; then
chmod -R 777 target;
fi
DEBUG: 'napi:*'

View File

@@ -26,7 +26,7 @@ runs:
echo "GIT_SHORT_HASH=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
- uses: azure/setup-helm@v3
- id: auth
uses: google-github-actions/auth@v1
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 }}'
@@ -34,7 +34,7 @@ runs:
project_id: '${{ inputs.gcp-project-id }}'
- name: 'Setup gcloud cli'
uses: 'google-github-actions/setup-gcloud@v1'
uses: 'google-github-actions/setup-gcloud@v2'
with:
install_components: 'gke-gcloud-auth-plugin'

View File

@@ -1,6 +1,7 @@
import { execSync } from 'node:child_process';
const {
APP_VERSION,
BUILD_TYPE,
DEPLOY_HOST,
CANARY_DEPLOY_HOST,
@@ -79,6 +80,7 @@ const createHelmCommand = ({ isDryRun }) => {
`--set global.ingress.enabled=true`,
`--set-json global.ingress.annotations=\"{ \\"kubernetes.io/ingress.class\\": \\"gce\\", \\"kubernetes.io/ingress.allow-http\\": \\"true\\", \\"kubernetes.io/ingress.global-static-ip-name\\": \\"${staticIpName}\\" }\"`,
`--set-string global.ingress.host="${host}"`,
`--set-string global.version="${APP_VERSION}"`,
...redisAndPostgres,
`--set web.replicaCount=${webReplicaCount}`,
`--set-string web.image.tag="${imageTag}"`,
@@ -105,7 +107,7 @@ const createHelmCommand = ({ isDryRun }) => {
`--set sync.replicaCount=${syncReplicaCount}`,
`--set-string sync.image.tag="${imageTag}"`,
...serviceAnnotations,
`--version "0.0.0-${buildType}.${GIT_SHORT_HASH}" --timeout 10m`,
`--timeout 10m`,
flag,
].join(' ');
return deployCommand;

View File

@@ -0,0 +1,22 @@
name: 'Download core artifacts'
description: 'Download core artifacts and extract to dist'
inputs:
path:
description: 'Path to extract'
required: true
runs:
using: 'composite'
steps:
- name: Download tar.gz
uses: actions/download-artifact@v3
with:
name: core
path: .
- name: Extract core artifacts
shell: bash
run: |
mkdir -p ${{ inputs.path }}
tar -xvf dist.tar.gz --directory ${{ inputs.path }}
rm dist.tar.gz

View File

@@ -36,17 +36,19 @@ inputs:
description: 'Set enableScripts in .yarnrc.yml'
required: false
default: 'true'
full-cache:
description: 'Full installation cache'
required: false
runs:
using: 'composite'
steps:
- name: Setup Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
registry-url: https://npm.pkg.github.com
scope: '@toeverything'
cache: 'yarn'
- name: Set nmMode
if: ${{ inputs.hard-link-nm == 'false' }}
@@ -63,6 +65,48 @@ runs:
shell: bash
run: yarn config set enableScripts false
- name: Set yarn global cache path
shell: bash
id: yarn-cache
run: node -e "const p = $(yarn config cacheFolder --json).effective; console.log('yarn_global_cache=' + p)" >> $GITHUB_OUTPUT
- name: Cache non-full yarn cache on Linux
uses: actions/cache@v3
if: ${{ inputs.full-cache != 'true' && runner.os == 'Linux' }}
with:
path: |
node_modules
${{ steps.yarn-cache.outputs.yarn_global_cache }}
key: node_modules-cache-${{ github.job }}-${{ runner.os }}
# The network performance on macOS is very poor
# and the decompression performance on Windows is very terrible
# so we reduce the number of cached files on non-Linux systems by remove node_modules from cache path.
- name: Cache non-full yarn cache on non-Linux
uses: actions/cache@v3
if: ${{ inputs.full-cache != 'true' && runner.os != 'Linux' }}
with:
path: |
${{ steps.yarn-cache.outputs.yarn_global_cache }}
key: node_modules-cache-${{ github.job }}-${{ runner.os }}
- name: Cache full yarn cache on Linux
uses: actions/cache@v3
if: ${{ inputs.full-cache == 'true' && runner.os == 'Linux' }}
with:
path: |
node_modules
${{ steps.yarn-cache.outputs.yarn_global_cache }}
key: node_modules-cache-full-${{ runner.os }}
- name: Cache full yarn cache on non-Linux
uses: actions/cache@v3
if: ${{ inputs.full-cache == 'true' && runner.os != 'Linux' }}
with:
path: |
${{ steps.yarn-cache.outputs.yarn_global_cache }}
key: node_modules-cache-full-${{ runner.os }}
- name: yarn install
if: ${{ inputs.package-install == 'true' }}
continue-on-error: true
@@ -102,8 +146,8 @@ runs:
id: playwright-cache
if: ${{ inputs.playwright-install == 'true' }}
with:
path: '~/.cache/ms-playwright'
key: '${{ runner.os }}-${{ runner.arch }}-playwright-${{ steps.playwright-version.outputs.version }}'
path: ${{ github.workspace }}/node_modules/.cache/ms-playwright
key: '${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}'
# As a fallback, if the Playwright version has changed, try use the
# most recently cached version. There's a good chance that at least one
# of the browser binary versions haven't been updated, so Playwright can
@@ -113,7 +157,7 @@ runs:
# date cache, but still let Playwright decide if it needs to download
# new binaries or not.
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-playwright-
${{ runner.os }}-playwright-
# If the Playwright browser binaries weren't able to be restored, we tell
# playwright to install everything for us.
@@ -121,6 +165,8 @@ runs:
shell: bash
if: inputs.playwright-install == 'true'
run: yarn playwright install --with-deps chromium
env:
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/node_modules/.cache/ms-playwright
- name: Get installed Electron version
id: electron-version
@@ -134,16 +180,16 @@ runs:
if: ${{ inputs.electron-install == 'true' }}
with:
path: 'node_modules/.cache/electron'
key: '${{ runner.os }}-{{ runner.arch }}-electron-${{ steps.electron-version.outputs.version }}'
key: '${{ runner.os }}-electron-${{ steps.electron-version.outputs.version }}'
restore-keys: |
${{ runner.os }}-{{ runner.arch }}-electron-
${{ runner.os }}-electron-
- name: Install Electron binary
shell: bash
if: inputs.electron-install == 'true'
run: node ./node_modules/electron/install.js
env:
ELECTRON_OVERRIDE_DIST_PATH: ./node_modules/.cache/electron
electron_config_cache: ./node_modules/.cache/electron
- name: Build Infra
shell: bash

View File

@@ -1,31 +0,0 @@
version: 2
updates:
- package-ecosystem: 'npm'
directory: '/'
groups:
all-npm-dependencies:
patterns:
- '*'
schedule:
interval: 'weekly'
versioning-strategy: increase
commit-message:
prefix: 'chore'
- package-ecosystem: 'cargo'
directory: '/'
schedule:
interval: 'weekly'
versioning-strategy: auto
commit-message:
prefix: 'chore'
groups:
all-cargo-dependencies:
patterns:
- '*'
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'daily'
commit-message:
prefix: 'ci'

View File

@@ -1,6 +1,6 @@
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 12.5.8
digest: sha256:c91c0dc1370e879538dc9d6e435e731a726ef99d6a3b081372318483792b48a7
generated: "2023-06-27T18:34:12.683806+08:00"
version: 13.2.23
digest: sha256:5b64538509bd067bb0f67bf082847a2c5d66dc37d0b9d7948a40405d9c446400
generated: "2023-12-05T03:04:57.997927753Z"

View File

@@ -8,5 +8,5 @@ appVersion: '0.6.1'
dependencies:
- name: postgresql
version: 12.5.8
version: 13.2.23
repository: https://charts.bitnami.com/bitnami

View File

@@ -3,4 +3,4 @@ name: affine
description: AFFiNE cloud chart
type: application
version: 0.0.0
appVersion: '0.7.0-canary.18'
appVersion: "0.10.4-beta.2"

View File

@@ -3,4 +3,4 @@ name: graphql
description: AFFiNE GraphQL server
type: application
version: 0.0.0
appVersion: '0.7.0-canary.18'
appVersion: "0.10.4-beta.2"

View File

@@ -3,4 +3,4 @@ name: sync
description: A Helm chart for Kubernetes
type: application
version: 0.0.0
appVersion: "0.7.0-canary.18"
appVersion: "0.10.4-beta.2"

117
.github/labeler.yml vendored
View File

@@ -1,62 +1,115 @@
docs:
- 'docs/**/*'
- '**/README.md'
- 'packages/frontend/templates/**/*'
- changed-files:
- any-glob-to-any-file:
- 'docs/**/*'
- '**/README.md'
- 'packages/frontend/templates/**/*'
test:
- 'tests/**/*'
- '**/tests/**/*'
- '**/__tests__/**/*'
- changed-files:
- any-glob-to-any-file:
- 'tests/**/*'
- '**/tests/**/*'
- '**/__tests__/**/*'
mod:dev:
- 'scripts/**/*'
- 'tools/cli/**/*'
- 'packages/common/debug/**/*'
- changed-files:
- any-glob-to-any-file:
- 'scripts/**/*'
- 'tools/cli/**/*'
- 'packages/common/debug/**/*'
mod:plugin:
- 'packages/plugins/**/*'
- changed-files:
- any-glob-to-any-file:
- 'packages/plugins/**/*'
plugin:copilot:
- 'packages/plugins/copilot/**/*'
- changed-files:
- any-glob-to-any-file:
- 'packages/plugins/copilot/**/*'
mod:infra:
- 'packages/common/infra/**/*'
- changed-files:
- any-glob-to-any-file:
- 'packages/common/infra/**/*'
mod:sdk:
- 'packages/common/sdk/**/*'
- changed-files:
- any-glob-to-any-file:
- 'packages/common/sdk/**/*'
mod:plugin-cli:
- 'tools/plugin-cli/**/*'
- changed-files:
- any-glob-to-any-file:
- 'tools/plugin-cli/**/*'
mod:workspace: 'packages/frontend/workspace/**/*'
mod:workspace:
- changed-files:
- any-glob-to-any-file:
- 'packages/frontend/workspace/**/*'
mod:i18n: 'packages/frontend/i18n/**/*'
mod:i18n:
- changed-files:
- any-glob-to-any-file:
- 'packages/frontend/i18n/**/*'
mod:env: 'packages/common/env/**/*'
mod:env:
- changed-files:
- any-glob-to-any-file:
- 'packages/common/env/**/*'
mod:hooks: 'packages/frontend/hooks/**/*'
mod:hooks:
- changed-files:
- any-glob-to-any-file:
- 'packages/frontend/hooks/**/*'
mod:component: 'packages/frontend/component/**/*'
mod:component:
- changed-files:
- any-glob-to-any-file:
- 'packages/frontend/component/**/*'
mod:storage: 'packages/backend/storage/**/*'
mod:storage:
- changed-files:
- any-glob-to-any-file:
- 'packages/backend/storage/**/*'
mod:native: 'packages/frontend/native/**/*'
mod:native:
- changed-files:
- any-glob-to-any-file:
- 'packages/frontend/native/**/*'
mod:store:
- '**/atoms/**/*'
- changed-files:
- any-glob-to-any-file:
- '**/atoms/**/*'
rust:
- '**/*.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain'
- '**/rust-toolchain.toml'
- '**/rustfmt.toml'
- changed-files:
- any-glob-to-any-file:
- '**/*.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain'
- '**/rust-toolchain.toml'
- '**/rustfmt.toml'
package:y-indexeddb: 'packages/common/y-indexeddb/**/*'
package:y-indexeddb:
- changed-files:
- any-glob-to-any-file:
- 'packages/common/y-indexeddb/**/*'
app:core: 'packages/frontend/core/**/*'
app:core:
- changed-files:
- any-glob-to-any-file:
- 'packages/frontend/core/**/*'
app:electron: 'packages/frontend/electron/**/*'
app:electron:
- changed-files:
- any-glob-to-any-file:
- 'packages/frontend/electron/**/*'
app:server: 'packages/backend/server/**/*'
app:server:
- changed-files:
- any-glob-to-any-file:
- 'packages/backend/server/**/*'

53
.github/renovate.json vendored Normal file
View File

@@ -0,0 +1,53 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
"group:allNonMajor",
":preserveSemverRanges",
":disablePeerDependencies"
],
"labels": ["dependencies"],
"packageRules": [
{
"matchPackageNames": ["napi", "napi-build", "napi-derive"],
"groupName": "napi-rs"
},
{
"matchPackagePatterns": ["^eslint", "^@typescript-eslint"],
"groupName": "linter"
},
{
"matchPackagePatterns": ["^@nestjs"],
"groupName": "nestjs"
},
{
"matchPackagePatterns": ["^@opentelemetry"],
"groupName": "opentelemetry"
},
{
"matchPackageNames": [
"@prisma/client",
"@prisma/instrumentation",
"prisma"
],
"groupName": "prisma"
},
{
"matchPackagePatterns": ["^@electron-forge"],
"groupName": "electron-forge"
},
{
"matchPackagePatterns": ["^@blocksuite"],
"excludePackageNames": ["@blocksuite/icons"],
"followTag": "nightly"
}
],
"commitMessagePrefix": "chore: ",
"commitMessageAction": "bump up",
"commitMessageTopic": "{{depName}} version",
"ignoreDeps": [],
"lockFileMaintenance": {
"enabled": true,
"extends": ["schedule:weekly"]
}
}

View File

@@ -9,4 +9,5 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
- uses: actions/checkout@v4
- uses: actions/labeler@v5

View File

@@ -1,190 +0,0 @@
name: Build(Desktop) & Test
on:
push:
branches:
- canary
- v[0-9]+.[0-9]+.x-staging
- v[0-9]+.[0-9]+.x
paths-ignore:
- README.md
- .github/**
- '!.github/workflows/build-desktop.yml'
- '!.github/actions/build-rust/action.yml'
- '!.github/actions/setup-node/action.yml'
pull_request:
merge_group:
branches:
- canary
- v[0-9]+.[0-9]+.x-staging
- v[0-9]+.[0-9]+.x
paths-ignore:
- README.md
- .github/**
- '!.github/workflows/build-desktop.yml'
- '!.github/actions/build-rust/action.yml'
- '!.github/actions/setup-node/action.yml'
env:
DEBUG: napi:*
BUILD_TYPE: canary
APP_NAME: affine
COVERAGE: true
DISTRIBUTION: desktop
MACOSX_DEPLOYMENT_TARGET: '10.13'
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
jobs:
build-core:
name: Build @affine/core
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
- name: Build Core
run: yarn nx build @affine/core
- name: Upload core artifact
uses: actions/upload-artifact@v3
with:
name: core
path: ./packages/frontend/core/dist
if-no-files-found: error
build-native:
name: Build Native
runs-on: ubuntu-latest
needs: build-core
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Build AFFiNE native
uses: ./.github/actions/build-rust
with:
target: x86_64-unknown-linux-gnu
package: '@affine/native'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Run tests
run: yarn test
working-directory: ./packages/frontend/native
desktop-test:
name: Desktop Test
runs-on: ${{ matrix.spec.os }}
strategy:
fail-fast: false
# all combinations: macos-latest x64, macos-latest arm64, windows-latest x64, ubuntu-latest x64
matrix:
spec:
- {
os: macos-latest,
platform: macos,
arch: x64,
target: x86_64-apple-darwin,
test: true,
}
- {
os: macos-latest,
platform: macos,
arch: arm64,
target: aarch64-apple-darwin,
test: false,
}
- {
os: ubuntu-latest,
platform: linux,
arch: x64,
target: x86_64-unknown-linux-gnu,
test: true,
}
- {
os: windows-latest,
platform: windows,
arch: x64,
target: x86_64-pc-windows-msvc,
test: true,
}
needs: build-core
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
timeout-minutes: 10
with:
extra-flags: workspaces focus @affine/electron @affine/monorepo @affine-test/affine-desktop
playwright-install: true
hard-link-nm: false
enableScripts: false
- name: Build AFFiNE native
uses: ./.github/actions/build-rust
with:
target: ${{ matrix.spec.target }}
package: '@affine/native'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Run unit tests
if: ${{ matrix.spec.test }}
shell: bash
run: yarn vitest
working-directory: packages/frontend/electron
- name: Download core artifact
uses: actions/download-artifact@v3
with:
name: core
path: packages/frontend/electron/resources/web-static
- name: Build Desktop Layers
run: yarn workspace @affine/electron build
- name: Run desktop tests
if: ${{ matrix.spec.test && matrix.spec.os == 'ubuntu-latest' }}
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn workspace @affine-test/affine-desktop e2e
env:
COVERAGE: true
- name: Run desktop tests
if: ${{ matrix.spec.test && matrix.spec.os != 'ubuntu-latest' }}
run: yarn workspace @affine-test/affine-desktop e2e
env:
COVERAGE: true
- name: Make bundle
if: ${{ matrix.spec.os == 'macos-latest' && matrix.spec.arch == 'arm64' }}
env:
SKIP_BUNDLE: true
SKIP_WEB_BUILD: true
HOIST_NODE_MODULES: 1
run: yarn workspace @affine/electron package --platform=darwin --arch=arm64
- name: Output check
if: ${{ matrix.spec.os == 'macos-latest' && matrix.spec.arch == 'arm64' }}
run: |
yarn workspace @affine/electron ts-node ./scripts/macos-arm64-output-check.ts
- name: Collect code coverage report
if: ${{ matrix.spec.test }}
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
- name: Upload e2e test coverage results
if: ${{ matrix.spec.test }}
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/lcov.info
flags: e2etest-${{ matrix.spec.os }}-${{ matrix.spec.arch }}
name: affine
fail_ci_if_error: false
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-${{ matrix.spec.os }}-${{ matrix.spec.arch }}
path: ./test-results
if-no-files-found: ignore

View File

@@ -1,311 +0,0 @@
name: Build(Server) & Test
on:
push:
branches:
- canary
- v[0-9]+.[0-9]+.x-staging
- v[0-9]+.[0-9]+.x
paths-ignore:
- README.md
- .github/**
- '!.github/workflows/build-server.yml'
- '!.github/actions/build-rust/action.yml'
- '!.github/actions/setup-node/action.yml'
pull_request:
merge_group:
branches:
- canary
- v[0-9]+.[0-9]+.x-staging
- v[0-9]+.[0-9]+.x
paths-ignore:
- README.md
- .github/**
- '!.github/workflows/build-server.yml'
- '!.github/actions/build-rust/action.yml'
- '!.github/actions/setup-node/action.yml'
env:
DEBUG: napi:*
BUILD_TYPE: canary
APP_NAME: affine
COVERAGE: true
DISTRIBUTION: browser
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
jobs:
build-storage:
name: Build Storage
runs-on: ubuntu-latest
env:
RUSTFLAGS: '-C debuginfo=1'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
extra-flags: workspaces focus @affine/storage
electron-install: false
build-infra: false
build-plugins: false
- name: Build Rust
uses: ./.github/actions/build-rust
with:
target: 'x86_64-unknown-linux-gnu'
package: '@affine/storage'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Upload storage.node
uses: actions/upload-artifact@v3
with:
name: storage.node
path: ./packages/backend/storage/storage.node
if-no-files-found: error
server-test:
name: Server Test
runs-on: ubuntu-latest
needs: build-storage
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: affine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
mailer:
image: mailhog/mailhog
ports:
- 1025:1025
- 8025:8025
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
- name: Initialize database
run: |
psql -h localhost -U postgres -c "CREATE DATABASE affine;"
psql -h localhost -U postgres -c "CREATE USER affine WITH PASSWORD 'affine';"
psql -h localhost -U postgres -c "ALTER USER affine WITH SUPERUSER;"
env:
PGPASSWORD: affine
- name: Generate prisma client
run: |
yarn workspace @affine/server exec prisma generate
yarn workspace @affine/server exec prisma db push
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Run init-db script
run: yarn workspace @affine/server exec ts-node ./scripts/init-db.ts
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Download storage.node
uses: actions/download-artifact@v3
with:
name: storage.node
path: ./packages/backend/server
- name: Run server tests
run: yarn workspace @affine/server test:coverage
env:
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Upload server test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/server/.coverage/lcov.info
flags: server-test
name: affine
fail_ci_if_error: false
server-e2e-test:
name: Server E2E Test
runs-on: ubuntu-latest
needs: build-storage
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: affine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
mailer:
image: mailhog/mailhog
ports:
- 1025:1025
- 8025:8025
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
playwright-install: true
- name: Initialize database
run: |
psql -h localhost -U postgres -c "CREATE DATABASE affine;"
psql -h localhost -U postgres -c "CREATE USER affine WITH PASSWORD 'affine';"
psql -h localhost -U postgres -c "ALTER USER affine WITH SUPERUSER;"
env:
PGPASSWORD: affine
- name: Generate prisma client
run: |
yarn workspace @affine/server exec prisma generate
yarn workspace @affine/server exec prisma db push
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Run init-db script
run: yarn workspace @affine/server exec ts-node ./scripts/init-db.ts
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Download storage.node
uses: actions/download-artifact@v3
with:
name: storage.node
path: ./packages/backend/server
- name: Run playwright tests
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn workspace @affine-test/affine-cloud e2e --forbid-only
env:
COVERAGE: true
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Collect code coverage report
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
- name: Upload e2e test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/lcov.info
flags: server-e2etest
name: affine
fail_ci_if_error: false
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-server
path: ./tests/affine-cloud/test-results
if-no-files-found: ignore
server-desktop-e2e-test:
name: Server Desktop E2E Test
runs-on: ubuntu-latest
needs: build-storage
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: affine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
mailer:
image: mailhog/mailhog
ports:
- 1025:1025
- 8025:8025
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
playwright-install: true
hard-link-nm: false
- name: Build AFFiNE native
uses: ./.github/actions/build-rust
with:
target: x86_64-unknown-linux-gnu
package: '@affine/native'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Initialize database
run: |
psql -h localhost -U postgres -c "CREATE DATABASE affine;"
psql -h localhost -U postgres -c "CREATE USER affine WITH PASSWORD 'affine';"
psql -h localhost -U postgres -c "ALTER USER affine WITH SUPERUSER;"
env:
PGPASSWORD: affine
- name: Generate prisma client
run: |
yarn workspace @affine/server exec prisma generate
yarn workspace @affine/server prisma db push
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Run init-db script
run: yarn workspace @affine/server exec ts-node ./scripts/init-db.ts
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Download storage.node
uses: actions/download-artifact@v3
with:
name: storage.node
path: ./packages/backend/server
- name: Build Plugins
run: yarn run build:plugins
- name: Build Desktop Layers
run: yarn workspace @affine/electron build:dev
- name: Run playwright tests
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" yarn workspace @affine-test/affine-desktop-cloud e2e
env:
COVERAGE: true
DEV_SERVER_URL: http://localhost:8080
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
ENABLE_LOCAL_EMAIL: true
- name: Collect code coverage report
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
- name: Upload e2e test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/lcov.info
flags: server-e2etest
name: affine
fail_ci_if_error: false
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-server
path: ./tests/affine-cloud/test-results
if-no-files-found: ignore

599
.github/workflows/build-test.yml vendored Normal file
View File

@@ -0,0 +1,599 @@
name: Build & Test
on:
push:
branches:
- canary
- v[0-9]+.[0-9]+.x-staging
- v[0-9]+.[0-9]+.x
paths-ignore:
- README.md
pull_request:
env:
DEBUG: napi:*
BUILD_TYPE: canary
APP_NAME: affine
AFFINE_ENV: dev
COVERAGE: true
MACOSX_DEPLOYMENT_TARGET: '10.13'
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/node_modules/.cache/ms-playwright
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript', 'typescript']
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run oxlint
# oxlint is fast, so wrong code will fail quickly
run: yarn dlx $(node -e "console.log(require('./package.json').scripts['lint:ox'])")
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
full-cache: true
- name: Run i18n codegen
run: yarn i18n-codegen gen
- name: Run ESLint
run: yarn lint:eslint --max-warnings=0
- name: Run Prettier
# Set nmMode in `actions/setup-node` will modify the .yarnrc.yml
run: |
git checkout .yarnrc.yml
yarn lint:prettier
- name: Run Type Check
run: yarn typecheck
check-yarn-binary:
name: Check yarn binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run check
run: |
yarn set version $(node -e "console.log(require('./package.json').packageManager.split('@')[1])")
git diff --exit-code
e2e-plugin-test:
name: E2E Plugin Test
runs-on: ubuntu-latest
env:
DISTRIBUTION: browser
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 e2e --forbid-only
working-directory: tests/affine-plugin
env:
COVERAGE: true
- name: Collect code coverage report
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
- name: Upload e2e test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/lcov.info
flags: e2e-plugin-test
name: affine
fail_ci_if_error: false
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-plugin
path: ./test-results
if-no-files-found: ignore
e2e-test:
name: E2E Test
runs-on: ubuntu-latest
env:
DISTRIBUTION: browser
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-local e2e --forbid-only --shard=${{ matrix.shard }}/${{ strategy.job-total }}
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-${{ matrix.shard }}
path: ./test-results
if-no-files-found: ignore
e2e-migration-test:
name: E2E Migration Test
runs-on: ubuntu-latest
env:
DISTRIBUTION: browser
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-migration e2e --forbid-only
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-migration
path: ./tests/affine-migration/test-results
if-no-files-found: ignore
unit-test:
name: Unit Test
runs-on: ubuntu-latest
needs:
- build-native
env:
DISTRIBUTION: browser
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
full-cache: true
- name: Download affine.linux-x64-gnu.node
uses: actions/download-artifact@v3
with:
name: affine.linux-x64-gnu.node
path: ./packages/frontend/native
- name: Unit Test
run: yarn nx test:coverage @affine/monorepo
- name: Upload unit test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/store/lcov.info
flags: unittest
name: affine
fail_ci_if_error: false
build-native:
name: Build AFFiNE native (${{ matrix.spec.target }})
runs-on: ${{ matrix.spec.os }}
env:
CARGO_PROFILE_RELEASE_DEBUG: '1'
strategy:
fail-fast: false
matrix:
spec:
- { os: ubuntu-latest, target: x86_64-unknown-linux-gnu }
- { os: windows-latest, target: x86_64-pc-windows-msvc }
- { os: macos-latest, target: x86_64-apple-darwin }
- { os: macos-latest, target: aarch64-apple-darwin }
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
extra-flags: workspaces focus @affine/native
electron-install: false
build-infra: false
build-plugins: false
- name: Setup filename
id: filename
shell: bash
run: |
export PLATFORM_ARCH_ABI=$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
- name: Build AFFiNE native
uses: ./.github/actions/build-rust
with:
target: ${{ matrix.spec.target }}
package: '@affine/native'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Upload ${{ steps.filename.outputs.filename }}
uses: actions/upload-artifact@v3
with:
name: ${{ steps.filename.outputs.filename }}
path: ./packages/frontend/native/${{ steps.filename.outputs.filename }}
if-no-files-found: error
build-storage:
name: Build Storage
runs-on: ubuntu-latest
env:
CARGO_PROFILE_RELEASE_DEBUG: '1'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
extra-flags: workspaces focus @affine/storage
electron-install: false
build-infra: false
build-plugins: false
- name: Build Rust
uses: ./.github/actions/build-rust
with:
target: 'x86_64-unknown-linux-gnu'
package: '@affine/storage'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Upload storage.node
uses: actions/upload-artifact@v3
with:
name: storage.node
path: ./packages/backend/storage/storage.node
if-no-files-found: error
build-core:
name: Build @affine/core
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
build-plugins: false
full-cache: true
- name: Build Core
# always skip cache because its fast, and cache configuration is always changing
run: yarn nx build @affine/core --skip-nx-cache
- name: zip core
run: tar -czf dist.tar.gz --directory=packages/frontend/core/dist .
- name: Upload core artifact
uses: actions/upload-artifact@v3
with:
name: core
path: dist.tar.gz
if-no-files-found: error
server-test:
name: Server Test
runs-on: ubuntu-latest
needs: build-storage
env:
DISTRIBUTION: browser
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: affine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
mailer:
image: mailhog/mailhog
ports:
- 1025:1025
- 8025:8025
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
full-cache: true
- name: Initialize database
run: |
psql -h localhost -U postgres -c "CREATE DATABASE affine;"
psql -h localhost -U postgres -c "CREATE USER affine WITH PASSWORD 'affine';"
psql -h localhost -U postgres -c "ALTER USER affine WITH SUPERUSER;"
env:
PGPASSWORD: affine
- name: Generate prisma client
run: |
yarn workspace @affine/server exec prisma generate
yarn workspace @affine/server exec prisma db push
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Run init-db script
run: yarn workspace @affine/server exec node --loader ts-node/esm/transpile-only ./scripts/init-db.ts
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Download storage.node
uses: actions/download-artifact@v3
with:
name: storage.node
path: ./packages/backend/server
- name: Run server tests
run: yarn workspace @affine/server test:coverage
env:
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Upload server test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/server/.coverage/lcov.info
flags: server-test
name: affine
fail_ci_if_error: false
server-e2e-test:
name: ${{ matrix.tests.name }}
runs-on: ubuntu-latest
env:
DISTRIBUTION: browser
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
strategy:
fail-fast: false
matrix:
tests:
- name: 'Server E2E Test 1/3'
script: yarn workspace @affine-test/affine-cloud e2e --forbid-only --shard=1/3
- name: 'Server E2E Test 2/3'
script: yarn workspace @affine-test/affine-cloud e2e --forbid-only --shard=2/3
- name: 'Server E2E Test 3/3'
script: yarn workspace @affine-test/affine-cloud e2e --forbid-only --shard=3/3
- name: 'Server Desktop E2E Test'
script: |
yarn workspace @affine/electron build:dev
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn workspace @affine-test/affine-desktop-cloud e2e
needs:
- build-storage
- build-native
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: affine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
mailer:
image: mailhog/mailhog
ports:
- 1025:1025
- 8025:8025
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
playwright-install: true
hard-link-nm: false
- name: Initialize database
run: |
psql -h localhost -U postgres -c "CREATE DATABASE affine;"
psql -h localhost -U postgres -c "CREATE USER affine WITH PASSWORD 'affine';"
psql -h localhost -U postgres -c "ALTER USER affine WITH SUPERUSER;"
env:
PGPASSWORD: affine
- name: Generate prisma client
run: |
yarn workspace @affine/server exec prisma generate
yarn workspace @affine/server exec prisma db push
env:
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
- name: Run init-db script
run: yarn workspace @affine/server exec node --loader ts-node/esm/transpile-only ./scripts/init-db.ts
- name: Download storage.node
uses: actions/download-artifact@v3
with:
name: storage.node
path: ./packages/backend/server
- name: Download affine.linux-x64-gnu.node
uses: actions/download-artifact@v3
with:
name: affine.linux-x64-gnu.node
path: ./packages/frontend/native
- name: ${{ matrix.tests.name }}
run: |
${{ matrix.tests.script }}
env:
DEV_SERVER_URL: http://localhost:8080
ENABLE_LOCAL_EMAIL: true
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-server
path: ./tests/affine-cloud/test-results
if-no-files-found: ignore
desktop-test:
name: Desktop Test (${{ matrix.spec.os }}, ${{ matrix.spec.platform }}, ${{ matrix.spec.arch }}, ${{ matrix.spec.target }}, ${{ matrix.spec.test }})
runs-on: ${{ matrix.spec.os }}
strategy:
fail-fast: false
# all combinations: macos-latest x64, macos-latest arm64, windows-latest x64, ubuntu-latest x64
matrix:
spec:
- {
os: macos-latest,
platform: macos,
arch: x64,
target: x86_64-apple-darwin,
test: true,
}
- {
os: macos-latest,
platform: macos,
arch: arm64,
target: aarch64-apple-darwin,
test: false,
}
- {
os: ubuntu-latest,
platform: linux,
arch: x64,
target: x86_64-unknown-linux-gnu,
test: true,
}
- {
os: windows-latest,
platform: windows,
arch: x64,
target: x86_64-pc-windows-msvc,
test: true,
}
needs:
- build-core
- build-native
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
timeout-minutes: 10
with:
extra-flags: workspaces focus @affine/electron @affine/monorepo @affine-test/affine-desktop
playwright-install: true
hard-link-nm: false
enableScripts: false
- name: Setup filename
id: filename
shell: bash
run: |
export PLATFORM_ARCH_ABI=$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
- name: Download ${{ steps.filename.outputs.filename }}
uses: actions/download-artifact@v3
with:
name: ${{ steps.filename.outputs.filename }}
path: ./packages/frontend/native
- name: Run unit tests
if: ${{ matrix.spec.test }}
shell: bash
run: yarn vitest
working-directory: packages/frontend/electron
- name: Download core artifact
uses: ./.github/actions/download-core
with:
path: packages/frontend/electron/resources/web-static
- name: Build Desktop Layers
run: yarn workspace @affine/electron build
- name: Run desktop tests
if: ${{ matrix.spec.test && matrix.spec.os == 'ubuntu-latest' }}
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn workspace @affine-test/affine-desktop e2e
- name: Run desktop tests
if: ${{ matrix.spec.test && matrix.spec.os != 'ubuntu-latest' }}
run: yarn workspace @affine-test/affine-desktop e2e
- name: Make bundle
if: ${{ matrix.spec.os == 'macos-latest' && matrix.spec.arch == 'arm64' }}
env:
SKIP_BUNDLE: true
SKIP_WEB_BUILD: true
HOIST_NODE_MODULES: 1
run: yarn workspace @affine/electron package --platform=darwin --arch=arm64
- name: Output check
if: ${{ matrix.spec.os == 'macos-latest' && matrix.spec.arch == 'arm64' }}
run: |
yarn workspace @affine/electron exec node --loader ts-node/esm/transpile-only ./scripts/macos-arm64-output-check.ts
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-${{ matrix.spec.os }}-${{ matrix.spec.arch }}
path: ./test-results
if-no-files-found: ignore

View File

@@ -1,201 +0,0 @@
name: Build & Test
on:
push:
branches:
- canary
- v[0-9]+.[0-9]+.x-staging
- v[0-9]+.[0-9]+.x
paths-ignore:
- README.md
- .github/**
- '!.github/workflows/build.yml'
- '!.github/actions/build-rust/action.yml'
- '!.github/actions/setup-node/action.yml'
pull_request:
merge_group:
branches:
- canary
- v[0-9]+.[0-9]+.x-staging
- v[0-9]+.[0-9]+.x
paths-ignore:
- README.md
- .github/**
- '!.github/workflows/build.yml'
- '!.github/actions/build-rust/action.yml'
- '!.github/actions/setup-node/action.yml'
env:
DEBUG: napi:*
BUILD_TYPE: canary
APP_NAME: affine
AFFINE_ENV: dev
COVERAGE: true
DISTRIBUTION: browser
MACOSX_DEPLOYMENT_TARGET: '10.13'
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run oxlint
# oxlint is fast, so wrong code will fail quickly
run: yarn dlx oxlint@latest .
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
- name: Run i18n codegen
run: yarn i18n-codegen gen
- name: Run ESLint
run: yarn lint:eslint --max-warnings=0
- name: Run Prettier
# Set nmMode in `actions/setup-node` will modify the .yarnrc.yml
run: |
git checkout .yarnrc.yml
yarn lint:prettier
- name: Run circular
run: yarn circular
- name: Run Type Check
run: yarn typecheck
check-yarn-binary:
name: Check yarn binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run check
run: |
yarn set version $(node -e "console.log(require('./package.json').packageManager.split('@')[1])")
git diff --exit-code
e2e-plugin-test:
name: E2E Plugin Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
playwright-install: true
electron-install: false
- name: Run playwright tests
run: yarn e2e --forbid-only
working-directory: tests/affine-plugin
env:
COVERAGE: true
- name: Collect code coverage report
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
- name: Upload e2e test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/lcov.info
flags: e2e-plugin-test
name: affine
fail_ci_if_error: false
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-plugin
path: ./test-results
if-no-files-found: ignore
e2e-test:
name: E2E Test
runs-on: ubuntu-latest
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
- name: Run playwright tests
run: yarn e2e --forbid-only --shard=${{ matrix.shard }}/${{ strategy.job-total }}
working-directory: tests/affine-local
env:
COVERAGE: true
- name: Collect code coverage report
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
- name: Upload e2e test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/lcov.info
flags: e2etest
name: affine
fail_ci_if_error: false
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-${{ matrix.shard }}
path: ./test-results
if-no-files-found: ignore
e2e-migration-test:
name: E2E Migration Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
playwright-install: true
electron-install: false
- name: Run playwright tests
run: yarn workspace @affine-test/affine-migration e2e --forbid-only
- name: Upload test results
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: test-results-e2e-migration
path: ./tests/affine-migration/test-results
if-no-files-found: ignore
unit-test:
name: Unit Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
- name: Build AFFiNE native
uses: ./.github/actions/build-rust
with:
target: x86_64-unknown-linux-gnu
package: '@affine/native'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Unit Test
run: yarn nx test:coverage @affine/monorepo
- name: Upload unit test coverage results
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./.coverage/store/lcov.info
flags: unittest
name: affine
fail_ci_if_error: false

View File

@@ -1,36 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
name: Cleanup caches for closed branches
on:
pull_request:
types:
- closed
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
REPO=${{ github.repository }}
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,18 +0,0 @@
name: Cancel
on:
pull_request_target:
types:
- edited
- synchronize
jobs:
cancel:
name: 'Cancel Previous Runs'
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- uses: styfle/cancel-workflow-action@0.12.0
with:
# See https://api.github.com/repos/toeverything/AFFiNE/actions/workflows
workflow_id: 44038251, 61883931, 65188160, 66789140
access_token: ${{ github.token }}

View File

@@ -1,70 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: 'CodeQL'
on:
push:
branches: [canary]
pull_request:
merge_group:
# The branches below must be a subset of the branches above
branches: [canary]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -9,7 +9,6 @@ on:
default: canary
env:
BUILD_TYPE: canary
APP_NAME: affine
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
@@ -17,7 +16,6 @@ jobs:
build-server:
name: Build Server
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.flavor }}
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
@@ -43,12 +41,12 @@ jobs:
- name: Build Plugins
run: yarn run build:plugins
- name: Build Core
run: yarn nx build @affine/core
run: yarn nx build @affine/core --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_OVERRIDE: ${{ github.event.inputs.flavor }}
BUILD_TYPE: ${{ github.event.inputs.flavor }}
SHOULD_REPORT_TRACE: true
TRACE_REPORT_ENDPOINT: ${{ secrets.TRACE_REPORT_ENDPOINT }}
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
@@ -71,7 +69,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Setup Rust
- name: Build Rust
uses: ./.github/actions/build-rust
with:
target: 'x86_64-unknown-linux-gnu'
@@ -92,7 +90,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Setup Rust
- name: Build Rust
uses: ./.github/actions/build-rust
with:
target: 'aarch64-unknown-linux-gnu'
@@ -209,7 +207,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to dev
- name: setup deploy version
id: version
run: |
export APP_VERSION=`node -e "console.log(require('./package.json').version)"`
echo $APP_VERSION
echo "APP_VERSION=$APP_VERSION" >> "$GITHUB_OUTPUT"
- name: Deploy to ${{ github.event.inputs.flavor }}
uses: ./.github/actions/deploy
with:
build-type: ${{ github.event.inputs.flavor }}
@@ -219,6 +223,7 @@ jobs:
cluster-name: ${{ secrets.GCP_CLUSTER_NAME }}
cluster-location: ${{ secrets.GCP_CLUSTER_LOCATION }}
env:
APP_VERSION: ${{ steps.version.outputs.APP_VERSION }}
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
CANARY_DEPLOY_HOST: ${{ secrets.CANARY_DEPLOY_HOST }}
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}

View File

@@ -65,14 +65,15 @@ jobs:
- name: Replace Version
run: ./scripts/set-version.sh ${{ needs.set-build-version.outputs.version }}
- name: generate-assets
working-directory: packages/frontend/electron
run: yarn generate-assets
run: yarn workspace @affine/electron generate-assets
env:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
RELEASE_VERSION: ${{ needs.set-build-version.outputs.version }}
SKIP_PLUGIN_BUILD: 'true'
SKIP_NX_CACHE: 'true'
- name: Upload core artifact
uses: actions/upload-artifact@v3
@@ -230,6 +231,11 @@ jobs:
node ./packages/frontend/electron/scripts/generate-yml.js
env:
RELEASE_VERSION: ${{ needs.set-build-version.outputs.version }}
- name: Generate SHA512 checksums
run: |
sha512sum *-linux-* > SHA512SUMS.txt
sha512sum *-macos-* >> SHA512SUMS.txt
sha512sum *-windows-* >> SHA512SUMS.txt
- name: Create Release Draft
uses: softprops/action-gh-release@v1
env:
@@ -240,6 +246,7 @@ jobs:
tag_name: ${{ needs.set-build-version.outputs.version }}
prerelease: true
files: |
./SHA512SUMS.txt
./VERSION
./*.zip
./*.dmg

View File

@@ -19,7 +19,10 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
uses: actions/setup-node@v4
with:
electron-install: false
- run: echo "${{ github.event.pull_request.title }}" | yarn dlx commitlint -g ./.commitlintrc.json
cache: 'yarn'
node-version-file: '.nvmrc'
- name: Install dependencies
run: yarn workspaces focus @affine/commitlint-config
- run: echo "${{ github.event.pull_request.title }}" | yarn workspace @affine/commitlint-config commitlint -g ./.commitlintrc.json

View File

@@ -69,6 +69,7 @@ jobs:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
RELEASE_VERSION: ${{ github.event.inputs.version || steps.get-canary-version.outputs.RELEASE_VERSION }}
SKIP_PLUGIN_BUILD: 'true'
SKIP_NX_CACHE: 'true'
- name: Upload core artifact
uses: actions/upload-artifact@v3

View File

@@ -1,165 +0,0 @@
name: Release
on:
push:
branches:
- canary
env:
BUILD_TYPE: stable
APP_NAME: affine
COVERAGE: false
DISTRIBUTION: browser
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
jobs:
release:
name: Try publishing npm@latest release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Try publishing to NPM
run: ./scripts/publish.sh
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
build-core:
name: Build @affine/core
runs-on: ubuntu-latest
environment: development
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Build Plugins
run: yarn run build:plugins
- name: Build Core
run: yarn nx build @affine/core
- name: Upload core artifact
uses: actions/upload-artifact@v3
with:
name: core
path: ./packages/frontend/core/dist
if-no-files-found: error
build-server:
name: Build Server
runs-on: ubuntu-latest
environment: development
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
- name: Build Server
run: yarn nx build @affine/server
- name: Upload server dist
uses: actions/upload-artifact@v3
with:
name: server-dist
path: ./packages/backend/server/dist
if-no-files-found: error
build-storage:
name: Build Storage
runs-on: ubuntu-latest
env:
RUSTFLAGS: '-C debuginfo=1'
environment: development
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Setup Rust
uses: ./.github/actions/build-rust
with:
target: 'x86_64-unknown-linux-gnu'
package: '@affine/storage'
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
- name: Upload storage.node
uses: actions/upload-artifact@v3
with:
name: storage.node
path: ./packages/backend/storage/storage.node
if-no-files-found: error
build-docker:
if: github.ref == 'refs/heads/canary'
name: Build Docker
runs-on: ubuntu-latest
needs:
- build-server
- build-core
- build-storage
steps:
- uses: actions/checkout@v4
- name: Download core artifact
uses: actions/download-artifact@v3
with:
name: core
path: ./packages/frontend/core/dist
- name: Download server dist
uses: actions/download-artifact@v3
with:
name: server-dist
path: ./packages/backend/server/dist
- name: Download storage.node
uses: actions/download-artifact@v3
with:
name: storage.node
path: ./packages/backend/server
- name: Setup Git short hash
run: |
echo "GIT_SHORT_HASH=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
logout: false
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build front Dockerfile
uses: docker/build-push-action@v5
with:
context: .
push: true
pull: true
platforms: linux/amd64,linux/arm64
provenance: true
file: .github/deployment/front/Dockerfile
tags: ghcr.io/toeverything/affine-front:${{ env.GIT_SHORT_HASH }},ghcr.io/toeverything/affine-front:latest
# setup node without cache configuration
# Prisma cache is not compatible with docker build cache
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
registry-url: https://npm.pkg.github.com
scope: '@toeverything'
- name: Install Node.js dependencies
run: yarn workspaces focus @affine/server --production
- name: Generate Prisma client
run: yarn workspace @affine/server prisma generate
- name: Build graphql Dockerfile
uses: docker/build-push-action@v5
with:
context: .
push: true
pull: true
platforms: linux/amd64,linux/arm64
provenance: true
file: .github/deployment/node/Dockerfile
tags: ghcr.io/toeverything/affine-graphql:${{ env.GIT_SHORT_HASH }},ghcr.io/toeverything/affine-graphql:latest

View File

@@ -1,23 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# check lockfile is up to date
yarn install --mode=skip-build --inline-builds --immutable
# build infra code
yarn -T run build:infra
# generate prisma client type
yarn workspace @affine/server prisma generate
# generate i18n
yarn i18n-codegen gen
# lint staged files
yarn exec lint-staged
# type check
yarn typecheck
# circular dependency check
yarn circular
yarn lint-staged && yarn lint:ox

View File

@@ -15,6 +15,7 @@ packages/backend/server/src/schema.gql
packages/frontend/i18n/src/i18n-generated.ts
packages/frontend/graphql/src/graphql/index.ts
tests/affine-legacy/**/static
.yarnrc.yml
# auto-generated by NAPI-RS
# fixme(@joooye34): need script to check and generate ignore list here

File diff suppressed because one or more lines are too long

View File

@@ -6,10 +6,10 @@ nmMode: hardlinks-local
nodeLinker: node-modules
npmAuthToken: '${NPM_TOKEN:-NONE}'
npmAuthToken: "${NPM_TOKEN:-NONE}"
npmPublishAccess: public
npmPublishRegistry: 'https://registry.npmjs.org'
npmPublishRegistry: "https://registry.npmjs.org"
yarnPath: .yarn/releases/yarn-4.0.1.cjs
yarnPath: .yarn/releases/yarn-4.0.2.cjs

144
Cargo.lock generated
View File

@@ -83,14 +83,15 @@ dependencies = [
[[package]]
name = "ahash"
version = "0.8.3"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
dependencies = [
"cfg-if",
"getrandom",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
@@ -240,6 +241,16 @@ dependencies = [
"num-traits",
]
[[package]]
name = "atomic-write-file"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c232177ba50b16fe7a4588495bd474a62a9e45a8e4ca6fd7d0b7ac29d164631e"
dependencies = [
"nix",
"rand",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@@ -941,7 +952,7 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
"ahash 0.8.3",
"ahash 0.8.6",
]
[[package]]
@@ -950,7 +961,7 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
dependencies = [
"ahash 0.8.3",
"ahash 0.8.6",
"allocator-api2",
]
@@ -1112,7 +1123,7 @@ dependencies = [
[[package]]
name = "jwst-codec"
version = "0.1.0"
source = "git+https://github.com/toeverything/OctoBase.git?rev=aad9e5b#aad9e5b7e9d6f479e6cf7555f5845bbbaaadbc66"
source = "git+https://github.com/toeverything/OctoBase.git?rev=49a6b7a#49a6b7af25ce1fe54e8383e10980e9536821d286"
dependencies = [
"arbitrary",
"bitvec",
@@ -1133,7 +1144,7 @@ dependencies = [
[[package]]
name = "jwst-core"
version = "0.1.0"
source = "git+https://github.com/toeverything/OctoBase.git?rev=aad9e5b#aad9e5b7e9d6f479e6cf7555f5845bbbaaadbc66"
source = "git+https://github.com/toeverything/OctoBase.git?rev=49a6b7a#49a6b7af25ce1fe54e8383e10980e9536821d286"
dependencies = [
"async-trait",
"base64",
@@ -1151,7 +1162,7 @@ dependencies = [
[[package]]
name = "jwst-logger"
version = "0.1.0"
source = "git+https://github.com/toeverything/OctoBase.git?rev=aad9e5b#aad9e5b7e9d6f479e6cf7555f5845bbbaaadbc66"
source = "git+https://github.com/toeverything/OctoBase.git?rev=49a6b7a#49a6b7af25ce1fe54e8383e10980e9536821d286"
dependencies = [
"chrono",
"nu-ansi-term 0.49.0",
@@ -1164,7 +1175,7 @@ dependencies = [
[[package]]
name = "jwst-storage"
version = "0.1.0"
source = "git+https://github.com/toeverything/OctoBase.git?rev=aad9e5b#aad9e5b7e9d6f479e6cf7555f5845bbbaaadbc66"
source = "git+https://github.com/toeverything/OctoBase.git?rev=49a6b7a#49a6b7af25ce1fe54e8383e10980e9536821d286"
dependencies = [
"anyhow",
"async-trait",
@@ -1189,7 +1200,7 @@ dependencies = [
[[package]]
name = "jwst-storage-migration"
version = "0.1.0"
source = "git+https://github.com/toeverything/OctoBase.git?rev=aad9e5b#aad9e5b7e9d6f479e6cf7555f5845bbbaaadbc66"
source = "git+https://github.com/toeverything/OctoBase.git?rev=49a6b7a#49a6b7af25ce1fe54e8383e10980e9536821d286"
dependencies = [
"sea-orm-migration",
"tokio",
@@ -1257,9 +1268,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "libsqlite3-sys"
version = "0.26.0"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326"
checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716"
dependencies = [
"cc",
"pkg-config",
@@ -1337,6 +1348,15 @@ version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@@ -1375,9 +1395,9 @@ dependencies = [
[[package]]
name = "napi"
version = "2.14.0"
version = "2.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d90182620f32fe34b6ac9b52cba898af26e94c7f5abc01eb4094c417ae2e6c"
checksum = "1133249c46e92da921bafc8aba4912bf84d6c475f7625183772ed2d0844dc3a7"
dependencies = [
"anyhow",
"bitflags 2.4.1",
@@ -1399,9 +1419,9 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df"
[[package]]
name = "napi-derive"
version = "2.14.1"
version = "2.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3619fa472d23cd5af94d63a2bae454a77a8863251f40230fbf59ce20eafa8a86"
checksum = "a0cca5738c6e81eb5ffd2c8ff2b4f05ece9c4c60c7e2b36cec6524492cf7f330"
dependencies = [
"cfg-if",
"convert_case",
@@ -1413,9 +1433,9 @@ dependencies = [
[[package]]
name = "napi-derive-backend"
version = "1.0.54"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecd3ea4b54020c73d591a49cd192f6334c5f37f71a63ead54dbc851fa991ef00"
checksum = "35960e5f33228192a9b661447d0dfe8f5a3790ff5b4058c4d67680ded4f65b91"
dependencies = [
"convert_case",
"once_cell",
@@ -1435,6 +1455,19 @@ dependencies = [
"libloading",
]
[[package]]
name = "nix"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
dependencies = [
"bitflags 1.3.2",
"cfg-if",
"libc",
"memoffset",
"pin-utils",
]
[[package]]
name = "no-std-compat"
version = "0.4.1"
@@ -2292,18 +2325,18 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]]
name = "serde"
version = "1.0.192"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.192"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
@@ -2450,9 +2483,9 @@ dependencies = [
[[package]]
name = "sqlx"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33"
checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf"
dependencies = [
"sqlx-core",
"sqlx-macros",
@@ -2463,11 +2496,11 @@ dependencies = [
[[package]]
name = "sqlx-core"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d"
checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd"
dependencies = [
"ahash 0.8.3",
"ahash 0.8.6",
"atoi",
"bigdecimal",
"byteorder",
@@ -2511,9 +2544,9 @@ dependencies = [
[[package]]
name = "sqlx-macros"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec"
checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5"
dependencies = [
"proc-macro2",
"quote",
@@ -2524,10 +2557,11 @@ dependencies = [
[[package]]
name = "sqlx-macros-core"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc"
checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841"
dependencies = [
"atomic-write-file",
"dotenvy",
"either",
"heck",
@@ -2550,9 +2584,9 @@ dependencies = [
[[package]]
name = "sqlx-mysql"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db"
checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4"
dependencies = [
"atoi",
"base64",
@@ -2597,9 +2631,9 @@ dependencies = [
[[package]]
name = "sqlx-postgres"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624"
checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24"
dependencies = [
"atoi",
"base64",
@@ -2642,9 +2676,9 @@ dependencies = [
[[package]]
name = "sqlx-sqlite"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f"
checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490"
dependencies = [
"atoi",
"chrono",
@@ -2662,6 +2696,7 @@ dependencies = [
"time",
"tracing",
"url",
"urlencoding",
"uuid",
]
@@ -3024,6 +3059,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "utf8parse"
version = "0.2.1"
@@ -3032,9 +3073,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.6.0"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c58fe91d841bc04822c9801002db4ea904b9e4b8e6bbad25127b46eff8dc516b"
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
dependencies = [
"getrandom",
"rand",
@@ -3141,12 +3182,9 @@ dependencies = [
[[package]]
name = "webpki-roots"
version = "0.24.0"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888"
dependencies = [
"rustls-webpki",
]
checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
[[package]]
name = "whoami"
@@ -3278,6 +3316,26 @@ dependencies = [
"tap",
]
[[package]]
name = "zerocopy"
version = "0.7.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.38",
]
[[package]]
name = "zeroize"
version = "1.6.0"

View File

@@ -107,12 +107,11 @@ If you have questions, you are welcome to contact us. One of the best places to
## Ecosystem
| Name | | |
| ----------------------------------------------------------------------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| [@toeverything/component](https://github.com/toeverything/design/tree/main/packages/components) | Toeverything Shared Component Resources | |
| [@affine/component](packages/frontend/component) | AFFiNE Component Resources | [![](https://img.shields.io/codecov/c/github/toeverything/affine?style=flat-square)](https://affine-storybook.vercel.app/) |
| [@toeverything/y-indexeddb](packages/common/y-indexeddb) | IndexedDB database adapter for Yjs | [![](https://img.shields.io/npm/dm/@toeverything/y-indexeddb?style=flat-square&color=eee)](https://www.npmjs.com/package/@toeverything/y-indexeddb) |
| [@toeverything/theme](packages/common/theme) | AFFiNE theme | [![](https://img.shields.io/npm/dm/@toeverything/theme?style=flat-square&color=eee)](https://www.npmjs.com/package/@toeverything/theme) |
| Name | | |
| -------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| [@affine/component](packages/frontend/component) | AFFiNE Component Resources | [![](https://img.shields.io/codecov/c/github/toeverything/affine?style=flat-square)](https://affine-storybook.vercel.app/) |
| [@toeverything/y-indexeddb](packages/common/y-indexeddb) | IndexedDB database adapter for Yjs | [![](https://img.shields.io/npm/dm/@toeverything/y-indexeddb?style=flat-square&color=eee)](https://www.npmjs.com/package/@toeverything/y-indexeddb) |
| [@toeverything/theme](packages/common/theme) | AFFiNE theme | [![](https://img.shields.io/npm/dm/@toeverything/theme?style=flat-square&color=eee)](https://www.npmjs.com/package/@toeverything/theme) |
## Plugins
@@ -228,7 +227,7 @@ See [LICENSE] for details.
[jobs available]: ./docs/jobs.md
[latest packages]: https://github.com/toeverything/AFFiNE/pkgs/container/affine-self-hosted
[contributor license agreement]: https://github.com/toeverything/affine/edit/canary/.github/CLA.md
[rust-version-icon]: https://img.shields.io/badge/Rust-1.71.0-dea584
[rust-version-icon]: https://img.shields.io/badge/Rust-1.74.1-dea584
[stars-icon]: https://img.shields.io/github/stars/toeverything/AFFiNE.svg?style=flat&logo=github&colorB=red&label=stars
[codecov]: https://codecov.io/gh/toeverything/affine/branch/canary/graphs/badge.svg?branch=canary
[node-version-icon]: https://img.shields.io/badge/node-%3E=18.16.1-success

28
docs/issue-triaging.md Normal file
View File

@@ -0,0 +1,28 @@
# Issues Triaging
When we receive your issue, we will first triaging it. Triaging an issue usually takes around one business day but may take longer. Goal of triaging is to provide you with a clear understanding of what will happen to your issue. For example, after your feature request was triaged you know whether we plan to tackle the issue or whether we'll wait to hear what the broader community thinks about this request.
Here are issue states and their descriptions:
| State | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Untriaged | The team has not yet reviewed the issue. We usually do it within one business day. |
| As designed | The behavior described in the issue is intentional. If you find it seriously disruptive or if weve misunderstood you, please let us know in the issues comments section. |
| Blocked | We cant work on this issue until another one (linked) is resolved. |
| Cant Reproduce | We have been unable to reproduce the issue on our side. It could be flaky or fixed already, or we may not have had all the details we needed. If youre still experiencing the issue and have any further details, please share them. |
| Duplicate | The issue is the same (or has the same cause) as another one (linked). |
| Fixed | If the issue was a bug, its been fixed; if it was a missing feature, its been implemented. |
| Fixed In Branch | If the issue was a bug, its been fixed; if it was a missing feature, its been implemented; the changes are now in a separate branch and havent been merged into the default branch yet. |
| In Progress | Were currently working on the issue. |
| Incomplete | Unfortunately we dont have enough information to proceed. If youre willing to share any further details about the issue, please do so in the comments. |
| Obsolete | The part of the product that was causing this issue has been removed or significantly reworked since it was created. |
| Upvoting | We are currently evaluating demand for the issue and checking whether it requires complicated or risky changes. Please leave a vote or comment if you think it should be prioritized. |
| Open | We want to implement the fix or feature in the near future. We cant promise it will appear in the next public release, but its on our short list. |
| Shelved | We have reviewed the issue and decided that, even though it has merit, we cannot currently include it in our near-term plan. |
| Third Party Problem | The issue is caused by a third party. We've done our best to inform them about it. |
| To be Discussed | We need some time to discuss the issue. |
| To Reproduce | We will try to find the steps needed to reproduce the issue on our side. |
| Under Investigation | Weve triaged the issue, but now we need to investigate it more thoroughly. This may require processing additional information like logs or dumps. |
| Waiting for Info | Weve requested additional information from the person who created the issue and are waiting for them to get back to us. |
| Declined | Weve reviewed the suggestion and, while we appreciate its value, we unfortunately do not have the resources to implement it. |
| Answered | The issue actually turned out to be a question or a misunderstanding, and it has been answered or resolved. |

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/monorepo",
"version": "0.10.3",
"version": "0.10.4-beta.2",
"private": true,
"author": "toeverything",
"license": "MIT",
@@ -33,12 +33,12 @@
"lint:eslint:fix": "yarn lint:eslint --fix",
"lint:prettier": "prettier --ignore-unknown --cache --check .",
"lint:prettier:fix": "prettier --ignore-unknown --cache --write .",
"lint:ox": "oxlint --deny-warnings --import-plugin -D correctness -D nursery -D prefer-array-some -D no-useless-promise-resolve-reject -A no-undef -A consistent-type-exports -A default -A named -A ban-ts-comment",
"lint": "yarn lint:eslint && yarn lint:prettier",
"lint:fix": "yarn lint:eslint:fix && yarn lint:prettier:fix",
"test": "vitest --run",
"test:ui": "vitest --ui",
"test:coverage": "vitest run --coverage",
"circular": "madge --circular --ts-config ./tsconfig.json ./packages/frontend/core/src/pages/**/*.tsx ./packages/frontend/core/src/index.tsx ./packages/frontend/electron/src/*/index.ts",
"typecheck": "tsc -b tsconfig.json --diagnostics",
"postinstall": "node ./scripts/check-version.mjs && yarn i18n-codegen gen && yarn husky install"
},
@@ -49,8 +49,10 @@
"eslint --cache --fix"
],
"*.toml": [
"prettier --ignore-unknown --write",
"taplo format"
],
"*.rs": [
"cargo fmt --"
]
},
"devDependencies": {
@@ -71,8 +73,8 @@
"@types/affine__env": "workspace:*",
"@types/eslint": "^8.44.7",
"@types/node": "^20.9.3",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"@vanilla-extract/vite-plugin": "^3.9.2",
"@vanilla-extract/webpack-plugin": "^2.3.1",
"@vitejs/plugin-react-swc": "^3.5.0",
@@ -82,7 +84,6 @@
"eslint": "^8.54.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-i": "^2.29.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
@@ -94,29 +95,29 @@
"happy-dom": "^12.10.3",
"husky": "^8.0.3",
"lint-staged": "^15.1.0",
"madge": "^6.1.0",
"msw": "^2.0.8",
"nanoid": "^5.0.3",
"nx": "^17.1.3",
"nx-cloud": "^16.5.2",
"nyc": "^15.1.0",
"oxlint": "^0.0.18",
"prettier": "^3.1.0",
"semver": "^7.5.4",
"serve": "^14.2.1",
"string-width": "^7.0.0",
"ts-node": "^10.9.1",
"typescript": "^5.3.2",
"vite": "^5.0.1",
"vite": "^5.0.6",
"vite-plugin-istanbul": "^5.0.0",
"vite-plugin-static-copy": "^0.17.1",
"vite-plugin-static-copy": "^1.0.0",
"vite-tsconfig-paths": "^4.2.1",
"vitest": "0.34.6",
"vitest-fetch-mock": "^0.2.2",
"vitest-mock-extended": "^1.3.1"
},
"packageManager": "yarn@4.0.1",
"packageManager": "yarn@4.0.2",
"resolutions": {
"vite": "^4.4.11",
"vite": "^5.0.6",
"array-buffer-byte-length": "npm:@nolyfill/array-buffer-byte-length@latest",
"array-includes": "npm:@nolyfill/array-includes@latest",
"array.prototype.flat": "npm:@nolyfill/array.prototype.flat@latest",
@@ -173,7 +174,7 @@
"which-boxed-primitive": "npm:@nolyfill/which-boxed-primitive@latest",
"which-typed-array": "npm:@nolyfill/which-typed-array@latest",
"next-auth@^4.24.5": "patch:next-auth@npm%3A4.24.5#~/.yarn/patches/next-auth-npm-4.24.5-8428e11927.patch",
"@reforged/maker-appimage/@electron-forge/maker-base": "7.1.0",
"@reforged/maker-appimage/@electron-forge/maker-base": "7.2.0",
"macos-alias": "npm:macos-alias-building@latest",
"fs-xattr": "npm:@napi-rs/xattr@latest"
}

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "optimized_blobs" ADD COLUMN "deleted_at" TIMESTAMPTZ(6);

View File

@@ -1,7 +1,7 @@
{
"name": "@affine/server",
"private": true,
"version": "0.10.3",
"version": "0.10.4-beta.2",
"description": "Affine Node.js server",
"type": "module",
"bin": {
@@ -41,13 +41,14 @@
"@opentelemetry/core": "^1.18.1",
"@opentelemetry/exporter-prometheus": "^0.45.1",
"@opentelemetry/exporter-zipkin": "^1.18.1",
"@opentelemetry/host-metrics": "^0.33.2",
"@opentelemetry/host-metrics": "^0.34.0",
"@opentelemetry/instrumentation": "^0.45.1",
"@opentelemetry/instrumentation-graphql": "^0.36.0",
"@opentelemetry/instrumentation-http": "^0.45.1",
"@opentelemetry/instrumentation-ioredis": "^0.35.3",
"@opentelemetry/instrumentation-ioredis": "^0.36.0",
"@opentelemetry/instrumentation-nestjs-core": "^0.33.3",
"@opentelemetry/instrumentation-socket.io": "^0.34.3",
"@opentelemetry/resources": "^1.18.1",
"@opentelemetry/sdk-metrics": "^1.18.1",
"@opentelemetry/sdk-node": "^0.45.1",
"@opentelemetry/sdk-trace-node": "^1.18.1",
@@ -101,7 +102,7 @@
"@types/sinon": "^17.0.2",
"@types/supertest": "^2.0.16",
"@types/ws": "^8.5.10",
"ava": "^5.3.1",
"ava": "^6.0.0",
"c8": "^8.0.1",
"nodemon": "^3.0.1",
"sinon": "^17.0.1",

View File

@@ -178,13 +178,15 @@ model Blob {
}
model OptimizedBlob {
id Int @id @default(autoincrement()) @db.Integer
hash String @db.VarChar
workspaceId String @map("workspace_id") @db.VarChar
params String @db.VarChar
blob Bytes @db.ByteA
id Int @id @default(autoincrement()) @db.Integer
hash String @db.VarChar
workspaceId String @map("workspace_id") @db.VarChar
params String @db.VarChar
blob Bytes @db.ByteA
length BigInt
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
// not for keeping, but for snapshot history
deletedAt DateTime? @map("deleted_at") @db.Timestamptz(6)
@@unique([workspaceId, hash, params])
@@map("optimized_blobs")

View File

@@ -3,6 +3,7 @@ import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { CacheModule } from './cache';
import { ConfigModule } from './config';
import { EventModule } from './event';
import { BusinessModules } from './modules';
import { AuthModule } from './modules/auth';
import { PrismaModule } from './prisma';
@@ -14,6 +15,7 @@ const BasicModules = [
PrismaModule,
ConfigModule.forRoot(),
CacheModule,
EventModule,
StorageModule.forRoot(),
SessionModule,
RateLimiterModule,

View File

@@ -50,7 +50,7 @@ function boolean(value: string) {
}
export function parseEnvValue(value: string | undefined, type?: EnvConfigType) {
if (typeof value === 'undefined') {
if (value === undefined) {
return;
}

View File

@@ -10,7 +10,7 @@ export function applyEnvToConfig(rawConfig: AFFiNEConfig) {
? [config, process.env[env]]
: [config[0], parseEnvValue(process.env[env], config[1])];
if (typeof value !== 'undefined') {
if (value !== undefined) {
set(rawConfig, path, value);
}
}

View File

@@ -0,0 +1,23 @@
import type { Snapshot, Workspace } from '@prisma/client';
import { Flatten, Payload } from './types';
interface EventDefinitions {
workspace: {
deleted: Payload<Workspace['id']>;
};
snapshot: {
updated: Payload<
Pick<Snapshot, 'id' | 'workspaceId'> & {
previous: Pick<Snapshot, 'blob' | 'state' | 'updatedAt'>;
}
>;
deleted: Payload<Pick<Snapshot, 'id' | 'workspaceId'>>;
};
}
export type EventKV = Flatten<EventDefinitions>;
export type Event = keyof EventKV;
export type EventPayload<E extends Event> = EventKV[E];

View File

@@ -0,0 +1,45 @@
import { Global, Injectable, Module } from '@nestjs/common';
import {
EventEmitter2,
EventEmitterModule,
OnEvent as RawOnEvent,
} from '@nestjs/event-emitter';
import type { Event, EventPayload } from './events';
@Injectable()
export class EventEmitter {
constructor(private readonly emitter: EventEmitter2) {}
emit<E extends Event>(event: E, payload: EventPayload<E>) {
return this.emitter.emit(event, payload);
}
emitAsync<E extends Event>(event: E, payload: EventPayload<E>) {
return this.emitter.emitAsync(event, payload);
}
on<E extends Event>(event: E, handler: (payload: EventPayload<E>) => void) {
return this.emitter.on(event, handler);
}
once<E extends Event>(event: E, handler: (payload: EventPayload<E>) => void) {
return this.emitter.once(event, handler);
}
}
export const OnEvent = (
event: Event,
opts?: Parameters<typeof RawOnEvent>[1]
) => {
return RawOnEvent(event, opts);
};
@Global()
@Module({
imports: [EventEmitterModule.forRoot()],
providers: [EventEmitter],
exports: [EventEmitter],
})
export class EventModule {}
export { EventPayload };

View File

@@ -0,0 +1,33 @@
export type Payload<T> = {
__payload: true;
data: T;
};
export type Join<A extends string, B extends string> = A extends ''
? B
: `${A}.${B}`;
export type PathType<T, Path extends string> = string extends Path
? unknown
: Path extends keyof T
? T[Path]
: Path extends `${infer K}.${infer R}`
? K extends keyof T
? PathType<T[K], R>
: unknown
: unknown;
export type Leaves<T, P extends string = ''> = T extends Payload<any>
? P
: T extends Record<string, any>
? {
[K in keyof T]: K extends string ? Leaves<T[K], Join<P, K>> : never;
}[keyof T]
: never;
export type Flatten<T> = Leaves<T> extends infer R
? {
// @ts-expect-error yo, ts can't make it
[K in R]: PathType<T, K> extends Payload<infer U> ? U : never;
}
: never;

View File

@@ -20,7 +20,7 @@ export class GQLLoggerPlugin implements ApolloServerPlugin {
const res = reqContext.contextValue.req.res as Response;
const operation = reqContext.request.operationName;
metrics().gqlRequest.add(1, { operation });
metrics.gql.counter('query_counter').add(1, { operation });
const start = Date.now();
return Promise.resolve({
@@ -30,7 +30,9 @@ export class GQLLoggerPlugin implements ApolloServerPlugin {
'Server-Timing',
`gql;dur=${costInMilliseconds};desc="GraphQL"`
);
metrics().gqlTimer.record(costInMilliseconds, { operation });
metrics.gql
.histogram('query_duration')
.record(costInMilliseconds, { operation });
return Promise.resolve();
},
didEncounterErrors: () => {
@@ -39,7 +41,9 @@ export class GQLLoggerPlugin implements ApolloServerPlugin {
'Server-Timing',
`gql;dur=${costInMilliseconds};desc="GraphQL ${operation}"`
);
metrics().gqlTimer.record(costInMilliseconds, { operation });
metrics.gql
.histogram('query_duration')
.record(costInMilliseconds, { operation });
return Promise.resolve();
},
});

View File

@@ -1,76 +1,129 @@
import opentelemetry, { Attributes, Observable } from '@opentelemetry/api';
import {
Attributes,
Counter,
Histogram,
Meter,
MetricOptions,
} from '@opentelemetry/api';
interface AsyncMetric {
ob: Observable;
get value(): any;
get attrs(): Attributes | undefined;
}
import { getMeter } from './opentelemetry';
let _metrics: ReturnType<typeof createBusinessMetrics> | undefined = undefined;
type MetricType = 'counter' | 'gauge' | 'histogram';
type Metric<T extends MetricType> = T extends 'counter'
? Counter
: T extends 'gauge'
? Histogram
: T extends 'histogram'
? Histogram
: never;
export function getMeter(name = 'business') {
return opentelemetry.metrics.getMeter(name);
}
export type ScopedMetrics = {
[T in MetricType]: (name: string, opts?: MetricOptions) => Metric<T>;
};
type MetricCreators = {
[T in MetricType]: (
meter: Meter,
name: string,
opts?: MetricOptions
) => Metric<T>;
};
function createBusinessMetrics() {
const meter = getMeter();
const asyncMetrics: AsyncMetric[] = [];
export type KnownMetricScopes =
| 'socketio'
| 'gql'
| 'jwst'
| 'auth'
| 'controllers'
| 'doc';
function createGauge(name: string) {
const metricCreators: MetricCreators = {
counter(meter: Meter, name: string, opts?: MetricOptions) {
return meter.createCounter(name, opts);
},
gauge(meter: Meter, name: string, opts?: MetricOptions) {
let value: any;
let attrs: Attributes | undefined;
const ob = meter.createObservableGauge(name);
asyncMetrics.push({
ob,
get value() {
return value;
},
get attrs() {
return attrs;
},
const ob = meter.createObservableGauge(name, opts);
ob.addCallback(result => {
result.observe(value, attrs);
});
return (newValue: any, newAttrs?: Attributes) => {
value = newValue;
attrs = newAttrs;
};
return {
record: (newValue, newAttrs) => {
value = newValue;
attrs = newAttrs;
},
} satisfies Histogram;
},
histogram(meter: Meter, name: string, opts?: MetricOptions) {
return meter.createHistogram(name, opts);
},
};
const scopes = new Map<string, ScopedMetrics>();
function make(scope: string) {
const meter = getMeter();
const metrics = new Map<string, { type: MetricType; metric: any }>();
const prefix = scope + '/';
function getOrCreate<T extends MetricType>(
type: T,
name: string,
opts?: MetricOptions
): Metric<T> {
name = prefix + name;
const metric = metrics.get(name);
if (metric) {
if (type !== metric.type) {
throw new Error(
`Metric ${name} has already been registered as ${metric.type} mode, but get as ${type} again.`
);
}
return metric.metric;
} else {
const metric = metricCreators[type](meter, name, opts);
metrics.set(name, { type, metric });
return metric;
}
}
const metrics = {
socketIOConnectionGauge: createGauge('socket_io_connection'),
gqlRequest: meter.createCounter('gql_request'),
gqlError: meter.createCounter('gql_error'),
gqlTimer: meter.createHistogram('gql_timer'),
jwstCodecMerge: meter.createCounter('jwst_codec_merge'),
jwstCodecDidnotMatch: meter.createCounter('jwst_codec_didnot_match'),
jwstCodecFail: meter.createCounter('jwst_codec_fail'),
authCounter: meter.createCounter('auth'),
authFailCounter: meter.createCounter('auth_fail'),
docHistoryCounter: meter.createCounter('doc_history_created'),
docRecoverCounter: meter.createCounter('doc_history_recovered'),
};
meter.addBatchObservableCallback(
result => {
asyncMetrics.forEach(metric => {
result.observe(metric.ob, metric.value, metric.attrs);
});
return {
counter(name, opts) {
return getOrCreate('counter', name, opts);
},
asyncMetrics.map(({ ob }) => ob)
);
return metrics;
gauge(name, opts) {
return getOrCreate('gauge', name, opts);
},
histogram(name, opts) {
return getOrCreate('histogram', name, opts);
},
} satisfies ScopedMetrics;
}
export function registerBusinessMetrics() {
if (!_metrics) {
_metrics = createBusinessMetrics();
/**
* @example
*
* ```
* metrics.scope.counter('example_count').add(1, {
* attr1: 'example-event'
* })
* ```
*/
export const metrics = new Proxy<Record<KnownMetricScopes, ScopedMetrics>>(
// @ts-expect-error proxied
{},
{
get(_, scopeName: string) {
let scope = scopes.get(scopeName);
if (!scope) {
scope = make(scopeName);
scopes.set(scopeName, scope);
}
return scope;
},
}
return _metrics;
}
export const metrics = registerBusinessMetrics;
);

View File

@@ -1,5 +1,6 @@
import { MetricExporter } from '@google-cloud/opentelemetry-cloud-monitoring-exporter';
import { TraceExporter } from '@google-cloud/opentelemetry-cloud-trace-exporter';
import { metrics } from '@opentelemetry/api';
import {
CompositePropagator,
W3CBaggagePropagator,
@@ -16,6 +17,8 @@ import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core'
import { SocketIoInstrumentation } from '@opentelemetry/instrumentation-socket.io';
import {
ConsoleMetricExporter,
type MeterProvider,
MetricProducer,
MetricReader,
PeriodicExportingMetricReader,
} from '@opentelemetry/sdk-metrics';
@@ -24,10 +27,11 @@ import {
BatchSpanProcessor,
ConsoleSpanExporter,
SpanExporter,
TraceIdRatioBasedSampler,
} from '@opentelemetry/sdk-trace-node';
import { PrismaInstrumentation } from '@prisma/instrumentation';
import { registerBusinessMetrics } from './metrics';
import { PrismaMetricProducer } from './prisma';
abstract class OpentelemetryFactor {
abstract getMetricReader(): MetricReader;
@@ -44,9 +48,14 @@ abstract class OpentelemetryFactor {
];
}
getMetricsProducers(): MetricProducer[] {
return [new PrismaMetricProducer()];
}
create() {
const traceExporter = this.getSpanExporter();
return new NodeSDK({
sampler: new TraceIdRatioBasedSampler(0.1),
traceExporter,
metricReader: this.getMetricReader(),
spanProcessor: new BatchSpanProcessor(traceExporter),
@@ -67,7 +76,10 @@ class GCloudOpentelemetryFactor extends OpentelemetryFactor {
return new PeriodicExportingMetricReader({
exportIntervalMillis: 30000,
exportTimeoutMillis: 10000,
exporter: new MetricExporter(),
exporter: new MetricExporter({
prefix: 'custom.googleapis.com',
}),
metricProducers: this.getMetricsProducers(),
});
}
@@ -78,7 +90,9 @@ class GCloudOpentelemetryFactor extends OpentelemetryFactor {
class LocalOpentelemetryFactor extends OpentelemetryFactor {
override getMetricReader(): MetricReader {
return new PrometheusExporter();
return new PrometheusExporter({
metricProducers: this.getMetricsProducers(),
});
}
override getSpanExporter(): SpanExporter {
@@ -90,6 +104,7 @@ class DebugOpentelemetryFactor extends OpentelemetryFactor {
override getMetricReader(): MetricReader {
return new PeriodicExportingMetricReader({
exporter: new ConsoleMetricExporter(),
metricProducers: this.getMetricsProducers(),
});
}
@@ -111,9 +126,30 @@ function createSDK() {
return factor?.create();
}
let OPENTELEMETRY_STARTED = false;
function ensureStarted() {
if (!OPENTELEMETRY_STARTED) {
OPENTELEMETRY_STARTED = true;
start();
}
}
function getMeterProvider() {
ensureStarted();
return metrics.getMeterProvider();
}
function registerCustomMetrics() {
const host = new HostMetrics({ name: 'instance-host-metrics' });
host.start();
const hostMetricsMonitoring = new HostMetrics({
name: 'instance-host-metrics',
meterProvider: getMeterProvider() as MeterProvider,
});
hostMetricsMonitoring.start();
}
export function getMeter(name = 'business') {
return getMeterProvider().getMeter(name);
}
export function start() {
@@ -122,6 +158,5 @@ export function start() {
if (sdk) {
sdk.start();
registerCustomMetrics();
registerBusinessMetrics();
}
}

View File

@@ -0,0 +1,132 @@
import { HrTime, ValueType } from '@opentelemetry/api';
import { hrTime } from '@opentelemetry/core';
import { Resource } from '@opentelemetry/resources';
import {
AggregationTemporality,
CollectionResult,
DataPointType,
InstrumentType,
MetricProducer,
ScopeMetrics,
} from '@opentelemetry/sdk-metrics';
import { PrismaService } from '../prisma';
function transformPrismaKey(key: string) {
// replace first '_' to '/' as a scope prefix
// example: prisma_client_query_duration_seconds_sum -> prisma/client_query_duration_seconds_sum
return key.replace(/_/, '/');
}
export class PrismaMetricProducer implements MetricProducer {
private readonly startTime: HrTime = hrTime();
async collect(): Promise<CollectionResult> {
const result: CollectionResult = {
resourceMetrics: {
resource: Resource.EMPTY,
scopeMetrics: [],
},
errors: [],
};
if (!PrismaService.INSTANCE) {
return result;
}
const prisma = PrismaService.INSTANCE;
const endTime = hrTime();
const metrics = await prisma.$metrics.json();
const scopeMetrics: ScopeMetrics = {
scope: {
name: '',
},
metrics: [],
};
for (const counter of metrics.counters) {
scopeMetrics.metrics.push({
descriptor: {
name: transformPrismaKey(counter.key),
description: counter.description,
unit: '1',
type: InstrumentType.COUNTER,
valueType: ValueType.INT,
},
dataPointType: DataPointType.SUM,
aggregationTemporality: AggregationTemporality.CUMULATIVE,
dataPoints: [
{
startTime: this.startTime,
endTime: endTime,
value: counter.value,
attributes: counter.labels,
},
],
isMonotonic: true,
});
}
for (const gauge of metrics.gauges) {
scopeMetrics.metrics.push({
descriptor: {
name: transformPrismaKey(gauge.key),
description: gauge.description,
unit: '1',
type: InstrumentType.UP_DOWN_COUNTER,
valueType: ValueType.INT,
},
dataPointType: DataPointType.GAUGE,
aggregationTemporality: AggregationTemporality.CUMULATIVE,
dataPoints: [
{
startTime: this.startTime,
endTime: endTime,
value: gauge.value,
attributes: gauge.labels,
},
],
});
}
for (const histogram of metrics.histograms) {
const boundaries = [];
const counts = [];
for (const [boundary, count] of histogram.value.buckets) {
boundaries.push(boundary);
counts.push(count);
}
scopeMetrics.metrics.push({
descriptor: {
name: transformPrismaKey(histogram.key),
description: histogram.description,
unit: 'ms',
type: InstrumentType.HISTOGRAM,
valueType: ValueType.DOUBLE,
},
dataPointType: DataPointType.HISTOGRAM,
aggregationTemporality: AggregationTemporality.CUMULATIVE,
dataPoints: [
{
startTime: this.startTime,
endTime: endTime,
value: {
buckets: {
boundaries,
counts,
},
count: histogram.value.count,
sum: histogram.value.sum,
},
attributes: histogram.labels,
},
],
});
}
result.resourceMetrics.scopeMetrics.push(scopeMetrics);
return result;
}
}

View File

@@ -1,8 +1,9 @@
import { Attributes } from '@opentelemetry/api';
import { getMeter } from './metrics';
import { KnownMetricScopes, metrics } from './metrics';
export const CallTimer = (
scope: KnownMetricScopes,
name: string,
attrs?: Attributes
): MethodDecorator => {
@@ -18,9 +19,11 @@ export const CallTimer = (
}
desc.value = function (...args: any[]) {
const timer = getMeter().createHistogram(name, {
const timer = metrics[scope].histogram(name, {
description: `function call time costs of ${name}`,
unit: 'ms',
});
const start = Date.now();
const end = () => {
@@ -48,6 +51,7 @@ export const CallTimer = (
};
export const CallCounter = (
scope: KnownMetricScopes,
name: string,
attrs?: Attributes
): MethodDecorator => {
@@ -63,7 +67,7 @@ export const CallCounter = (
}
desc.value = function (...args: any[]) {
const count = getMeter().createCounter(name, {
const count = metrics[scope].counter(name, {
description: `function call counter of ${name}`,
});

View File

@@ -14,7 +14,7 @@ const TrivialExceptions = [NotFoundException];
@Catch()
export class ExceptionLogger implements ExceptionFilter {
private logger = new Logger('ExceptionLogger');
private readonly logger = new Logger('ExceptionLogger');
catch(exception: Error, host: ArgumentsHost) {
// with useGlobalFilters, the context is always HTTP

View File

@@ -53,8 +53,8 @@ class AuthGuard implements CanActivate {
constructor(
@Inject(NextAuthOptionsProvide)
private readonly nextAuthOptions: NextAuthOptions,
private auth: AuthService,
private prisma: PrismaService,
private readonly auth: AuthService,
private readonly prisma: PrismaService,
private readonly reflector: Reflector
) {}

View File

@@ -89,12 +89,13 @@ export class NextAuthController {
res.redirect(`/signin${query}`);
return;
}
metrics().authCounter.add(1);
const [action, providerId] = req.url // start with request url
.slice(BASE_URL.length) // make relative to baseUrl
.replace(/\?.*/, '') // remove query part, use only path part
.split('/') as [AuthAction, string]; // as array of strings;
metrics.auth.counter('call_counter').add(1, { action, providerId });
const credentialsSignIn =
req.method === 'POST' && providerId === 'credentials';
let userId: string | undefined;
@@ -126,7 +127,9 @@ export class NextAuthController {
const options = this.nextAuthOptions;
if (req.method === 'POST' && action === 'session') {
if (typeof req.body !== 'object' || typeof req.body.data !== 'object') {
metrics().authFailCounter.add(1, { reason: 'invalid_session_data' });
metrics.auth
.counter('call_fails_counter')
.add(1, { reason: 'invalid_session_data' });
throw new BadRequestException(`Invalid new session data`);
}
const user = await this.updateSession(req, req.body.data);
@@ -209,9 +212,10 @@ export class NextAuthController {
if (redirect?.endsWith('api/auth/error?error=AccessDenied')) {
this.logger.log(`Early access redirect headers: ${req.headers}`);
metrics().authFailCounter.add(1, {
reason: 'no_early_access_permission',
});
metrics.auth
.counter('call_fails_counter')
.add(1, { reason: 'no_early_access_permission' });
if (
!req.headers?.referer ||
checkUrlOrigin(req.headers.referer, 'https://accounts.google.com')

View File

@@ -23,14 +23,14 @@ export type UserClaim = Pick<
hasPassword?: boolean;
};
export const getUtcTimestamp = () => Math.floor(new Date().getTime() / 1000);
export const getUtcTimestamp = () => Math.floor(Date.now() / 1000);
@Injectable()
export class AuthService {
constructor(
private config: Config,
private prisma: PrismaService,
private mailer: MailService
private readonly config: Config,
private readonly prisma: PrismaService,
private readonly mailer: MailService
) {}
sign(user: UserClaim) {

View File

@@ -0,0 +1,30 @@
import { Module } from '@nestjs/common';
import { Field, ObjectType, Query } from '@nestjs/graphql';
export const { SERVER_FLAVOR } = process.env;
@ObjectType()
export class ServerConfigType {
@Field({ description: 'server version' })
version!: string;
@Field({ description: 'server flavor' })
flavor!: string;
}
export class ServerConfigResolver {
@Query(() => ServerConfigType, {
description: 'server config',
})
serverConfig(): ServerConfigType {
return {
version: AFFiNE.version,
flavor: SERVER_FLAVOR || 'allinone',
};
}
}
@Module({
providers: [ServerConfigResolver],
})
export class ServerConfigModule {}

View File

@@ -1,15 +1,15 @@
import { isDeepStrictEqual } from 'node:util';
import { Injectable, Logger } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { Cron, CronExpression } from '@nestjs/schedule';
import type { Snapshot } from '@prisma/client';
import { Config } from '../../config';
import { type EventPayload, OnEvent } from '../../event';
import { metrics } from '../../metrics';
import { PrismaService } from '../../prisma';
import { SubscriptionStatus } from '../payment/service';
import { Permission } from '../workspaces/types';
import { isEmptyBuffer } from './manager';
@Injectable()
export class DocHistoryManager {
@@ -19,16 +19,38 @@ export class DocHistoryManager {
private readonly db: PrismaService
) {}
@OnEvent('doc:manager:snapshot:beforeUpdate')
async onDocUpdated(snapshot: Snapshot, forceCreate = false) {
const last = await this.last(snapshot.workspaceId, snapshot.id);
@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 === snapshot.updatedAt) {
} else if (last.timestamp === previous.updatedAt) {
// no change
shouldCreateHistory = false;
} else if (
@@ -36,16 +58,23 @@ export class DocHistoryManager {
forceCreate ||
// last history created before interval in configs
last.timestamp.getTime() <
snapshot.updatedAt.getTime() - this.config.doc.history.interval
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, snapshot.state)) {
if (last && isDeepStrictEqual(last.state, previous.state)) {
this.logger.debug(
`State matches, skip creating history record for ${snapshot.id} in workspace ${snapshot.workspaceId}`
`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;
}
@@ -56,22 +85,24 @@ export class DocHistoryManager {
timestamp: true,
},
data: {
workspaceId: snapshot.workspaceId,
id: snapshot.id,
timestamp: snapshot.updatedAt,
blob: snapshot.blob,
state: snapshot.state,
expiredAt: await this.getExpiredDateFromNow(snapshot.workspaceId),
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().docHistoryCounter.add(1, {});
this.logger.log(
`History created for ${snapshot.id} in workspace ${snapshot.workspaceId}.`
);
metrics.doc
.counter('history_created_counter', {
description: 'How many times the snapshot history created',
})
.add(1);
this.logger.log(`History created for ${id} in workspace ${workspaceId}.`);
}
}
@@ -89,7 +120,7 @@ export class DocHistoryManager {
workspaceId,
id,
timestamp: {
lte: before,
lt: before,
},
// only include the ones has not expired
expiredAt: {
@@ -176,13 +207,17 @@ export class DocHistoryManager {
}
// save old snapshot as one history record
await this.onDocUpdated(oldSnapshot, true);
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().docRecoverCounter.add(1, {});
metrics.doc
.counter('history_recovered_counter', {
description: 'How many times history recovered request happened',
})
.add(1);
return history.timestamp;
}

View File

@@ -5,12 +5,12 @@ import {
OnModuleDestroy,
OnModuleInit,
} from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Snapshot, Update } from '@prisma/client';
import { chunk } from 'lodash-es';
import { defer, retry } from 'rxjs';
import {
applyUpdate,
decodeStateVector,
Doc,
encodeStateAsUpdate,
encodeStateVector,
@@ -19,6 +19,7 @@ import {
import { Cache } from '../../cache';
import { Config } from '../../config';
import { EventEmitter, type EventPayload, OnEvent } from '../../event';
import { metrics } from '../../metrics/metrics';
import { PrismaService } from '../../prisma';
import { mergeUpdatesInApplyWay as jwstMergeUpdates } from '../../storage';
@@ -40,9 +41,39 @@ function compare(yBinary: Buffer, jwstBinary: Buffer, strict = false): boolean {
return compare(yBinary, yBinary2, true);
}
function isEmptyBuffer(buf: Buffer): boolean {
/**
* Detect whether rhs state is newer than lhs state.
*
* How could we tell a state is newer:
*
* i. if the state vector size is larger, it's newer
* ii. if the state vector size is same, compare each client's state
*/
function isStateNewer(lhs: Buffer, rhs: Buffer): boolean {
const lhsVector = decodeStateVector(lhs);
const rhsVector = decodeStateVector(rhs);
if (lhsVector.size < rhsVector.size) {
return true;
}
for (const [client, state] of lhsVector) {
const rstate = rhsVector.get(client);
if (!rstate) {
return false;
}
if (state < rstate) {
return true;
}
}
return false;
}
export function isEmptyBuffer(buf: Buffer): boolean {
return (
buf.length == 0 ||
buf.length === 0 ||
// 0x0000
(buf.length === 2 && buf[0] === 0 && buf[1] === 0)
);
@@ -60,9 +91,9 @@ const MAX_SEQ_NUM = 0x3fffffff; // u31
*/
@Injectable()
export class DocManager implements OnModuleInit, OnModuleDestroy {
private logger = new Logger(DocManager.name);
private readonly logger = new Logger(DocManager.name);
private job: NodeJS.Timeout | null = null;
private seqMap = new Map<string, number>();
private readonly seqMap = new Map<string, number>();
private busy = false;
constructor(
@@ -71,7 +102,7 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
private readonly db: PrismaService,
private readonly config: Config,
private readonly cache: Cache,
private readonly event: EventEmitter2
private readonly event: EventEmitter
) {}
onModuleInit() {
@@ -125,13 +156,13 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
this.config.doc.manager.experimentalMergeWithJwstCodec &&
updates.length < 100 /* avoid overloading */
) {
metrics().jwstCodecMerge.add(1);
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().jwstCodecDidnotMatch.add(1);
metrics.jwst.counter('codec_not_match').add(1);
this.logger.warn(
`jwst codec result doesn't match yjs codec result for: ${guid}`
);
@@ -142,7 +173,7 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
}
}
} catch (e) {
metrics().jwstCodecFail.add(1);
metrics.jwst.counter('codec_fails_counter').add(1);
this.logger.warn(`jwst apply update failed for ${guid}: ${e}`);
log = true;
} finally {
@@ -193,6 +224,33 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
}
}
@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.
*/
@@ -374,23 +432,17 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
}
const { id, workspaceId } = candidate;
// acquire lock
const ok = await this.lockUpdatesForAutoSquash(workspaceId, id);
if (!ok) {
return;
}
try {
await this._get(workspaceId, id);
} catch (e) {
this.logger.error(
`Failed to apply updates for workspace: ${workspaceId}, guid: ${id}`
);
this.logger.error(e);
} finally {
await this.unlockUpdatesForAutoSquash(workspaceId, id);
}
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() {
@@ -414,34 +466,67 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
doc: Doc,
initialSeq?: number
) {
const blob = Buffer.from(encodeStateAsUpdate(doc));
const state = Buffer.from(encodeStateVector(doc));
return this.lockSnapshotForUpsert(workspaceId, guid, async () => {
const blob = Buffer.from(encodeStateAsUpdate(doc));
if (isEmptyBuffer(blob)) {
return;
}
if (isEmptyBuffer(blob)) {
return false;
}
await this.db.snapshot.upsert({
select: {
seq: true,
},
where: {
id_workspaceId: {
id: guid,
workspaceId,
},
},
create: {
id: guid,
workspaceId,
blob,
state,
seq: initialSeq,
},
update: {
blob,
state,
},
const state = Buffer.from(encodeStateVector(doc));
return await this.db.$transaction(async db => {
const snapshot = await db.snapshot.findUnique({
where: {
id_workspaceId: {
id: guid,
workspaceId,
},
},
});
// update
if (snapshot) {
// only update if state is newer
if (isStateNewer(snapshot.state ?? Buffer.from([0]), state)) {
await db.snapshot.update({
select: {
seq: true,
},
where: {
id_workspaceId: {
workspaceId,
id: guid,
},
},
data: {
blob,
state,
},
});
return true;
} else {
return false;
}
} else {
// create
await db.snapshot.create({
select: {
seq: true,
},
data: {
id: guid,
workspaceId,
blob,
state,
seq: initialSeq,
},
});
return true;
}
});
});
}
@@ -480,15 +565,29 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
...updates.map(u => u.blob)
);
if (snapshot) {
this.event.emit('doc:manager:snapshot:beforeUpdate', snapshot);
const done = await this.upsert(workspaceId, id, doc, 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}`
);
}
await this.upsert(workspaceId, id, doc, last.seq);
this.logger.debug(
`Squashed ${updates.length} updates for ${id} in workspace ${workspaceId}`
);
await this.db.update.deleteMany({
// 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,
@@ -498,7 +597,8 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
},
});
await this.updateCachedUpdatesCount(workspaceId, id, -updates.length);
await this.updateCachedUpdatesCount(workspaceId, id, -count);
return doc;
}
@@ -581,22 +681,44 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
return null;
}
private async lockUpdatesForAutoSquash(workspaceId: string, guid: string) {
return this.cache.setnx(
private async doWithLock<T>(lock: string, job: () => Promise<T>) {
const acquired = await this.cache.setnx(lock, 1, {
ttl: 60 * 1000,
});
if (!acquired) {
return;
}
try {
return await job();
} finally {
await this.cache.delete(lock).catch(e => {
// 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-lock:${workspaceId}::${guid}`,
1,
{
ttl: 60 * 1000,
}
job
);
}
private async unlockUpdatesForAutoSquash(workspaceId: string, guid: string) {
return this.cache
.delete(`doc:manager:updates-lock:${workspaceId}::${guid}`)
.catch(e => {
// safe, the lock will be expired when ttl ends
this.logger.error('Failed to release updates lock', e);
});
async lockSnapshotForUpsert<T>(
workspaceId: string,
guid: string,
job: () => Promise<T>
) {
return this.doWithLock(
`doc:manager:snapshot-lock:${workspaceId}::${guid}`,
job
);
}
}

View File

@@ -1,34 +1,40 @@
import { DynamicModule, Type } from '@nestjs/common';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { ScheduleModule } from '@nestjs/schedule';
import { GqlModule } from '../graphql.module';
import { AuthModule } from './auth';
import { SERVER_FLAVOR, ServerConfigModule } from './config';
import { DocModule } from './doc';
import { PaymentModule } from './payment';
import { SelfHostedModule } from './self-hosted';
import { SyncModule } from './sync';
import { UsersModule } from './users';
import { WorkspaceModule } from './workspaces';
const { SERVER_FLAVOR } = process.env;
const BusinessModules: (Type | DynamicModule)[] = [
EventEmitterModule.forRoot({
global: true,
}),
];
const BusinessModules: (Type | DynamicModule)[] = [];
switch (SERVER_FLAVOR) {
case 'sync':
BusinessModules.push(SyncModule, DocModule.forSync());
break;
case 'graphql':
case 'selfhosted':
BusinessModules.push(
ServerConfigModule,
SelfHostedModule,
ScheduleModule.forRoot(),
GqlModule,
WorkspaceModule,
UsersModule,
SyncModule,
DocModule.forRoot()
);
break;
case 'graphql':
BusinessModules.push(
ServerConfigModule,
ScheduleModule.forRoot(),
GqlModule,
WorkspaceModule,
UsersModule,
AuthModule,
DocModule.forRoot(),
PaymentModule
);
@@ -36,11 +42,11 @@ switch (SERVER_FLAVOR) {
case 'allinone':
default:
BusinessModules.push(
ServerConfigModule,
ScheduleModule.forRoot(),
GqlModule,
WorkspaceModule,
UsersModule,
AuthModule,
SyncModule,
DocModule.forRoot(),
PaymentModule
@@ -48,4 +54,4 @@ switch (SERVER_FLAVOR) {
break;
}
export { BusinessModules };
export { BusinessModules, SERVER_FLAVOR };

View File

@@ -52,7 +52,7 @@ class SubscriptionPrice {
}
@ObjectType('UserSubscription')
class UserSubscriptionType implements Partial<UserSubscription> {
export class UserSubscriptionType implements Partial<UserSubscription> {
@Field({ name: 'id' })
stripeSubscriptionId!: string;

View File

@@ -30,6 +30,7 @@ export enum SubscriptionPlan {
Pro = 'pro',
Team = 'team',
Enterprise = 'enterprise',
SelfHosted = 'selfhosted',
}
export function encodeLookupKey(

View File

@@ -0,0 +1,38 @@
import { Module } from '@nestjs/common';
import { ResolveField, Resolver } from '@nestjs/graphql';
import { UserSubscriptionType } from './payment/resolver';
import {
SubscriptionPlan,
SubscriptionRecurring,
SubscriptionStatus,
} from './payment/service';
import { UserType } from './users';
const YEAR = 1000 * 60 * 60 * 24 * 30 * 12;
@Resolver(() => UserType)
export class SelfHostedDummyResolver {
private readonly start = new Date();
private readonly end = new Date(Number(this.start) + YEAR);
constructor() {}
@ResolveField(() => UserSubscriptionType)
async subscription() {
return {
stripeSubscriptionId: 'dummy',
plan: SubscriptionPlan.SelfHosted,
recurring: SubscriptionRecurring.Yearly,
status: SubscriptionStatus.Active,
start: this.start,
end: this.end,
createdAt: this.start,
updatedAt: this.start,
};
}
}
@Module({
providers: [SelfHostedDummyResolver],
})
export class SelfHostedModule {}

View File

@@ -25,7 +25,6 @@ import {
EventError,
InternalError,
NotInWorkspaceError,
WorkspaceNotFoundError,
} from './error';
export const GatewayErrorWrapper = (): MethodDecorator => {
@@ -45,6 +44,7 @@ export const GatewayErrorWrapper = (): MethodDecorator => {
try {
result = originalMethod.apply(this, args);
} catch (e) {
metrics.socketio.counter('unhandled_errors').add(1);
return {
error: new InternalError(e as Error),
};
@@ -52,6 +52,7 @@ export const GatewayErrorWrapper = (): MethodDecorator => {
if (result instanceof Promise) {
return result.catch(e => {
metrics.socketio.counter('unhandled_errors').add(1);
return {
error: new InternalError(e),
};
@@ -68,7 +69,7 @@ export const GatewayErrorWrapper = (): MethodDecorator => {
const SubscribeMessage = (event: string) =>
applyDecorators(
GatewayErrorWrapper(),
CallTimer('socket_io_event_duration', { event }),
CallTimer('socketio', 'event_duration', { event }),
RawSubscribeMessage(event)
);
@@ -104,12 +105,12 @@ export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect {
handleConnection() {
this.connectionCount++;
metrics().socketIOConnectionGauge(this.connectionCount);
metrics.socketio.gauge('realtime_connections').record(this.connectionCount);
}
handleDisconnect() {
this.connectionCount--;
metrics().socketIOConnectionGauge(this.connectionCount);
metrics.socketio.gauge('realtime_connections').record(this.connectionCount);
}
@Auth()
@@ -317,9 +318,7 @@ export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect {
if (!doc) {
return {
error: docId.isWorkspace
? new WorkspaceNotFoundError(workspaceId)
: new DocNotFoundError(workspaceId, docId.guid),
error: new DocNotFoundError(workspaceId, docId.guid),
};
}

View File

@@ -34,7 +34,7 @@ export class WorkspacesController {
//
// NOTE: because graphql can't represent a File, so we have to use REST API to get blob
@Get('/:id/blobs/:name')
@CallTimer('doc_controller', { method: 'get_blob' })
@CallTimer('controllers', 'workspace_get_blob')
async blob(
@Param('id') workspaceId: string,
@Param('name') name: string,
@@ -59,7 +59,7 @@ export class WorkspacesController {
@Get('/:id/docs/:guid')
@Auth()
@Publicable()
@CallTimer('doc_controller', { method: 'get_doc' })
@CallTimer('controllers', 'workspace_get_doc')
async doc(
@CurrentUser() user: UserType | undefined,
@Param('id') ws: string,
@@ -106,7 +106,7 @@ export class WorkspacesController {
@Get('/:id/docs/:guid/histories/:timestamp')
@Auth()
@CallTimer('doc_controller', { method: 'get_history' })
@CallTimer('controllers', 'workspace_get_history')
async history(
@CurrentUser() user: UserType,
@Param('id') ws: string,

View File

@@ -33,6 +33,7 @@ import type {
import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs';
import { applyUpdate, Doc } from 'yjs';
import { EventEmitter } from '../../event';
import { PrismaService } from '../../prisma';
import { StorageProvide } from '../../storage';
import { CloudThrottlerGuard, Throttle } from '../../throttler';
@@ -146,6 +147,7 @@ export class WorkspaceResolver {
private readonly prisma: PrismaService,
private readonly permissions: PermissionService,
private readonly users: UsersService,
private readonly event: EventEmitter,
@Inject(StorageProvide) private readonly storage: Storage
) {}
@@ -308,22 +310,11 @@ export class WorkspaceResolver {
})
async createWorkspace(
@CurrentUser() user: UserType,
@Args({ name: 'init', type: () => GraphQLUpload })
update: FileUpload
// we no longer support init workspace with a preload file
// use sync system to uploading them once created
@Args({ name: 'init', type: () => GraphQLUpload, nullable: true })
init: FileUpload | null
) {
// convert stream to buffer
const buffer = await new Promise<Buffer>((resolve, reject) => {
const stream = update.createReadStream();
const chunks: Uint8Array[] = [];
stream.on('data', chunk => {
chunks.push(chunk);
});
stream.on('error', reject);
stream.on('end', () => {
resolve(Buffer.concat(chunks));
});
});
const workspace = await this.prisma.workspace.create({
data: {
public: false,
@@ -341,14 +332,31 @@ export class WorkspaceResolver {
},
});
if (buffer.length) {
await this.prisma.snapshot.create({
data: {
id: workspace.id,
workspaceId: workspace.id,
blob: buffer,
},
if (init) {
// convert stream to buffer
const buffer = await new Promise<Buffer>(resolve => {
const stream = init.createReadStream();
const chunks: Uint8Array[] = [];
stream.on('data', chunk => {
chunks.push(chunk);
});
stream.on('error', () => {
resolve(Buffer.from([]));
});
stream.on('end', () => {
resolve(Buffer.concat(chunks));
});
});
if (buffer.length) {
await this.prisma.snapshot.create({
data: {
id: workspace.id,
workspaceId: workspace.id,
blob: buffer,
},
});
}
}
return workspace;
@@ -382,18 +390,7 @@ export class WorkspaceResolver {
},
});
await this.prisma.$transaction([
this.prisma.update.deleteMany({
where: {
workspaceId: id,
},
}),
this.prisma.snapshot.deleteMany({
where: {
workspaceId: id,
},
}),
]);
this.event.emit('workspace.deleted', id);
return true;
}

View File

@@ -7,6 +7,13 @@ export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
static INSTANCE: PrismaService | null = null;
constructor() {
super();
PrismaService.INSTANCE = this;
}
async onModuleInit() {
await this.$connect();
}

View File

@@ -2,6 +2,14 @@
# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
# ------------------------------------------------------
type ServerConfigType {
"""server version"""
version: String!
"""server flavor"""
flavor: String!
}
type UserType {
id: ID!
@@ -73,6 +81,7 @@ enum SubscriptionPlan {
Pro
Team
Enterprise
SelfHosted
}
type UserSubscription {
@@ -240,6 +249,9 @@ type DocHistoryType {
}
type Query {
"""server config"""
serverConfig: ServerConfigType!
"""Get is owner of workspace"""
isOwner(workspaceId: String!): Boolean!
@@ -280,7 +292,7 @@ type Mutation {
sendVerifyChangeEmail(token: String!, email: String!, callbackUrl: String!): Boolean!
"""Create a new workspace"""
createWorkspace(init: Upload!): WorkspaceType!
createWorkspace(init: Upload): WorkspaceType!
"""Update workspace"""
updateWorkspace(input: UpdateWorkspaceInput!): WorkspaceType!

View File

@@ -16,7 +16,7 @@ export class DocID {
raw: string;
workspace: string;
variant: DocVariant;
private sub: string | null;
private readonly sub: string | null;
static parse(raw: string): DocID | null {
try {

View File

@@ -1,15 +1,20 @@
import { mock } from 'node:test';
import type { INestApplication } from '@nestjs/common';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { Test, TestingModule } from '@nestjs/testing';
import test from 'ava';
import { register } from 'prom-client';
import * as Sinon from 'sinon';
import { Doc as YDoc, encodeStateAsUpdate } from 'yjs';
import {
applyUpdate,
decodeStateVector,
Doc as YDoc,
encodeStateAsUpdate,
} from 'yjs';
import { CacheModule } from '../src/cache';
import { Config, ConfigModule } from '../src/config';
import { EventModule } from '../src/event';
import { DocManager, DocModule } from '../src/modules/doc';
import { PrismaModule, PrismaService } from '../src/prisma';
import { flushDB } from './utils';
@@ -19,7 +24,7 @@ const createModule = () => {
imports: [
PrismaModule,
CacheModule,
EventEmitterModule.forRoot(),
EventModule,
ConfigModule.forRoot(),
DocModule.forRoot(),
],
@@ -283,3 +288,73 @@ test('should throw if meet max retry times', async t => {
);
t.is(stub.callCount, 5);
});
test('should not update snapshot if state is outdated', async t => {
const db = m.get(PrismaService);
const manager = m.get(DocManager);
await db.snapshot.create({
data: {
id: '2',
workspaceId: '2',
blob: Buffer.from([0, 0]),
seq: 1,
},
});
const doc = new YDoc();
const text = doc.getText('content');
const updates: Buffer[] = [];
doc.on('update', update => {
updates.push(Buffer.from(update));
});
text.insert(0, 'hello');
text.insert(5, 'world');
text.insert(5, ' ');
await Promise.all(updates.map(update => manager.push('2', '2', update)));
const updateWith3Records = await manager.getUpdates('2', '2');
text.insert(11, '!');
await manager.push('2', '2', updates[3]);
const updateWith4Records = await manager.getUpdates('2', '2');
// Simulation:
// Node A get 3 updates and squash them at time 1, will finish at time 10
// Node B get 4 updates and squash them at time 3, will finish at time 8
// Node B finish the squash first, and update the snapshot
// Node A finish the squash later, and update the snapshot to an outdated state
// Time: ---------------------->
// A: ^get ^upsert
// B: ^get ^upsert
//
// We should avoid such situation
// @ts-expect-error private
await manager.squash(updateWith4Records, null);
// @ts-expect-error private
await manager.squash(updateWith3Records, null);
const result = await db.snapshot.findUnique({
where: {
id_workspaceId: {
id: '2',
workspaceId: '2',
},
},
});
if (!result) {
t.fail('snapshot not found');
return;
}
const state = decodeStateVector(result.state!);
t.is(state.get(doc.clientID), 12);
const d = new YDoc();
applyUpdate(d, result.blob!);
const dtext = d.getText('content');
t.is(dtext.toString(), 'hello world!');
});

View File

@@ -17,7 +17,7 @@ class FakePrisma {
get workspace() {
return {
async findUnique() {
throw Error('exception from graphql');
throw new Error('exception from graphql');
},
};
}

View File

@@ -6,6 +6,7 @@ import test from 'ava';
import * as Sinon from 'sinon';
import { ConfigModule } from '../src/config';
import type { EventPayload } from '../src/event';
import { DocHistoryManager } from '../src/modules/doc';
import { PrismaModule, PrismaService } from '../src/prisma';
import { flushDB } from './utils';
@@ -41,21 +42,28 @@ test.afterEach(async () => {
const snapshot: Snapshot = {
workspaceId: '1',
id: 'doc1',
blob: Buffer.from([0, 0]),
state: Buffer.from([0, 0]),
blob: Buffer.from([1, 0]),
state: Buffer.from([0]),
seq: 0,
updatedAt: new Date(),
createdAt: new Date(),
};
function getEventData(
timestamp: Date = new Date()
): EventPayload<'snapshot.updated'> {
return {
workspaceId: snapshot.workspaceId,
id: snapshot.id,
previous: { ...snapshot, updatedAt: timestamp },
};
}
test('should create doc history if never created before', async t => {
Sinon.stub(manager, 'last').resolves(null);
const timestamp = new Date();
await manager.onDocUpdated({
...snapshot,
updatedAt: timestamp,
});
await manager.onDocUpdated(getEventData(timestamp));
const history = await db.snapshotHistory.findFirst({
where: {
@@ -72,10 +80,7 @@ test('should not create history if timestamp equals to last record', async t =>
const timestamp = new Date();
Sinon.stub(manager, 'last').resolves({ timestamp, state: null });
await manager.onDocUpdated({
...snapshot,
updatedAt: timestamp,
});
await manager.onDocUpdated(getEventData(timestamp));
const history = await db.snapshotHistory.findFirst({
where: {
@@ -94,10 +99,7 @@ test('should not create history if state equals to last record', async t => {
state: snapshot.state,
});
await manager.onDocUpdated({
...snapshot,
updatedAt: timestamp,
});
await manager.onDocUpdated(getEventData(timestamp));
const history = await db.snapshotHistory.findFirst({
where: {
@@ -116,10 +118,7 @@ test('should not create history if time diff is less than interval config', asyn
state: Buffer.from([0, 1]),
});
await manager.onDocUpdated({
...snapshot,
updatedAt: timestamp,
});
await manager.onDocUpdated(getEventData(timestamp));
const history = await db.snapshotHistory.findFirst({
where: {
@@ -138,10 +137,7 @@ test('should create history if time diff is larger than interval config and stat
state: Buffer.from([0, 1]),
});
await manager.onDocUpdated({
...snapshot,
updatedAt: timestamp,
});
await manager.onDocUpdated(getEventData(timestamp));
const history = await db.snapshotHistory.findFirst({
where: {
@@ -160,13 +156,7 @@ test('should create history with force flag even if time diff in small', async t
state: Buffer.from([0, 1]),
});
await manager.onDocUpdated(
{
...snapshot,
updatedAt: timestamp,
},
true
);
await manager.onDocUpdated(getEventData(timestamp), true);
const history = await db.snapshotHistory.findFirst({
where: {
@@ -183,26 +173,30 @@ test('should correctly list all history records', async t => {
// insert expired data
await db.snapshotHistory.createMany({
data: new Array(10).fill(0).map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp - 10 - i),
expiredAt: new Date(timestamp - 1),
})),
data: Array.from({ length: 10 })
.fill(0)
.map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp - 10 - i),
expiredAt: new Date(timestamp - 1),
})),
});
// insert available data
await db.snapshotHistory.createMany({
data: new Array(10).fill(0).map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp + i),
expiredAt: new Date(timestamp + 1000),
})),
data: Array.from({ length: 10 })
.fill(0)
.map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp + i),
expiredAt: new Date(timestamp + 1000),
})),
});
const list = await manager.list(
@@ -220,13 +214,7 @@ test('should correctly list all history records', async t => {
test('should be able to get history data', async t => {
const timestamp = new Date();
await manager.onDocUpdated(
{
...snapshot,
updatedAt: timestamp,
},
true
);
await manager.onDocUpdated(getEventData(timestamp), true);
const history = await manager.get(
snapshot.workspaceId,
@@ -243,14 +231,16 @@ test('should be able to get last history record', async t => {
// insert available data
await db.snapshotHistory.createMany({
data: new Array(10).fill(0).map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp + i),
expiredAt: new Date(timestamp + 1000),
})),
data: Array.from({ length: 10 })
.fill(0)
.map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp + i),
expiredAt: new Date(timestamp + 1000),
})),
});
const history = await manager.last(snapshot.workspaceId, snapshot.id);
@@ -268,10 +258,7 @@ test('should be able to recover from history', async t => {
},
});
const history1Timestamp = snapshot.updatedAt.getTime() - 10;
await manager.onDocUpdated({
...snapshot,
updatedAt: new Date(history1Timestamp),
});
await manager.onDocUpdated(getEventData(new Date(history1Timestamp)));
await manager.recover(
snapshot.workspaceId,
@@ -299,26 +286,30 @@ test('should be able to cleanup expired history', async t => {
// insert expired data
await db.snapshotHistory.createMany({
data: new Array(10).fill(0).map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp - 10 - i),
expiredAt: new Date(timestamp - 1),
})),
data: Array.from({ length: 10 })
.fill(0)
.map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp - 10 - i),
expiredAt: new Date(timestamp - 1),
})),
});
// insert available data
await db.snapshotHistory.createMany({
data: new Array(10).fill(0).map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp + i),
expiredAt: new Date(timestamp + 1000),
})),
data: Array.from({ length: 10 })
.fill(0)
.map((_, i) => ({
workspaceId: snapshot.workspaceId,
id: snapshot.id,
blob: snapshot.blob,
state: snapshot.state,
timestamp: new Date(timestamp + i),
expiredAt: new Date(timestamp + 1000),
})),
});
let count = await db.snapshotHistory.count();

View File

@@ -65,9 +65,7 @@ test.afterEach.always(async t => {
test('should get blob size limit', async t => {
const { resolver } = t.context;
fakeUserService.getStorageQuotaById.returns(
Promise.resolve(100 * 1024 * 1024 * 1024)
);
fakeUserService.getStorageQuotaById.resolves(100 * 1024 * 1024 * 1024);
const res = await resolver.checkBlobSize(new FakePrisma().fakeUser, '', 100);
t.not(res, false);
// @ts-expect-error

View File

@@ -8,9 +8,9 @@ crate-type = ["cdylib"]
[dependencies]
chrono = "0.4"
jwst-codec = { git = "https://github.com/toeverything/OctoBase.git", rev = "aad9e5b" }
jwst-core = { git = "https://github.com/toeverything/OctoBase.git", rev = "aad9e5b" }
jwst-storage = { git = "https://github.com/toeverything/OctoBase.git", rev = "aad9e5b" }
jwst-codec = { git = "https://github.com/toeverything/OctoBase.git", rev = "49a6b7a" }
jwst-core = { git = "https://github.com/toeverything/OctoBase.git", rev = "49a6b7a" }
jwst-storage = { git = "https://github.com/toeverything/OctoBase.git", rev = "49a6b7a" }
napi = { version = "2", default-features = false, features = [
"napi5",
"async",

View File

@@ -1,21 +1,6 @@
/* tslint:disable */
/* auto-generated by NAPI-RS */
/* eslint-disable */
/* auto-generated by NAPI-RS */
export function verifyChallengeResponse(response: string, bits: number, resource: string): Promise<boolean>
export function mintChallengeResponse(resource: string, bits?: number | undefined | null): Promise<string>
export interface Blob {
contentType: string
lastModified: string
size: number
data: Buffer
}
/**
* Merge updates in form like `Y.applyUpdate(doc, update)` way and return the
* result binary.
*/
export function mergeUpdatesInApplyWay(updates: Array<Buffer>): Buffer
export class Storage {
/** Create a storage instance and establish connection to persist store. */
static connect(database: string, debugOnlyAutoMigrate?: boolean | undefined | null): Promise<Storage>
@@ -30,3 +15,21 @@ export class Storage {
/** Workspace size taken by blobs. */
blobsSize(workspaces: Array<string>): Promise<number>
}
export interface Blob {
contentType: string
lastModified: string
size: number
data: Buffer
}
/**
* Merge updates in form like `Y.applyUpdate(doc, update)` way and return the
* result binary.
*/
export function mergeUpdatesInApplyWay(updates: Array<Buffer>): Buffer
export function mintChallengeResponse(resource: string, bits?: number | undefined | null): Promise<string>
export function verifyChallengeResponse(response: string, bits: number, resource: string): Promise<boolean>

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/storage",
"version": "0.10.3",
"version": "0.10.4-beta.2",
"engines": {
"node": ">= 10.16.0 < 11 || >= 11.8.0"
},
@@ -16,27 +16,26 @@
}
},
"napi": {
"name": "storage",
"binaryName": "storage",
"targets": [
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"aarch64-pc-windows-msvc",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
"universal-apple-darwin"
"x86_64-unknown-linux-gnu"
]
},
"scripts": {
"test": "node --test ./__tests__/**/*.spec.js",
"build": "napi build --release --strip",
"build": "napi build --release --strip --no-const-enum",
"build:debug": "napi build",
"prepublishOnly": "napi prepublish -t npm",
"artifacts": "napi artifacts",
"version": "napi version"
},
"devDependencies": {
"@napi-rs/cli": "^2.16.5",
"@napi-rs/cli": "3.0.0-alpha.15",
"lib0": "^0.2.87",
"nx": "^17.1.3",
"nx-cloud": "^16.5.2",

View File

@@ -8,5 +8,5 @@
"react": "18.2.0",
"react-dom": "18.2.0"
},
"version": "0.10.3"
"version": "0.10.4-beta.2"
}

View File

@@ -9,5 +9,5 @@
"@types/debug": "^4.1.9",
"vitest": "0.34.6"
},
"version": "0.10.3"
"version": "0.10.4-beta.2"
}

View File

@@ -24,7 +24,7 @@ if (typeof window !== 'undefined') {
}
export class DebugLogger {
private _debug: debug.Debugger;
private readonly _debug: debug.Debugger;
constructor(namespace: string) {
this._debug = debug(namespace);

View File

@@ -3,8 +3,8 @@
"private": true,
"type": "module",
"devDependencies": {
"@blocksuite/global": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/store": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/global": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/store": "0.11.0-nightly-202312070955-2b5bb47",
"react": "18.2.0",
"react-dom": "18.2.0",
"vitest": "0.34.6",
@@ -21,11 +21,10 @@
},
"peerDependencies": {
"@affine/templates": "workspace:*",
"@blocksuite/global": "0.0.0-20230409084303-221991d4-nightly",
"@toeverything/infra": "workspace:*"
"@blocksuite/global": "0.0.0-20230409084303-221991d4-nightly"
},
"dependencies": {
"lit": "^3.0.2"
},
"version": "0.10.3"
"version": "0.10.4-beta.2"
}

View File

@@ -6,12 +6,9 @@ import { isDesktop, isServer } from './constant.js';
import { UaHelper } from './ua-helper.js';
export const blockSuiteFeatureFlags = z.object({
enable_set_remote_flag: z.boolean(),
enable_block_hub: z.boolean(),
enable_toggle_block: z.boolean(),
enable_bookmark_operation: z.boolean(),
enable_note_index: z.boolean(),
enable_transformer_clipboard: z.boolean(),
enable_expand_database_block: z.boolean(),
enable_bultin_ledits: z.boolean(),
});
export const runtimeFlagsSchema = z.object({
@@ -21,6 +18,7 @@ export const runtimeFlagsSchema = z.object({
enableBroadcastChannelProvider: z.boolean(),
enableDebugPage: z.boolean(),
changelogUrl: z.string(),
downloadUrl: z.string(),
// see: tools/workers
imageProxyUrl: z.string(),
enablePreloading: z.boolean(),
@@ -32,12 +30,19 @@ export const runtimeFlagsSchema = z.object({
enableCaptcha: z.boolean(),
enableEnhanceShareMode: z.boolean(),
enablePayment: z.boolean(),
enablePageHistory: z.boolean(),
// this is for the electron app
serverUrlPrefix: z.string(),
enableMoveDatabase: z.boolean(),
editorFlags: blockSuiteFeatureFlags,
appVersion: z.string(),
editorVersion: z.string(),
appBuildType: z.union([
z.literal('stable'),
z.literal('beta'),
z.literal('internal'),
z.literal('canary'),
]),
});
export type BlockSuiteFeatureFlags = z.infer<typeof blockSuiteFeatureFlags>;

View File

@@ -1,7 +1,7 @@
import { assertExists } from '@blocksuite/global/utils';
export class UaHelper {
private uaMap;
private readonly uaMap;
public isLinux = false;
public isMacOs = false;
public isSafari = false;

View File

@@ -1,5 +1,3 @@
import type { EditorContainer } from '@blocksuite/editor';
import type { Page } from '@blocksuite/store';
import type {
ActiveDocProvider,
PassiveDocProvider,
@@ -111,7 +109,7 @@ export const settingPanel = {
Export: 'export',
Sync: 'sync',
} as const;
export const settingPanelValues = [...Object.values(settingPanel)] as const;
export const settingPanelValues = Object.values(settingPanel);
export type SettingPanel = (typeof settingPanel)[keyof typeof settingPanel];
// built-in workspaces
@@ -134,18 +132,6 @@ type UIBaseProps<_Flavour extends keyof WorkspaceRegistry> = {
currentWorkspaceId: string;
};
export type WorkspaceHeaderProps<Flavour extends keyof WorkspaceRegistry> =
UIBaseProps<Flavour> & {
rightSlot?: ReactNode;
currentEntry:
| {
subPath: WorkspaceSubPath;
}
| {
pageId: string;
};
};
type NewSettingProps<Flavour extends keyof WorkspaceRegistry> =
UIBaseProps<Flavour> & {
onDeleteLocalWorkspace: () => void;
@@ -161,18 +147,11 @@ type NewSettingProps<Flavour extends keyof WorkspaceRegistry> =
) => void;
};
type PageDetailProps<Flavour extends keyof WorkspaceRegistry> =
UIBaseProps<Flavour> & {
currentPageId: string;
onLoadEditor: (page: Page, editor: EditorContainer) => () => void;
};
interface FC<P> {
(props: P): ReactNode;
}
export interface WorkspaceUISchema<Flavour extends keyof WorkspaceRegistry> {
PageDetail: FC<PageDetailProps<Flavour>>;
NewSettingsDetail: FC<NewSettingProps<Flavour>>;
Provider: FC<PropsWithChildren>;
LoginCard?: FC<object>;

View File

@@ -7,9 +7,6 @@
"outDir": "lib"
},
"references": [
{
"path": "../infra"
},
{
"path": "../../../tests/fixtures"
}

View File

@@ -54,10 +54,12 @@
"dev": "vite build --watch"
},
"dependencies": {
"@affine/debug": "workspace:*",
"@affine/env": "workspace:*",
"@affine/sdk": "workspace:*",
"@blocksuite/blocks": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/global": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/store": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/blocks": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/global": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/store": "0.11.0-nightly-202312070955-2b5bb47",
"jotai": "^2.5.1",
"jotai-effect": "^0.2.3",
"tinykeys": "^2.1.0",
@@ -66,22 +68,22 @@
"devDependencies": {
"@affine-test/fixtures": "workspace:*",
"@affine/templates": "workspace:*",
"@blocksuite/editor": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/lit": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/lit": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/presets": "0.11.0-nightly-202312070955-2b5bb47",
"@testing-library/react": "^14.0.0",
"async-call-rpc": "^6.3.1",
"electron": "link:../../frontend/electron/node_modules/electron",
"nanoid": "^5.0.3",
"react": "^18.2.0",
"rxjs": "^7.8.1",
"vite": "^4.4.11",
"vite": "^5.0.6",
"vite-plugin-dts": "3.6.0",
"vitest": "0.34.6",
"yjs": "^13.6.10"
},
"peerDependencies": {
"@affine/templates": "*",
"@blocksuite/editor": "*",
"@blocksuite/presets": "*",
"async-call-rpc": "*",
"electron": "*",
"react": "*",
@@ -91,7 +93,7 @@
"@affine/templates": {
"optional": true
},
"@blocksuite/editor": {
"@blocksuite/presets": {
"optional": true
},
"async-call-rpc": {
@@ -107,5 +109,5 @@
"optional": true
}
},
"version": "0.10.3"
"version": "0.10.4-beta.2"
}

View File

@@ -0,0 +1,8 @@
import { atom } from 'jotai';
export const loadedPluginNameAtom = atom<string[]>([]);
export * from './layout';
export * from './root-store';
export * from './settings';
export * from './workspace';

View File

@@ -1,34 +1,5 @@
import type { ExpectedLayout } from '@affine/sdk/entry';
import { assertExists } from '@blocksuite/global/utils';
import type { Workspace } from '@blocksuite/store';
import { atom, createStore } from 'jotai/vanilla';
import { getBlockSuiteWorkspaceAtom } from './__internal__/workspace';
// global store
let rootStore = createStore();
export function getCurrentStore() {
return rootStore;
}
/**
* @internal do not use this function unless you know what you are doing
*/
export function _setCurrentStore(store: ReturnType<typeof createStore>) {
rootStore = store;
}
export const loadedPluginNameAtom = atom<string[]>([]);
export const currentWorkspaceIdAtom = atom<string | null>(null);
export const currentPageIdAtom = atom<string | null>(null);
export const currentWorkspaceAtom = atom<Promise<Workspace>>(async get => {
const workspaceId = get(currentWorkspaceIdAtom);
assertExists(workspaceId);
const [currentWorkspaceAtom] = getBlockSuiteWorkspaceAtom(workspaceId);
return get(currentWorkspaceAtom);
});
import { atom } from 'jotai';
const contentLayoutBaseAtom = atom<ExpectedLayout>('editor');

View File

@@ -0,0 +1,15 @@
import { createStore } from 'jotai';
// global store
let rootStore = createStore();
export function getCurrentStore() {
return rootStore;
}
/**
* @internal do not use this function unless you know what you are doing
*/
export function _setCurrentStore(store: ReturnType<typeof createStore>) {
rootStore = store;
}

View File

@@ -1,5 +1,9 @@
import { setupGlobal } from '@affine/env/global';
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
import { atomEffect } from 'jotai-effect';
setupGlobal();
export type DateFormats =
| 'MM/dd/YYYY'
@@ -63,15 +67,35 @@ const appSettingBaseAtom = atomWithStorage<AppSetting>('affine-settings', {
type SetStateAction<Value> = Value | ((prev: Value) => Value);
const appSettingEffect = atomEffect(get => {
const settings = get(appSettingBaseAtom);
// some values in settings should be synced into electron side
if (environment.isDesktop) {
console.log('set config', settings);
window.apis?.updater
.setConfig({
autoCheckUpdate: settings.autoCheckUpdate,
autoDownloadUpdate: settings.autoDownloadUpdate,
})
.catch(err => {
console.error(err);
});
}
});
export const appSettingAtom = atom<
AppSetting,
[SetStateAction<Partial<AppSetting>>],
void
>(
get => get(appSettingBaseAtom),
(get, set, apply) => {
const prev = get(appSettingBaseAtom);
const next = typeof apply === 'function' ? apply(prev) : apply;
set(appSettingBaseAtom, { ...prev, ...next });
get => {
get(appSettingEffect);
return get(appSettingBaseAtom);
},
(_get, set, apply) => {
set(appSettingBaseAtom, prev => {
const next = typeof apply === 'function' ? apply(prev) : apply;
return { ...prev, ...next };
});
}
);

View File

@@ -0,0 +1,14 @@
import { assertExists } from '@blocksuite/global/utils';
import type { Workspace } from '@blocksuite/store';
import { atom } from 'jotai';
import { getBlockSuiteWorkspaceAtom } from '../__internal__/workspace';
export const currentWorkspaceIdAtom = atom<string | null>(null);
export const currentPageIdAtom = atom<string | null>(null);
export const currentWorkspaceAtom = atom<Promise<Workspace>>(async get => {
const workspaceId = get(currentWorkspaceIdAtom);
assertExists(workspaceId);
const [currentWorkspaceAtom] = getBlockSuiteWorkspaceAtom(workspaceId);
return get(currentWorkspaceAtom);
});

View File

@@ -3,8 +3,11 @@ import type { Page, PageMeta, Workspace } from '@blocksuite/store';
import type { createStore, WritableAtom } from 'jotai/vanilla';
import { nanoid } from 'nanoid';
import { checkWorkspaceCompatibility, MigrationPoint } from '..';
import { migratePages } from '../migration/blocksuite';
import {
checkWorkspaceCompatibility,
MigrationPoint,
} from '../migration/workspace';
export async function initEmptyPage(page: Page, title?: string) {
await page.load(() => {

View File

@@ -50,7 +50,7 @@ function migrateDatabase(data: YMap<unknown>) {
update: (cell: { id: string; value: unknown }) => void
) => {
Object.values(cells).forEach(row => {
if (row[id] != null) {
if (row[id] !== null && row[id] !== undefined) {
update(row[id]);
}
});

View File

@@ -1,3 +1,4 @@
import { DebugLogger } from '@affine/debug';
// @ts-expect-error upstream type is wrong
import { tinykeys } from 'tinykeys';
@@ -7,12 +8,14 @@ import {
createAffineCommand,
} from './command';
const commandLogger = new DebugLogger('command:registry');
export const AffineCommandRegistry = new (class {
readonly commands: Map<string, AffineCommand> = new Map();
register(options: AffineCommandOptions) {
if (this.commands.has(options.id)) {
console.warn(`Command ${options.id} already registered.`);
commandLogger.warn(`Command ${options.id} already registered.`);
return () => {};
}
const command = createAffineCommand(options);
@@ -38,17 +41,17 @@ export const AffineCommandRegistry = new (class {
});
}
console.debug(`Registered command ${command.id}`);
commandLogger.debug(`Registered command ${command.id}`);
return () => {
unsubKb?.();
this.commands.delete(command.id);
console.debug(`Unregistered command ${command.id}`);
commandLogger.debug(`Unregistered command ${command.id}`);
};
}
get(id: string): AffineCommand | undefined {
if (!this.commands.has(id)) {
console.warn(`Command ${id} not registered.`);
commandLogger.warn(`Command ${id} not registered.`);
return undefined;
}
return this.commands.get(id);

View File

@@ -45,8 +45,8 @@ export abstract class HandlerManager<
Handlers extends Record<string, PrimitiveHandlers>,
> {
static instance: HandlerManager<string, Record<string, PrimitiveHandlers>>;
private _app: App<Namespace, Handlers>;
private _namespace: Namespace;
private readonly _app: App<Namespace, Handlers>;
private readonly _namespace: Namespace;
private _handlers: Handlers;
constructor() {
@@ -190,10 +190,18 @@ export interface UpdateMeta {
allowAutoUpdate: boolean;
}
export type UpdaterConfig = {
autoCheckUpdate: boolean;
autoDownloadUpdate: boolean;
};
export type UpdaterHandlers = {
currentVersion: () => Promise<string>;
quitAndInstall: () => Promise<void>;
checkForUpdatesAndNotify: () => Promise<{ version: string } | null>;
downloadUpdate: () => Promise<void>;
getConfig: () => Promise<UpdaterConfig>;
setConfig: (newConfig: Partial<UpdaterConfig>) => Promise<void>;
checkForUpdates: () => Promise<{ version: string } | null>;
};
export type WorkspaceHandlers = {

View File

@@ -11,6 +11,12 @@
{
"path": "../sdk"
},
{
"path": "../env"
},
{
"path": "../debug"
},
{
"path": "./tsconfig.node.json"
}

View File

@@ -13,7 +13,7 @@ export default defineConfig({
entry: {
blocksuite: resolve(root, 'src/blocksuite/index.ts'),
index: resolve(root, 'src/index.ts'),
atom: resolve(root, 'src/atom.ts'),
atom: resolve(root, 'src/atom/index.ts'),
command: resolve(root, 'src/command/index.ts'),
type: resolve(root, 'src/type.ts'),
'core/event-emitter': resolve(root, 'src/core/event-emitter.ts'),

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/sdk",
"version": "0.10.3",
"version": "0.10.4-beta.2",
"type": "module",
"scripts": {
"build": "vite build",
@@ -22,16 +22,16 @@
"dist"
],
"dependencies": {
"@blocksuite/block-std": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/blocks": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/editor": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/global": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/store": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/block-std": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/blocks": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/global": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/presets": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/store": "0.11.0-nightly-202312070955-2b5bb47",
"jotai": "^2.5.1",
"zod": "^3.22.4"
},
"devDependencies": {
"vite": "^4.4.11",
"vite": "^5.0.6",
"vite-plugin-dts": "3.6.0"
}
}

View File

@@ -1,5 +1,5 @@
import type { BaseSelection } from '@blocksuite/block-std';
import type { EditorContainer } from '@blocksuite/editor';
import type { EditorContainer } from '@blocksuite/presets';
import type { Page } from '@blocksuite/store';
import type { Workspace } from '@blocksuite/store';
import type { Atom, getDefaultStore } from 'jotai/vanilla';

View File

@@ -1,7 +1,7 @@
{
"name": "@toeverything/y-indexeddb",
"type": "module",
"version": "0.10.3",
"version": "0.10.4-beta.2",
"description": "IndexedDB database adapter for Yjs",
"repository": "toeverything/AFFiNE",
"author": "toeverything",
@@ -32,15 +32,15 @@
}
},
"dependencies": {
"idb": "^7.1.1",
"idb": "^8.0.0",
"nanoid": "^5.0.3",
"y-provider": "workspace:*"
},
"devDependencies": {
"@blocksuite/blocks": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/store": "0.0.0-20231122113751-6bf81eb3-nightly",
"@blocksuite/blocks": "0.11.0-nightly-202312070955-2b5bb47",
"@blocksuite/store": "0.11.0-nightly-202312070955-2b5bb47",
"fake-indexeddb": "^5.0.0",
"vite": "^4.4.11",
"vite": "^5.0.6",
"vite-plugin-dts": "3.6.0",
"vitest": "0.34.6",
"y-indexeddb": "^9.0.11",

View File

@@ -65,7 +65,7 @@ beforeEach(() => {
id = nanoid();
workspace = new Workspace({
id,
isSSR: true,
schema,
});
vi.useFakeTimers({ toFake: ['requestIdleCallback'] });
@@ -383,7 +383,7 @@ describe('subDoc', () => {
{
const newWorkspace = new Workspace({
id,
isSSR: true,
schema,
});
const provider = createIndexedDBProvider(newWorkspace.doc, rootDBName);
@@ -423,7 +423,7 @@ describe('utils', () => {
expect(update).toBeInstanceOf(Uint8Array);
const newWorkspace = new Workspace({
id,
isSSR: true,
schema,
});
applyUpdate(newWorkspace.doc, update);

View File

@@ -1,7 +1,7 @@
{
"name": "y-provider",
"type": "module",
"version": "0.10.3",
"version": "0.10.4-beta.2",
"description": "Yjs provider protocol for multi document support",
"exports": {
".": "./src/index.ts"
@@ -24,8 +24,8 @@
"build": "vite build"
},
"devDependencies": {
"@blocksuite/store": "0.0.0-20231122113751-6bf81eb3-nightly",
"vite": "^4.4.11",
"@blocksuite/store": "0.11.0-nightly-202312070955-2b5bb47",
"vite": "^5.0.6",
"vite-plugin-dts": "3.6.0",
"vitest": "0.34.6",
"yjs": "^13.6.10"

View File

@@ -0,0 +1,54 @@
import { StorybookConfig } from '@storybook/react-vite';
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
import { fileURLToPath } from 'url';
import { mergeConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import { getRuntimeConfig } from '../../core/.webpack/runtime-config';
export default {
stories: ['../src/ui/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-mdx-gfm',
'storybook-dark-mode',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
features: {
storyStoreV7: true,
},
docs: {
autodocs: true,
},
async viteFinal(config, _options) {
return mergeConfig(config, {
plugins: [
vanillaExtractPlugin(),
tsconfigPaths({
root: fileURLToPath(new URL('../../../../', import.meta.url)),
ignoreConfigErrors: true,
}),
],
define: {
'process.on': '(() => void 0)',
'process.env': {},
'process.env.COVERAGE': JSON.stringify(!!process.env.COVERAGE),
'process.env.SHOULD_REPORT_TRACE': `${Boolean(
process.env.SHOULD_REPORT_TRACE === 'true'
)}`,
'process.env.TRACE_REPORT_ENDPOINT': `"${process.env.TRACE_REPORT_ENDPOINT}"`,
'process.env.CAPTCHA_SITE_KEY': `"${process.env.CAPTCHA_SITE_KEY}"`,
runtimeConfig: getRuntimeConfig({
distribution: 'browser',
mode: 'development',
channel: 'canary',
coverage: false,
}),
},
});
},
} satisfies StorybookConfig;

View File

@@ -0,0 +1,27 @@
import { darkCssVariables, lightCssVariables } from '@toeverything/theme';
import { globalStyle } from '@vanilla-extract/css';
globalStyle('*', {
margin: 0,
padding: 0,
});
globalStyle('body', {
color: 'var(--affine-text-primary-color)',
fontFamily: 'var(--affine-font-family)',
fontSize: 'var(--affine-font-base)',
lineHeight: 'var(--affine-font-height)',
backgroundColor: 'var(--affine-background-primary-color)',
});
globalStyle('html', {
vars: lightCssVariables,
});
globalStyle('html[data-theme="dark"]', {
vars: darkCssVariables,
});
globalStyle('.docs-story', {
backgroundColor: 'var(--affine-background-primary-color)',
});

Some files were not shown because too many files have changed in this diff Show More