docs: update outdated docs (#6756)

fix #5171
This commit is contained in:
pengx17 2024-05-06 02:03:14 +00:00
parent cebb841430
commit 625249ca5b
No known key found for this signature in database
GPG Key ID: 23F23D9E8B3971ED
8 changed files with 95 additions and 376 deletions

View File

@ -546,7 +546,6 @@ jobs:
run: yarn workspace @affine/electron make --platform=linux --arch=x64
if: ${{ matrix.spec.target == 'x86_64-unknown-linux-gnu' }}
env:
SKIP_PLUGIN_BUILD: 1
SKIP_WEB_BUILD: 1
HOIST_NODE_MODULES: 1

View File

@ -57,7 +57,6 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }}
SKIP_PLUGIN_BUILD: 'true'
SKIP_NX_CACHE: 'true'
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
@ -138,7 +137,6 @@ jobs:
- name: make
run: yarn workspace @affine/electron make --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
env:
SKIP_PLUGIN_BUILD: 1
SKIP_WEB_BUILD: 1
HOIST_NODE_MODULES: 1
@ -214,7 +212,6 @@ jobs:
- name: package
run: yarn workspace @affine/electron package --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
env:
SKIP_PLUGIN_BUILD: 1
SKIP_WEB_BUILD: 1
HOIST_NODE_MODULES: 1

View File

@ -2,7 +2,7 @@
> **Warning**:
>
> This document has not been updated for a while.
> This document is not guaranteed to be up-to-date.
> If you find any outdated information, please feel free to open an issue or submit a PR.
> **Note**
@ -27,7 +27,7 @@ We suggest develop our product under node.js LTS(Long-term support) version
install [Node LTS version](https://nodejs.org/en/download)
> Up to now, the major node.js version is 18.x
> Up to now, the major node.js version is 20.x
#### Option 2: Use node version manager
@ -76,7 +76,7 @@ Once Developer Mode is enabled, execute the following command with administrator
```sh
# Enable symbolic links
git config --global core.symlinks true
# Clone the repository, also need to be run with administrator privileges
# Clone the repository
git clone https://github.com/toeverything/AFFiNE
```

View File

@ -1,93 +1 @@
# Welcome to our contributing guide <!-- omit in toc -->
Thank you for investing your time in contributing to our project! Any contribution you make will be reflected on our GitHub :sparkles:.
Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable. Join our [Discord](https://discord.com/invite/yz6tGVsf5p) server for more.
In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.
Use the table of contents icon on the top left corner of this document to get to a specific section of this guide quickly.
## New contributor guide
Currently we have two versions of AFFiNE:
- [AFFiNE Pre-Alpha](https://livedemo.affine.pro/). This version uses the branch `Pre-Alpha`, it is no longer actively developed but contains some different functions and features.
- [AFFiNE Alpha](https://pathfinder.affine.pro/). This version uses the `canary` branch, this is the latest version under active development.
To get an overview of the project, read the [README](../README.md). Here are some resources to help you get started with open source contributions:
- [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github)
- [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git)
- [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow)
- [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests)
## Getting started
Check to see what [types of contributions](types-of-contributions.md) we accept before making changes. Some of them don't even require writing a single line of code :sparkles:.
### Issues
#### Create a new issue or feature request
If you spot a problem, [search if an issue already exists](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-issues-and-pull-requests#search-by-the-title-body-or-comments). If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/toeverything/AFFiNE/issues/new/choose).
#### Solve an issue
Scan through our [existing issues](https://github.com/toeverything/AFFiNE/issues) to find one that interests you. You can narrow down the search using `labels` as filters. See our [Labels](https://github.com/toeverything/AFFiNE/labels) for more information. As a general rule, we dont assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix.
### Make Changes
#### Make changes in the UI
Click **Make a contribution** at the bottom of any docs page to make small changes such as a typo, sentence fix, or a broken link. This takes you to the `.md` file where you can make your changes and [create a pull request](#pull-request) for a review.
#### Make changes in a codespace
For more information about using a codespace for working on GitHub documentation, see "[Working in a codespace](https://github.com/github/docs/blob/main/contributing/codespace.md)."
#### Make changes locally
1. [Install Git LFS](https://docs.github.com/en/github/managing-large-files/versioning-large-files/installing-git-large-file-storage).
2. Fork the repository.
- Using GitHub Desktop:
- [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop.
- Once Desktop is set up, you can use it to [fork the repo](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/cloning-and-forking-repositories-from-github-desktop)!
- Using the command line:
- [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them.
3. Install or update to **Node.js v16**.
4. Create a working branch and start with your changes!
### Commit your update
Commit the changes once you are happy with them.
Reach out the community members for necessary help.
Once your changes are ready, don't forget to self-review to speed up the review process:zap:.
### Pull Request
When you're finished with the changes, create a pull request, also known as a PR.
- Fill the "Ready for review" template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request.
- Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.
- Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge.
Once you submit your PR, a Docs team member will review your proposal. We may ask questions or request for additional information.
- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).
- If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues.
### Your PR is merged!
Congratulations :tada::tada: The AFFiNE team thanks you :sparkles:.
Once your PR is merged, your contributions will be publicly visible on our GitHub.
Now that you are part of the AFFiNE community, see how else you can join and help over at [GitBook](https://docs.affine.pro/affine/)
# Please visit https://docs.affine.pro/docs/contributing

View File

@ -1,5 +1,10 @@
# Building AFFiNE Desktop Client App
> **Warning**:
>
> This document is not guaranteed to be up-to-date.
> If you find any outdated information, please feel free to open an issue or submit a PR.
## Table of Contents
- [Prerequisites](#prerequisites)
@ -7,35 +12,100 @@
- [Build](#build)
- [CI](#ci)
## Things you may need to know before getting started
Building the desktop client app for the moment is a bit more complicated than building the web app. The client right now is an Electron app that wraps the prebuilt web app, with parts of the native modules written in Rust, which means we have the following source modules to build a desktop client app:
1. `packages/frontend/core`: the web app
2. `packages/frontend/native`: the native modules written in Rust (mostly the sqlite bindings)
3. `packages/frontend/electron`: the Electron app (containing main & helper process, and the electron entry point in `packages/frontend/electron/renderer`)
#3 is dependent on #1 and #2, and relies on electron-forge to make the final app & installer. To get a deep understanding of how the desktop client app is built, you may want to read the workflow file in [release-desktop.yml](/.github/workflows/release-desktop.yml).
Due to [some limitations of Electron builder](https://github.com/yarnpkg/berry/issues/4804), you may need to have two separate yarn config for building the core and the desktop client app:
1. build frontend (with default yarn settings)
2. build electron (reinstall with hoisting off)
We will explain the steps in the following sections.
## Prerequisites
Before you start building AFFiNE Desktop Client Application, please [install Rust toolchain first](https://www.rust-lang.org/learn/get-started).
Before you start building AFFiNE Desktop Client Application, please following the same steps in [BUILDING#Prerequisites](./BUILDING.md#prerequisites) to install Node.js and Rust.
Note that if you encounter any issues with installing Rust and crates, try following [this guide (zh-CN)](https://course.rs/first-try/slowly-downloading.html) to set up alternative registries.
On Windows, you must enable symbolic links this code repo. See [#### Windows](./BUILDING.md#Windows).
## Development
## Build, package & make the desktop client app
To run AFFiNE Desktop Client Application locally, run the following commands:
### 0. Build the native modules
```sh
# in repo root
yarn install
yarn dev
Please refer to `Build Native Dependencies` section in [BUILDING.md](./BUILDING.md#Build-Native-Dependencies) to build the native modules.
# in packages/frontend/native
yarn build
### 1. Build the core
# in packages/frontend/electron
yarn dev
On Mac & Linux
```shell
BUILD_TYPE=canary SKIP_NX_CACHE=1 yarn workspace @affine/electron generate-assets
```
Now you should see the Electron app window popping up shortly.
On Windows (powershell)
## Build
```powershell
$env:BUILD_TYPE="canary"
$env:SKIP_NX_CACHE=1
$env:DISTRIBUTION=desktop
$env:SKIP_WEB_BUILD=1
yarn build --skip-nx-cache
```
To build the desktop client application, run `yarn make` in `packages/frontend/electron`.
### 2. Re-config yarn, clean up the node_modules and reinstall the dependencies
Note: you may want to comment out `osxSign` and `osxNotarize` in `forge.config.js` to avoid signing and notarizing the app.
As we said before, you need to reinstall the dependencies with hoisting off. You can do this by running the following command:
```shell
yarn config set nmMode classic
yarn config set nmHoistingLimits workspaces
```
Then, clean up all node_modules and reinstall the dependencies:
On Mac & Linux
```shell
find . -name 'node_modules' -type d -prune -exec rm -rf '{}' +
yarn install
```
On Windows (powershell)
```powershell
dir -Path . -Filter node_modules -recurse | foreach {echo $_.fullname; rm -r -Force $_.fullname}
yarn install
```
### 3. Build the desktop client app installer
#### Mac & Linux
Note: you need to comment out `osxSign` and `osxNotarize` in `forge.config.js` to skip signing and notarizing the app.
```shell
BUILD_TYPE=canary SKIP_WEB_BUILD=1 HOIST_NODE_MODULES=1 yarn workspace @affine/electron make
```
#### Windows
Making the windows installer is a bit different. Right now we provide two installer options: squirrel and nsis.
```powershell
$env:BUILD_TYPE="canary"
$env:SKIP_WEB_BUILD=1
$env:HOIST_NODE_MODULES=1
yarn workspace @affine/electron package
yarn workspace @affine/electron make-squirrel
yarn workspace @affine/electron make-nsis
```
Once the build is complete, you can find the paths to the binaries in the terminal output.

View File

@ -1,256 +0,0 @@
# Behind the code - Code Design and Architecture of the AFFiNE platform
## Introduction
This document delves into the design and architecture of the AFFiNE platform, providing insights for developers interested in contributing to AFFiNE or gaining a better understanding of our design principles.
## Addressing the Challenge
AFFiNE is a platform designed to be the next-generation collaborative knowledge base for professionals. It is local-first, yet collaborative; It is robust as a foundational platform, yet friendly to extend. We believe that a knowledge base that truly meets the needs of professionals in different scenarios should be open-source and open to the community. By using AFFiNE, people can take full control of their data and workflow, thus achieving data sovereignty.
To do so, we should have a stable plugin system that is easy to use by the community and a well-modularized editor for customizability. Let's list the challenges from the perspective of data modeling, UI and feature plugins, and cross-platform support.
### Data might come from anywhere and go anywhere, in spite of the cloud
AFFiNE provides users with flexibility and control over their data storage. Our platform is designed to prioritize user ownership of data, which means data in AFFiNE is always accessible from local devices like a laptop's local file or the browser's indexedDB. In the mean while, data can also be stored in centralised cloud-native way.
Thanks to our use of CRDTs (Conflict-free Replicated Data Types), data in AFFiNE is always conflict-free, similar to a auto-resolve-conflict Git. This means that data synchronization, sharing, and real-time collaboration are seamless and can occur across any network layer so long as the data as passed. As a result, developers do not need to worry about whether the data was generated locally or remotely, as CRDTs treat both equally.
While a server-centric backend is supported with AFFiNE, it is not suggested. By having a local-first architecture, AFFiNE users can have real-time responsive UI, optimal performance and effortlessly synchronize data across multiple devices and locations. This includes peer-to-peer file replication, storing file in local or cloud storage, saving it to a server-side database, or using AFFiNE Cloud for real-time collaboration and synchronization.
### Customizable UI and features
AFFiNE is a platform that allows users to customize the UI and features of each part.
We need to consider the following cases:
- Pluggable features: Some features can be disabled or enabled. For example, individuals who use AFFiNE for personal purposes may not need authentication or collaboration features. On the other hand, enterprise users may require authentication and strong security.
- SDK for the developers, the developers can modify or build their own feature or UI plugins, such as AI writing support, self-hosted databases, or domain-specific editable blocks.
### Diverse platforms
AFFiNE supports various platforms, including desktop, mobile, and web while being local-first. However, it's important to note that certain features may differ on different platforms, and it's also possible for data and editor versions to become mismatched.
## The solution
### Loading Mechanism
The AFFiNE is built on the web platform, meaning that most code runs on the JavaScript runtime(v8, QuickJS).
Some interfaces, like in the Desktop, will be implemented in the native code like Rust.
But eventually, the main logic of AFFiNE is running on the JavaScript runtime. Since it is a single-threaded runtime, we need to ensure that the code is running in a non-blocking way.
Some logic has to be running in the blocking way.
We have to set up the environment before starting the core.
And for the Workspace, like local workspace or cloud workspace, we have to load the data from the storage before rendering the UI.
During this period, there will be transition animation and skeleton UI.
```mermaid
graph LR
subgraph Interactive unavailable
A[Loading] --> B[Setup Environment]
B --> C[Loading Initial Data]
C --> D[Skeleton UI]
end
D --> E[Render UI]
E --> F[Async fetching Data] --> E
```
In this way, we need to boost the performance of the loading process.
The initial data is the most costly part of the process.
We must ensure that the initial data is loaded as quickly as possible.
Here is an obvious conclusion that only one Workspace is active simultaneously in one browser.
So we need to load the data of the active Workspace as the initial data.
And other workspaces can be loaded in the background asynchronously.
For example, the local Workspace is saved in the browser's indexedDB.
One way to boost the performance is to use the Web Worker to load the data in the background.
Here is one pseudocode:
```tsx
// worker.ts
import { openDB } from 'idb';
const db = await openDB('local-db' /* ... */);
const data = await db.getAll('data');
self.postMessage(data);
// main.ts
const worker = new Worker('./worker.ts', { type: 'module' });
await new Promise<Data>(resolve => {
worker.addEventListener('message', e => resolve(e.data));
});
// ready to render the UI
renderUI(data);
```
We use React Suspense to deal with the initial data loading in the real code.
```tsx
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
const currentWorkspaceIdAtom = atom(null);
const currentWorkspaceAtom = atom<Workspace>(async get => {
const workspaceId = await get(currentWorkspaceIdAtom);
// async load the workspace data
return Workspace;
});
const Workspace = () => {
const currentWorkspace = useAtomValue(currentWorkspaceAtom);
return <WorkspaceUI workspace={currentWorkspace} />;
};
const App = () => {
const router = useRouter();
const workspaceId = router.query.workspaceId;
const [currentWorkspaceId, set] = useAtom(currentWorkspaceIdAtom);
if (!currentWorkspaceId) {
set(workspaceId);
return <Loading />;
}
return (
<Suspense fallback={<Skeleton />}>
<Workspace />
</Suspense>
);
};
```
### Data Storage and UI Rendering
We assume that the data is stored in different places and loaded differently.
In the current version, we have two places to store the data: local and Cloud storage.
The local storage is the browser's indexedDB, the default storage for the local Workspace.
The cloud storage is the AFFiNE Cloud, which is the default storage for the cloud workspace.
But since the Time to Interactive(TTI) is the most important metric for performance and user experience,
all initial data is loaded in the indexedDB.
And other data will be loaded and updated in the background.
With this design concept, we have the following data structure:
```ts
import { Workspace as Store } from '@blocksuite/store';
interface Provider {
type: 'local-indexeddb' | 'affine-cloud' | 'desktop-sqlite';
background: boolean; // if the provider is background, we will load the data in the background
necessary: boolean; // if the provider is necessary, we will block the UI rendering until this provider is ready
}
interface Workspace {
id: string;
store: Store;
providers: Provider[];
}
```
The `provider` is a connector that bridges the current data in memory and the data in another place.
You can combine different providers to build different data storage and loading strategy.
For example, if there is only `affine-cloud`,
the data will be only loaded from the Cloud and not saved in the local storage,
which might be useful for the enterprise user.
Also, we want to distinguish the different types of Workspace.
Even though the providers are enough for the Workspace, when we display the Workspace in the UI, we need to know the type of Workspace.
AFFiNE Cloud Workspace needs user authentication; the local Workspace does not need it.
And there should have a way to create, read, update, and delete the Workspace.
Hence, we combine all details of the Workspace as we mentioned above into the `WorkspacePlugin` type.
```ts
import React from 'react';
interface UI<WorkspaceType> {
DetailPage: React.FC<UIProps<WorkspaceType>>;
SettingPage: React.FC<UIProps<WorkspaceType>>;
SettingPage: React.FC<UIProps<WorkspaceType>>;
}
interface CRUD<WorkspaceType> {
create: () => Promise<WorkspaceType>;
read: (id: string) => Promise<WorkspaceType>;
list: () => Promise<WorkspaceType[]>;
delete: (Workspace: WorkspaceType) => Promise<WorkspaceType>;
}
interface WorkspacePlugin<WorkspaceType> {
type: WorkspaceType;
ui: UI<WorkspaceType>;
crud: CRUD<WorkspaceType>;
}
```
```mermaid
graph TB
WorkspaceCRUD --> Cloud
WorkspaceCRUD --> SelfHostCloud
subgraph Remote
Cloud[AFFiNE Cloud]
SelfHostCloud[Self Host AFFiNE Server]
end
subgraph Computer
WorkspaceCRUD --> DesktopSqlite[Desktop Sqlite]
subgraph JavaScript Runtime
IndexedDB[IndexedDB]
WorkspaceCRUD --> IndexedDB
subgraph Next.js
Entry((entry point))
Entry --> NextApp[Next.js App]
NextApp --> App[App]
end
subgraph Workspace Runtime
App[App] --> WorkspaceUI
WorkspacePlugin[Workspace Plugin]
WorkspacePlugin[Workspace Plugin] --> WorkspaceUI
WorkspacePlugin[Workspace Plugin] --> WorkspaceCRUD[Workspace CRUD]
WorkspaceUI[Workspace UI] --> WorkspaceCRUD
WorkspaceUI -->|async init| Provider
Provider -->|update ui| WorkspaceUI
Provider -->|update data| WorkspaceCRUD
end
end
end
```
Notice that we do not assume the Workspace UI has to be written in React.js(for now, it has to be),
In the future, we can support other UI frameworks instead, like Vue and Svelte.
### Workspace Loading Details
```mermaid
flowchart TD
subgraph JavaScript Runtime
subgraph Next.js
Start((entry point)) -->|setup environment| OnMount{On mount}
OnMount -->|empty data| Init[Init Workspaces]
Init --> LoadData
OnMount -->|already have data| LoadData>Load data]
LoadData --> CurrentWorkspace[Current workspace]
LoadData --> Workspaces[Workspaces]
Workspaces --> Providers[Providers]
subgraph React
Router([Router]) -->|sync `query.workspaceId`| CurrentWorkspace
CurrentWorkspace -->|sync `currentWorkspaceId`| Router
CurrentWorkspace -->|render| WorkspaceUI[Workspace UI]
end
end
Providers -->|push new update| Persistence[(Persistence)]
Persistence -->|patch workspace| Providers
end
```

View File

@ -53,7 +53,3 @@ yarn dev
### `@affine/electron`
See [building desktop client app](../building-desktop-client-app.md).
## What's next?
- [Behind the code](./behind-the-code.md)

View File

@ -1,5 +1,10 @@
This document explains how to start server (@affine/server) locally with Docker
> **Warning**:
>
> This document is not guaranteed to be up-to-date.
> If you find any outdated information, please feel free to open an issue or submit a PR.
## Run postgresql in docker
```