refactor: environment setup (#2898)

Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>
This commit is contained in:
Alex Yang
2023-06-28 19:19:19 +08:00
committed by GitHub
parent 80c2a78273
commit 5496969e58
72 changed files with 255 additions and 242 deletions

View File

@@ -1,4 +1,4 @@
import { env } from '@affine/env/config';
import { isBrowser } from '@affine/env/constant';
import { atomWithObservable, atomWithStorage } from 'jotai/utils';
import { Observable } from 'rxjs';
@@ -22,7 +22,7 @@ function rpcToObservable<
return new Observable<T>(subscriber => {
subscriber.next(initialValue);
onSubscribe?.();
if (typeof window === 'undefined' || !env.isDesktop || !event) {
if (!isBrowser || !environment.isDesktop || !event) {
subscriber.complete();
return;
}

View File

@@ -1,5 +1,4 @@
import { config } from '@affine/env/config';
import { Unreachable } from '@affine/env/constant';
import { isBrowser, Unreachable } from '@affine/env/constant';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { CloseIcon, NewIcon, ResetIcon } from '@blocksuite/icons';
import clsx from 'clsx';
@@ -20,7 +19,7 @@ interface AddPageButtonProps {
}
const currentVersionAtom = atom(async () => {
if (typeof window === 'undefined') {
if (!isBrowser) {
return null;
}
const currentVersion = await window.apis?.updater.currentVersion();
@@ -28,7 +27,7 @@ const currentVersionAtom = atom(async () => {
});
const currentChangelogUnreadAtom = atom(async get => {
if (typeof window === 'undefined') {
if (!isBrowser) {
return false;
}
const mapping = get(changelogCheckedAtom);
@@ -79,7 +78,7 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
);
}
} else if (currentChangelogUnread) {
window.open(config.changelogUrl, '_blank');
window.open(runtimeConfig.changelogUrl, '_blank');
onDismissCurrentChangelog();
} else {
throw new Unreachable();

View File

@@ -1,4 +1,3 @@
import { env } from '@affine/env';
import { Skeleton } from '@mui/material';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
@@ -84,7 +83,7 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
// disable animation to avoid UI flash
const enableAnimation = useEnableAnimation();
const isMacosDesktop = env.isDesktop && env.isMacOs;
const isMacosDesktop = environment.isDesktop && environment.isMacOs;
if (initialRender) {
// avoid the UI flash
return <div />;
@@ -97,7 +96,7 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
[navWidthVar]: `${appSidebarWidth}px`,
})}
className={clsx(navWrapperStyle, {
'has-background': env.isDesktop && props.hasBackground,
'has-background': environment.isDesktop && props.hasBackground,
})}
data-open={open}
data-is-macos-electron={isMacosDesktop}

View File

@@ -1,19 +1,19 @@
import { env } from '@affine/env/config';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { SearchIcon } from '@blocksuite/icons';
import clsx from 'clsx';
import type { HTMLAttributes } from 'react';
import { Spotlight } from '../spolight';
import * as styles from './index.css';
interface QuickSearchInputProps extends React.HTMLAttributes<HTMLDivElement> {
interface QuickSearchInputProps extends HTMLAttributes<HTMLDivElement> {
onClick?: () => void;
}
// Although it is called an input, it is actually a button.
export function QuickSearchInput({ onClick, ...props }: QuickSearchInputProps) {
const t = useAFFiNEI18N();
const isMac = env.isBrowser && env.isMacOs;
const isMac = environment.isBrowser && environment.isMacOs;
return (
<div

View File

@@ -1,4 +1,3 @@
import { env } from '@affine/env/config';
import { ArrowLeftSmallIcon, ArrowRightSmallIcon } from '@blocksuite/icons';
import { useAtomValue } from 'jotai';
@@ -20,9 +19,9 @@ export const SidebarHeader = (props: SidebarHeaderProps) => {
const open = useAtomValue(appSidebarOpenAtom);
return (
<div className={navHeaderStyle} data-open={open}>
{env.isDesktop && (
{environment.isDesktop && (
<>
{env.isMacOs && <div style={{ flex: 1 }} />}
{environment.isMacOs && <div style={{ flex: 1 }} />}
<IconButton
size="middle"
data-testid="app-sidebar-arrow-button-back"
@@ -50,7 +49,7 @@ export const SidebarHeader = (props: SidebarHeaderProps) => {
<ArrowRightSmallIcon />
</IconButton>
{!env.isMacOs && <div style={{ flex: 1 }} />}
{!environment.isMacOs && <div style={{ flex: 1 }} />}
</>
)}
{open && <SidebarSwitch />}

View File

@@ -1,3 +1,4 @@
import { isBrowser } from '@affine/env/constant';
import type { EmbedBlockDoubleClickData } from '@blocksuite/blocks';
import { atom } from 'jotai';
@@ -5,7 +6,7 @@ export const previewBlockIdAtom = atom<string | null>(null);
export const hasAnimationPlayedAtom = atom<boolean | null>(true);
previewBlockIdAtom.onMount = set => {
if (typeof window !== 'undefined') {
if (isBrowser) {
const callback = (event: CustomEvent<EmbedBlockDoubleClickData>) => {
set(event.detail.blockId);
};

View File

@@ -1,3 +1,4 @@
import { isDesktop } from '@affine/env/constant';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import {
DeletePermanentlyIcon,
@@ -65,7 +66,7 @@ export const OperationCell: React.FC<OperationCellProps> = ({
>
{favorite ? t['Remove from favorites']() : t['Add to Favorites']()}
</MenuItem>
{!environment.isDesktop && (
{!isDesktop && (
<MenuItem onClick={onOpenPageInNewTab} icon={<OpenInNewIcon />}>
{t['Open in new tab']()}
</MenuItem>

View File

@@ -1,4 +1,3 @@
import { prefixUrl } from '@affine/env';
import type { LocalWorkspace } from '@affine/env/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { Trans } from '@affine/i18n';

View File

@@ -1,3 +1,4 @@
import { isDesktop } from '@affine/env/constant';
import { ThemeProvider as NextThemeProvider, useTheme } from 'next-themes';
import type { PropsWithChildren } from 'react';
import { memo, useRef } from 'react';
@@ -9,7 +10,7 @@ const DesktopThemeSync = memo(function DesktopThemeSync() {
const lastThemeRef = useRef(theme);
const onceRef = useRef(false);
if (lastThemeRef.current !== theme || !onceRef.current) {
if (environment.isDesktop && theme) {
if (isDesktop && theme) {
window.apis?.ui
.handleThemeChange(theme as 'dark' | 'light' | 'system')
.catch(err => {

View File

@@ -1,3 +1,4 @@
import { isDesktop } from '@affine/env/constant';
import { clsx } from 'clsx';
import type { FC, PropsWithChildren, ReactElement } from 'react';
@@ -22,7 +23,7 @@ export const AppContainer: FC<WorkspaceRootProps> = ({
<div
className={clsx(appStyle, {
'noisy-background': noisyBackground,
'blur-background': environment.isDesktop && useBlurBackground,
'blur-background': isDesktop && useBlurBackground,
})}
data-noise-background={noisyBackground}
data-is-resizing={resizing}
@@ -40,7 +41,7 @@ export const MainContainer = (props: MainContainerProps): ReactElement => {
return (
<div
className={clsx(mainContainerStyle, 'main-container', props.className)}
data-is-desktop={environment.isDesktop}
data-is-desktop={isDesktop}
>
{props.children}
</div>

View File

@@ -5,7 +5,8 @@
"compilerOptions": {
"composite": true,
"noEmit": false,
"outDir": "lib"
"outDir": "lib",
"types": ["@affine/env"]
},
"references": [
{

View File

@@ -3,6 +3,7 @@
"private": true,
"main": "./src/index.ts",
"module": "./src/index.ts",
"types": "./src/global.ts",
"devDependencies": {
"@blocksuite/global": "0.0.0-20230627165830-836e6fd1-nightly",
"next": "=13.4.2",
@@ -11,9 +12,7 @@
"zod": "^3.21.4"
},
"exports": {
".": "./src/index.ts",
"./api": "./src/api.ts",
"./config": "./src/config.ts",
"./global": "./src/global.ts",
"./constant": "./src/constant.ts",
"./workspace": "./src/workspace.ts",
"./workspace/legacy-cloud": "./src/workspace/legacy-cloud/index.ts",

View File

@@ -38,9 +38,11 @@ describe('subdoc', () => {
if (id === 'xyWNqindHH') {
return;
}
if (blocks[id]['sys:flavour'] === 'affine:surface' && !blocks[id]['prop:elements']) {
if (
blocks[id]['sys:flavour'] === 'affine:surface' &&
!blocks[id]['prop:elements']
) {
blocks[id]['prop:elements'] = data[id]['prop:elements'];
}
expect(data[id]).toEqual(blocks[id]);
});

View File

@@ -1,28 +0,0 @@
import { config, env } from './config';
import { isValidIPAddress } from './is-valid-ip-address';
let prefixUrl = '/';
if (typeof window === 'undefined' || env.isDesktop) {
// SSR or Desktop
const serverAPI = config.serverAPI;
if (isValidIPAddress(serverAPI.split(':')[0])) {
// This is for Server side rendering support
prefixUrl = new URL('http://' + config.serverAPI + '/').origin;
} else {
prefixUrl = serverAPI;
}
prefixUrl = prefixUrl.endsWith('/') ? prefixUrl : prefixUrl + '/';
} else {
const params = new URLSearchParams(window.location.search);
if (params.get('prefixUrl')) {
prefixUrl = params.get('prefixUrl') as string;
} else {
prefixUrl = window.location.origin + '/';
}
}
const apiUrl = new URL(prefixUrl);
const wsProtocol = apiUrl.protocol === 'https:' ? 'wss' : 'ws';
const websocketPrefixUrl = `${wsProtocol}://${apiUrl.host}`;
export { prefixUrl, websocketPrefixUrl };

View File

@@ -91,12 +91,12 @@ function runBlockMigration(
return;
}
if (flavour === 'affine:surface' && version <= 3) {
if(data.has('elements')){
if (data.has('elements')) {
const elements = data.get('elements') as Y.Map<unknown>;
data.set('prop:elements', elements.clone());
data.delete('elements');
} else {
data.set('prop:elements', new Y.Map())
data.set('prop:elements', new Y.Map());
}
}
if (flavour === 'affine:embed') {

View File

@@ -1,5 +1,19 @@
// This file should has not side effect
import type { Workspace } from '@blocksuite/store';
declare global {
interface Window {
appInfo: {
electron: boolean;
};
}
}
//#region runtime variables
export const isBrowser = typeof window !== 'undefined';
export const isServer = !isBrowser && typeof navigator === 'undefined';
export const isDesktop = isBrowser && !!window.appInfo?.electron;
//#endregion
export const AFFINE_STORAGE_KEY = 'affine-local-storage-v2';
export const DEFAULT_WORKSPACE_NAME = 'Demo Workspace';
export const UNTITLED_WORKSPACE_NAME = 'Untitled';

View File

@@ -1,2 +0,0 @@
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import '../hooks/src/use-block-suite-page-meta.ts';

View File

@@ -10,9 +10,12 @@ import type {
UpdaterHandlerManager,
WorkspaceHandlerManager,
} from '@toeverything/infra';
// fixme(himself65): remove `next/config` dependency
import getConfig from 'next/config';
import { z } from 'zod';
import { isBrowser, isDesktop, isServer } from './constant';
import { isValidIPAddress } from './is-valid-ip-address';
import { UaHelper } from './ua-helper';
declare global {
@@ -31,6 +34,19 @@ declare global {
};
events: any;
}
// eslint-disable-next-line no-var
var environment: Environment;
// eslint-disable-next-line no-var
var runtimeConfig: PublicRuntimeConfig;
// eslint-disable-next-line no-var
var $AFFINE_SETUP: boolean | undefined;
// eslint-disable-next-line no-var
var editorVersion: string | undefined;
// eslint-disable-next-line no-var
var prefixUrl: string;
// eslint-disable-next-line no-var
var websocketPrefixUrl: string;
}
export const buildFlagsSchema = z.object({
@@ -135,10 +151,31 @@ interface Desktop extends ChromeBrowser {
export type Environment = Browser | Server | Desktop;
export const env: Environment = (() => {
let environment = null;
function printBuildInfo() {
console.group('Build info');
console.log('Project:', config.PROJECT_NAME);
console.log(
'Build date:',
config.BUILD_DATE ? new Date(config.BUILD_DATE).toLocaleString() : 'Unknown'
);
console.log('Editor Version:', config.editorVersion);
console.log('Version:', config.gitVersion);
console.log(
'AFFiNE is an open source project, you can view its source code on GitHub!'
);
console.log(`https://github.com/toeverything/AFFiNE/tree/${config.hash}`);
console.groupEnd();
}
export function setupGlobal() {
if (globalThis.$AFFINE_SETUP) {
return;
}
globalThis.runtimeConfig = config;
let environment: Environment;
const isDebug = process.env.NODE_ENV === 'development';
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
if (isServer) {
environment = {
isDesktop: false,
isBrowser: false,
@@ -150,7 +187,7 @@ export const env: Environment = (() => {
environment = {
origin: window.location.origin,
isDesktop: !!window.appInfo?.electron,
isDesktop,
isBrowser: true,
isServer: false,
isDebug,
@@ -177,45 +214,37 @@ export const env: Environment = (() => {
}
}
globalThis.environment = environment;
return environment;
})();
function printBuildInfo() {
console.group('Build info');
console.log('Project:', config.PROJECT_NAME);
console.log(
'Build date:',
config.BUILD_DATE ? new Date(config.BUILD_DATE).toLocaleString() : 'Unknown'
);
console.log('Editor Version:', config.editorVersion);
console.log('Version:', config.gitVersion);
console.log(
'AFFiNE is an open source project, you can view its source code on GitHub!'
);
console.log(`https://github.com/toeverything/AFFiNE/tree/${config.hash}`);
console.groupEnd();
}
declare global {
// eslint-disable-next-line no-var
var environment: Environment;
// eslint-disable-next-line no-var
var $AFFINE_SETUP: boolean | undefined;
// eslint-disable-next-line no-var
var editorVersion: string | undefined;
}
export function setupGlobal() {
if (globalThis.$AFFINE_SETUP) {
return;
}
globalThis.environment = env;
if (env.isBrowser) {
if (environment.isBrowser) {
printBuildInfo();
globalThis.editorVersion = config.editorVersion;
globalThis.editorVersion = global.editorVersion;
}
let prefixUrl: string;
if (!isBrowser || isDesktop) {
// SSR or Desktop
const serverAPI = runtimeConfig.serverAPI;
if (isValidIPAddress(serverAPI.split(':')[0])) {
// This is for Server side rendering support
prefixUrl = new URL('http://' + runtimeConfig.serverAPI + '/').origin;
} else {
prefixUrl = serverAPI;
}
prefixUrl = prefixUrl.endsWith('/') ? prefixUrl : prefixUrl + '/';
} else {
const params = new URLSearchParams(window.location.search);
if (params.get('prefixUrl')) {
prefixUrl = params.get('prefixUrl') as string;
} else {
prefixUrl = window.location.origin + '/';
}
}
const apiUrl = new URL(prefixUrl);
const wsProtocol = apiUrl.protocol === 'https:' ? 'wss' : 'ws';
const websocketPrefixUrl = `${wsProtocol}://${apiUrl.host}`;
globalThis.prefixUrl = prefixUrl;
globalThis.websocketPrefixUrl = websocketPrefixUrl;
globalThis.$AFFINE_SETUP = true;
}
export { config };

View File

@@ -1,3 +0,0 @@
export * from './api';
export * from './config';
export * from './constant';

View File

@@ -3,7 +3,7 @@
*/
import 'fake-indexeddb/auto';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import type { Page } from '@blocksuite/store';
import { assertExists } from '@blocksuite/store';

View File

@@ -1,4 +1,4 @@
import { UNTITLED_WORKSPACE_NAME } from '@affine/env';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
import type { Workspace } from '@blocksuite/store';
import { assertExists } from '@blocksuite/store';
import type { Atom, WritableAtom } from 'jotai';

View File

@@ -26,7 +26,6 @@
"url": "git+https://github.com/toeverything/AFFiNE.git"
},
"dependencies": {
"@affine/debug": "workspace:*",
"i18next": "^23.2.3",
"react-i18next": "^13.0.0"
},

View File

@@ -2,9 +2,13 @@ import '@affine/component/theme/global.css';
import '@affine/component/theme/theme.css';
import { LOCALES, createI18n } from '@affine/i18n';
import { ThemeProvider, useTheme } from 'next-themes';
import { ComponentType, useEffect } from 'react';
import { setupGlobal } from '@affine/env/global';
import type { ComponentType } from 'react';
import { useEffect } from 'react';
import { useDarkMode } from 'storybook-dark-mode';
setupGlobal();
export const parameters = {
backgrounds: { disable: true },
actions: { argTypesRegex: '^on[A-Z].*' },

View File

@@ -12,5 +12,10 @@
},
"include": [".storybook/**/*"],
"exclude": ["lib"],
"references": [{ "path": "../i18n" }]
"references": [
{ "path": "../i18n" },
{
"path": "../env"
}
]
}

View File

@@ -1,4 +1,4 @@
import { MessageCode, Messages } from '@affine/env';
import { MessageCode, Messages } from '@affine/env/constant';
import type {
AcceptInvitingParams,
DeleteWorkspaceParams,

View File

@@ -1,3 +1,4 @@
import { isBrowser } from '@affine/env/constant';
import * as encoding from 'lib0/encoding';
import * as math from 'lib0/math';
import { Observable } from 'lib0/observable';
@@ -217,7 +218,7 @@ export class KeckProvider extends Observable<string> {
'window unload'
);
};
if (typeof window !== 'undefined') {
if (isBrowser) {
window.addEventListener('unload', this._unloadHandler);
} else if (typeof process !== 'undefined') {
process.on('exit', this._unloadHandler);
@@ -259,7 +260,7 @@ export class KeckProvider extends Observable<string> {
}
clearInterval(this._checkInterval);
this.disconnect();
if (typeof window !== 'undefined') {
if (isBrowser) {
window.removeEventListener('unload', this._unloadHandler);
} else if (typeof process !== 'undefined') {
process.off('exit', this._unloadHandler);

View File

@@ -1,5 +1,4 @@
import { DebugLogger } from '@affine/debug';
import { env } from '@affine/env';
import { assertExists } from '@blocksuite/global/utils';
import { Slot } from '@blocksuite/store';
import { initializeApp } from 'firebase/app';
@@ -189,7 +188,7 @@ export function createAffineAuth(prefix = '/') {
}
try {
let idToken: string | undefined;
if (env.isDesktop) {
if (environment.isDesktop) {
idToken = await signInWithElectron(auth);
} else {
const response = await signInWithPopup(auth, provider);

View File

@@ -1,4 +1,4 @@
import { prefixUrl } from '@affine/env';
import { setupGlobal } from '@affine/env/global';
import { rootStore } from '@toeverything/plugin-infra/manager';
import { createUserApis, createWorkspaceApis } from './api/index';
@@ -6,9 +6,12 @@ import { currentAffineUserAtom } from './atom';
import type { LoginResponse } from './login';
import { createAffineAuth, parseIdToken, setLoginStorage } from './login';
setupGlobal();
export const affineAuth = createAffineAuth(prefixUrl);
const affineApis = {} as ReturnType<typeof createUserApis> &
ReturnType<typeof createWorkspaceApis>;
Object.assign(affineApis, createUserApis(prefixUrl));
Object.assign(affineApis, createWorkspaceApis(prefixUrl));

View File

@@ -1,5 +1,4 @@
import { DebugLogger } from '@affine/debug';
import { websocketPrefixUrl } from '@affine/env/api';
import type { WorkspaceCRUD } from '@affine/env/workspace';
import type { WorkspaceFlavour } from '@affine/env/workspace';
import {

View File

@@ -1,3 +1,4 @@
import { isBrowser } from '@affine/env/constant';
import type { WorkspaceFlavour } from '@affine/env/workspace';
import type { WorkspaceVersion } from '@affine/env/workspace';
import type { EditorContainer } from '@blocksuite/editor';
@@ -44,14 +45,12 @@ export const rootWorkspacesMetadataAtom = atomWithStorage<
export const rootCurrentWorkspaceIdAtom = atom<string | null>(null);
rootCurrentWorkspaceIdAtom.onMount = set => {
if (typeof window !== 'undefined') {
if (isBrowser) {
const callback = (url: string) => {
const value = url.split('/')[2];
if (value) {
set(value);
if (typeof window !== 'undefined') {
localStorage.setItem('last_workspace_id', value);
}
localStorage.setItem('last_workspace_id', value);
} else {
set(null);
}
@@ -68,7 +67,7 @@ rootCurrentWorkspaceIdAtom.onMount = set => {
export const rootCurrentPageIdAtom = atom<string | null>(null);
rootCurrentPageIdAtom.onMount = set => {
if (typeof window !== 'undefined') {
if (isBrowser) {
const callback = (url: string) => {
const value = url.split('/')[3];
if (value) {

View File

@@ -1,5 +1,4 @@
import { DebugLogger } from '@affine/debug';
import { config } from '@affine/env';
import type { LocalWorkspace, WorkspaceCRUD } from '@affine/env/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { nanoid, Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
@@ -112,7 +111,11 @@ export const CRUD: WorkspaceCRUD<WorkspaceFlavour.LOCAL> = {
: [];
// workspaces in desktop
if (window.apis && environment.isDesktop && config.enableSQLiteProvider) {
if (
window.apis &&
environment.isDesktop &&
runtimeConfig.enableSQLiteProvider
) {
const desktopIds = (await window.apis.workspace.list()).map(([id]) => id);
// the ids maybe a subset of the local storage
const moreWorkspaces = desktopIds.filter(

View File

@@ -1,4 +1,3 @@
import { config, websocketPrefixUrl } from '@affine/env';
import type {
AffineWebSocketProvider,
LocalIndexedDBBackgroundProvider,
@@ -169,11 +168,11 @@ export const createLocalProviders = (): DocProviderCreator[] => {
createIndexedDBDownloadProvider,
] as DocProviderCreator[];
if (config.enableBroadcastChannelProvider) {
if (runtimeConfig.enableBroadcastChannelProvider) {
providers.push(createBroadcastChannelProvider);
}
if (environment.isDesktop && config.enableSQLiteProvider) {
if (environment.isDesktop && runtimeConfig.enableSQLiteProvider) {
providers.push(createSQLiteProvider, createSQLiteDBDownloadProvider);
}
@@ -185,7 +184,8 @@ export const createAffineProviders = (): DocProviderCreator[] => {
[
createAffineDownloadProvider,
createAffineWebSocketProvider,
config.enableBroadcastChannelProvider && createBroadcastChannelProvider,
runtimeConfig.enableBroadcastChannelProvider &&
createBroadcastChannelProvider,
createIndexedDBDownloadProvider,
] as DocProviderCreator[]
).filter(v => Boolean(v));

View File

@@ -1,5 +1,5 @@
import type { BlockSuiteFeatureFlags } from '@affine/env';
import { config } from '@affine/env';
import { isBrowser, isDesktop } from '@affine/env/constant';
import type { BlockSuiteFeatureFlags } from '@affine/env/global';
import { WorkspaceFlavour } from '@affine/env/workspace';
import {
createAffineProviders,
@@ -26,7 +26,7 @@ export function cleanupWorkspace(flavour: WorkspaceFlavour) {
}
function setEditorFlags(workspace: Workspace) {
Object.entries(config.editorFlags).forEach(([key, value]) => {
Object.entries(runtimeConfig.editorFlags).forEach(([key, value]) => {
workspace.awarenessStore.setFlag(
key as keyof BlockSuiteFeatureFlags,
value
@@ -96,9 +96,9 @@ export function createEmptyBlockSuiteWorkspace(
}
providerCreators.push(...createAffineProviders());
} else {
if (typeof window !== 'undefined') {
if (isBrowser) {
blobStorages.push(createIndexeddbStorage);
if (environment.isDesktop) {
if (isDesktop) {
blobStorages.push(createSQLiteStorage);
}
}
@@ -107,7 +107,7 @@ export function createEmptyBlockSuiteWorkspace(
const workspace = new Workspace({
id,
isSSR: typeof window === 'undefined',
isSSR: !isBrowser,
providerCreators: typeof window === 'undefined' ? [] : providerCreators,
blobStorages: blobStorages,
idGenerator,