From bff8ca617833584d3164e91feeeb6d1160c98bbd Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Wed, 28 Jun 2023 19:19:19 +0800 Subject: [PATCH] refactor: environment setup (#2898) Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com> --- apps/web/src/adapters/affine/index.tsx | 7 +- apps/web/src/adapters/local/index.tsx | 9 +- apps/web/src/adapters/workspace.ts | 2 +- apps/web/src/atoms/index.ts | 3 +- apps/web/src/atoms/public-workspace/index.ts | 5 +- apps/web/src/atoms/root.ts | 3 +- apps/web/src/bootstrap/index.ts | 13 +- .../affine/create-workspace-modal/index.tsx | 7 +- .../general-setting/about/index.tsx | 4 +- .../general-setting/appearance/index.tsx | 8 +- .../panel/collaboration/index.tsx | 3 +- .../panel/export/index.tsx | 5 +- .../panel/general/index.tsx | 7 +- .../panel/publish/index.tsx | 9 +- .../block-suite-page-list/index.tsx | 5 +- .../workspace-header/download-tips.tsx | 4 +- .../header-right-items/share-menu.tsx | 3 +- .../header-right-items/sync-user.tsx | 3 +- .../blocksuite/workspace-header/header.tsx | 3 +- .../blocksuite/workspace-header/utils.tsx | 18 +-- apps/web/src/components/pure/footer/index.tsx | 3 +- .../src/components/pure/help-island/index.tsx | 5 +- .../pure/quick-search-modal/index.tsx | 11 +- .../pure/quick-search-modal/results.tsx | 2 +- .../pure/workspace-list-modal/index.tsx | 3 +- .../src/components/root-app-sidebar/index.tsx | 12 +- apps/web/src/components/workspace-header.tsx | 3 +- apps/web/src/hooks/affine/use-shortcuts.ts | 9 +- .../hooks/current/use-current-workspace.ts | 3 +- apps/web/src/layouts/workspace-layout.tsx | 6 +- apps/web/src/pages/_app.tsx | 4 - apps/web/src/pages/plugins.tsx | 3 +- apps/web/src/providers/modal-provider.tsx | 3 +- apps/web/src/shared/gql.ts | 1 - apps/web/src/utils/create-emotion-cache.ts | 4 +- .../app-updater-button/index.jotai.ts | 4 +- .../app-sidebar/app-updater-button/index.tsx | 9 +- .../src/components/app-sidebar/index.tsx | 5 +- .../app-sidebar/quick-search-input/index.tsx | 6 +- .../app-sidebar/sidebar-header/index.tsx | 7 +- .../image-preview-modal/index.jotai.ts | 3 +- .../components/page-list/operation-cell.tsx | 3 +- .../src/components/share-menu/share-page.tsx | 1 - .../src/components/theme-provider/index.tsx | 3 +- .../src/components/workspace/index.tsx | 5 +- packages/component/tsconfig.json | 3 +- packages/env/package.json | 5 +- .../src/__tests__/subdoc-migration.spec.ts | 6 +- packages/env/src/api.ts | 28 ----- .../env/src/blocksuite/subdoc-migration.ts | 4 +- packages/env/src/constant.ts | 14 +++ packages/env/src/env.d.ts | 2 - packages/env/src/{config.ts => global.ts} | 111 +++++++++++------- packages/env/src/index.ts | 3 - packages/hooks/src/__tests__/index.spec.ts | 2 +- .../src/use-block-suite-workspace-name.ts | 2 +- packages/i18n/package.json | 1 - packages/storybook/.storybook/preview.tsx | 6 +- packages/storybook/tsconfig.node.json | 7 +- packages/workspace/src/affine/api/index.ts | 2 +- packages/workspace/src/affine/keck/index.ts | 5 +- packages/workspace/src/affine/login.ts | 3 +- packages/workspace/src/affine/shared.ts | 5 +- packages/workspace/src/affine/sync.ts | 1 - packages/workspace/src/atom.ts | 9 +- packages/workspace/src/local/crud.ts | 7 +- packages/workspace/src/providers/index.ts | 8 +- packages/workspace/src/utils.ts | 12 +- scripts/setup/global.ts | 3 + tsconfig.node.json | 7 +- vitest.config.ts | 1 + yarn.lock | 1 - 72 files changed, 255 insertions(+), 242 deletions(-) delete mode 100644 packages/env/src/api.ts delete mode 100644 packages/env/src/env.d.ts rename packages/env/src/{config.ts => global.ts} (78%) delete mode 100644 packages/env/src/index.ts create mode 100644 scripts/setup/global.ts diff --git a/apps/web/src/adapters/affine/index.tsx b/apps/web/src/adapters/affine/index.tsx index bcbc5967e2..915cae9c78 100644 --- a/apps/web/src/adapters/affine/index.tsx +++ b/apps/web/src/adapters/affine/index.tsx @@ -2,9 +2,8 @@ * This file has deprecated because we do not maintain legacy affine cloud, * please use new affine cloud instead. */ -import { AFFINE_STORAGE_KEY, config } from '@affine/env'; import { initEmptyPage } from '@affine/env/blocksuite'; -import { PageNotFoundError } from '@affine/env/constant'; +import { AFFINE_STORAGE_KEY, PageNotFoundError } from '@affine/env/constant'; import type { AffineDownloadProvider, AffineLegacyCloudWorkspace, @@ -109,7 +108,7 @@ export const AffineAdapter: WorkspaceAdapter = { loadPriority: LoadPriority.HIGH, Events: { 'workspace:access': async () => { - if (!config.enableLegacyCloud) { + if (!runtimeConfig.enableLegacyCloud) { console.warn('Legacy cloud is disabled'); return; } @@ -123,7 +122,7 @@ export const AffineAdapter: WorkspaceAdapter = { } }, 'workspace:revoke': async () => { - if (!config.enableLegacyCloud) { + if (!runtimeConfig.enableLegacyCloud) { console.warn('Legacy cloud is disabled'); return; } diff --git a/apps/web/src/adapters/local/index.tsx b/apps/web/src/adapters/local/index.tsx index 2dc784046c..d94b986220 100644 --- a/apps/web/src/adapters/local/index.tsx +++ b/apps/web/src/adapters/local/index.tsx @@ -1,11 +1,10 @@ import { DebugLogger } from '@affine/debug'; +import { initEmptyPage, initPageWithPreloading } from '@affine/env/blocksuite'; import { - config, DEFAULT_HELLO_WORLD_PAGE_ID, DEFAULT_WORKSPACE_NAME, -} from '@affine/env'; -import { initEmptyPage, initPageWithPreloading } from '@affine/env/blocksuite'; -import { PageNotFoundError } from '@affine/env/constant'; + PageNotFoundError, +} from '@affine/env/constant'; import type { LocalIndexedDBDownloadProvider } from '@affine/env/workspace'; import { LoadPriority, @@ -45,7 +44,7 @@ export const LocalAdapter: WorkspaceAdapter = { const page = blockSuiteWorkspace.createPage({ id: DEFAULT_HELLO_WORLD_PAGE_ID, }); - if (config.enablePreloading) { + if (runtimeConfig.enablePreloading) { initPageWithPreloading(page).catch(err => { logger.error('init page with preloading failed', err); }); diff --git a/apps/web/src/adapters/workspace.ts b/apps/web/src/adapters/workspace.ts index e619ce995f..448e119156 100644 --- a/apps/web/src/adapters/workspace.ts +++ b/apps/web/src/adapters/workspace.ts @@ -1,4 +1,4 @@ -import { Unreachable } from '@affine/env'; +import { Unreachable } from '@affine/env/constant'; import type { AppEvents, WorkspaceUISchema } from '@affine/env/workspace'; import { LoadPriority, diff --git a/apps/web/src/atoms/index.ts b/apps/web/src/atoms/index.ts index c2c3e6787e..959a5d89b8 100644 --- a/apps/web/src/atoms/index.ts +++ b/apps/web/src/atoms/index.ts @@ -1,5 +1,4 @@ import { DebugLogger } from '@affine/debug'; -import { config } from '@affine/env'; import { WorkspaceFlavour, WorkspaceVersion } from '@affine/env/workspace'; import type { RootWorkspaceMetadataV2 } from '@affine/workspace/atom'; import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; @@ -53,7 +52,7 @@ rootWorkspacesMetadataAtom.onMount = setAtom => { }, 0); } - if (environment.isDesktop && config.enableSQLiteProvider) { + if (environment.isDesktop && runtimeConfig.enableSQLiteProvider) { window.apis?.workspace .list() .then(workspaceIDs => { diff --git a/apps/web/src/atoms/public-workspace/index.ts b/apps/web/src/atoms/public-workspace/index.ts index 4ff4d10130..d57dbe9e81 100644 --- a/apps/web/src/atoms/public-workspace/index.ts +++ b/apps/web/src/atoms/public-workspace/index.ts @@ -1,5 +1,4 @@ -import type { BlockSuiteFeatureFlags } from '@affine/env'; -import { config } from '@affine/env'; +import type { BlockSuiteFeatureFlags } from '@affine/env/global'; import type { AffinePublicWorkspace } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace'; import { affineApis } from '@affine/workspace/affine/shared'; @@ -25,7 +24,7 @@ function createPublicWorkspace( blockSuiteWorkspace.doc, new Uint8Array(binary) ); - Object.entries(config.editorFlags).forEach(([key, value]) => { + Object.entries(runtimeConfig.editorFlags).forEach(([key, value]) => { blockSuiteWorkspace.awarenessStore.setFlag( key as keyof BlockSuiteFeatureFlags, value diff --git a/apps/web/src/atoms/root.ts b/apps/web/src/atoms/root.ts index 0bcad3c58c..4223b218c4 100644 --- a/apps/web/src/atoms/root.ts +++ b/apps/web/src/atoms/root.ts @@ -1,6 +1,5 @@ //#region async atoms that to load the real workspace data import { DebugLogger } from '@affine/debug'; -import { config } from '@affine/env'; import type { WorkspaceRegistry } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace'; import { @@ -30,7 +29,7 @@ export const workspacesAtom = atom>( // TODO: remove this when we remove the legacy cloud ) .filter(workspace => - !config.enableLegacyCloud + !runtimeConfig.enableLegacyCloud ? workspace.flavour !== WorkspaceFlavour.AFFINE : true ); diff --git a/apps/web/src/bootstrap/index.ts b/apps/web/src/bootstrap/index.ts index 0516219dbf..d27cfd3716 100644 --- a/apps/web/src/bootstrap/index.ts +++ b/apps/web/src/bootstrap/index.ts @@ -1,5 +1,6 @@ import { migrateToSubdoc } from '@affine/env/blocksuite'; -import { config, setupGlobal } from '@affine/env/config'; +import { isDesktop, isServer } from '@affine/env/constant'; +import { setupGlobal } from '@affine/env/global'; import type { LocalIndexedDBDownloadProvider } from '@affine/env/workspace'; import { WorkspaceFlavour, WorkspaceVersion } from '@affine/env/workspace'; import type { RootWorkspaceMetadata } from '@affine/workspace/atom'; @@ -16,15 +17,19 @@ import { WorkspaceAdapters } from '../adapters/workspace'; setupGlobal(); -if (config.enablePlugin && !environment.isServer) { +if (process.env.NODE_ENV === 'development') { + console.log('Runtime Preset', runtimeConfig); +} + +if (runtimeConfig.enablePlugin && !isServer) { import('@affine/copilot'); } -if (!environment.isServer) { +if (!isServer) { import('@affine/bookmark-block'); } -if (!environment.isDesktop && !environment.isServer) { +if (!isDesktop && !isServer) { // Polyfill Electron const unimplemented = () => { throw new Error('AFFiNE Plugin Web will be supported in the future'); diff --git a/apps/web/src/components/affine/create-workspace-modal/index.tsx b/apps/web/src/components/affine/create-workspace-modal/index.tsx index f95dd3b465..2fc6ae4995 100644 --- a/apps/web/src/components/affine/create-workspace-modal/index.tsx +++ b/apps/web/src/components/affine/create-workspace-modal/index.tsx @@ -8,7 +8,6 @@ import { Tooltip, } from '@affine/component'; import { DebugLogger } from '@affine/debug'; -import { config } from '@affine/env'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { HelpIcon } from '@blocksuite/icons'; import { useSetAtom } from 'jotai'; @@ -291,7 +290,7 @@ export const CreateWorkspaceModal = ({ }); } else if (mode === 'new') { setStep( - environment.isDesktop && config.enableSQLiteProvider + environment.isDesktop && runtimeConfig.enableSQLiteProvider ? 'set-db-location' : 'name-workspace' ); @@ -306,7 +305,7 @@ export const CreateWorkspaceModal = ({ const onConfirmEnableCloudSyncing = useCallback( (enableCloudSyncing: boolean) => { (async function () { - if (!config.enableLegacyCloud && enableCloudSyncing) { + if (!runtimeConfig.enableLegacyCloud && enableCloudSyncing) { setOpenDisableCloudAlertModal(true); } else { let id = addedId; @@ -346,7 +345,7 @@ export const CreateWorkspaceModal = ({ const onConfirmName = useCallback( (name: string) => { setWorkspaceName(name); - if (environment.isDesktop && config.enableSQLiteProvider) { + if (environment.isDesktop && runtimeConfig.enableSQLiteProvider) { setStep('set-syncing-mode'); } else { // this will be the last step for web for now diff --git a/apps/web/src/components/affine/setting-modal/general-setting/about/index.tsx b/apps/web/src/components/affine/setting-modal/general-setting/about/index.tsx index 99383eb2e2..e35dae368f 100644 --- a/apps/web/src/components/affine/setting-modal/general-setting/about/index.tsx +++ b/apps/web/src/components/affine/setting-modal/general-setting/about/index.tsx @@ -1,6 +1,6 @@ import { Switch } from '@affine/component'; import { relatedLinks } from '@affine/component/contact-modal'; -import { env } from '@affine/env'; +import { isDesktop } from '@affine/env/constant'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { ArrowRightSmallIcon, OpenInNewIcon } from '@blocksuite/icons'; import { useCallback } from 'react'; @@ -24,7 +24,7 @@ export const AboutAffine = () => { return ( <> - {IS_EXHIBITION && env.isDesktop ? ( + {IS_EXHIBITION && isDesktop ? ( { - {IS_EXHIBITION && env.isDesktop ? ( + {IS_EXHIBITION && isDesktop ? ( { onChange={checked => changeSwitch('fullWidthLayout', checked)} /> - {IS_EXHIBITION && env.isDesktop ? ( + {IS_EXHIBITION && isDesktop ? ( { ) : null} - {env.isDesktop ? ( + {isDesktop ? ( {t['Enable AFFiNE Cloud']()} - {config.enableLegacyCloud ? ( + {runtimeConfig.enableLegacyCloud ? ( { diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx index 67f9e25c2f..254102d35d 100644 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx +++ b/apps/web/src/components/affine/workspace-setting-detail/panel/export/index.tsx @@ -1,5 +1,4 @@ import { Button, toast, Wrapper } from '@affine/component'; -import { config } from '@affine/env'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { rootCurrentWorkspaceIdAtom } from '@affine/workspace/atom'; import { useAtomValue } from 'jotai'; @@ -13,7 +12,9 @@ export const ExportPanel = () => { - {environment.isDesktop && config.enableSQLiteProvider ? ( + {environment.isDesktop && runtimeConfig.enableSQLiteProvider ? ( ) : null}
@@ -209,7 +208,7 @@ function DesktopClientOnly({ workspaceId }: { workspaceId: string }) { const t = useAFFiNEI18N(); const showOpenFolder = useShowOpenDBFile(workspaceId); const onRevealDBFile = useCallback(() => { - if (environment.isDesktop && config.enableSQLiteProvider) { + if (environment.isDesktop && runtimeConfig.enableSQLiteProvider) { window.apis?.dialog.revealDBFile(workspaceId).catch(err => { console.error(err); }); diff --git a/apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx b/apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx index f96ae5a50e..5d166adbb8 100644 --- a/apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx +++ b/apps/web/src/components/affine/workspace-setting-detail/panel/publish/index.tsx @@ -5,8 +5,7 @@ import { Input, Wrapper, } from '@affine/component'; -import { config } from '@affine/env'; -import { Unreachable } from '@affine/env/constant'; +import { isBrowser, Unreachable } from '@affine/env/constant'; import type { AffineLegacyCloudWorkspace, LocalWorkspace, @@ -38,9 +37,7 @@ const PublishPanelAffine: React.FC = ({ const [origin, setOrigin] = useState(''); useEffect(() => { setOrigin( - typeof window !== 'undefined' && window.location.origin - ? window.location.origin - : '' + isBrowser && window.location.origin ? window.location.origin : '' ); }, []); const shareUrl = origin + '/public-workspace/' + workspace.id; @@ -137,7 +134,7 @@ const PublishPanelLocal: React.FC = ({ > {t['Enable AFFiNE Cloud']()} - {config.enableLegacyCloud ? ( + {runtimeConfig.enableLegacyCloud ? ( { diff --git a/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx b/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx index 2479fffb5d..214ab35674 100644 --- a/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx +++ b/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx @@ -5,7 +5,6 @@ import { PageList, PageListTrashView, } from '@affine/component/page-list'; -import { env } from '@affine/env'; import type { View } from '@affine/env/filter'; import { Trans } from '@affine/i18n'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; @@ -56,8 +55,8 @@ const PageListEmpty = (props: { New Page ); - if (env.isDesktop) { - const shortcut = env.isMacOs ? '⌘ + N' : 'Ctrl + N'; + if (environment.isDesktop) { + const shortcut = environment.isMacOs ? '⌘ + N' : 'Ctrl + N'; return ( Click on the button Or press diff --git a/apps/web/src/components/blocksuite/workspace-header/download-tips.tsx b/apps/web/src/components/blocksuite/workspace-header/download-tips.tsx index 0763df3bc3..4ee3fc554a 100644 --- a/apps/web/src/components/blocksuite/workspace-header/download-tips.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/download-tips.tsx @@ -1,5 +1,5 @@ import { DownloadTips } from '@affine/component/affine-banner'; -import { env } from '@affine/env'; +import { isDesktop } from '@affine/env/constant'; import { useAtom } from 'jotai'; import { useCallback } from 'react'; @@ -13,7 +13,7 @@ export const DownloadClientTip = () => { setShowDownloadClientTips(false); }, [setShowDownloadClientTips]); - if (!showDownloadClientTips || env.isDesktop) { + if (!showDownloadClientTips || isDesktop) { return <>; } return ; diff --git a/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx b/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx index b6fb02a624..fea30809b5 100644 --- a/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/header-right-items/share-menu.tsx @@ -1,5 +1,4 @@ import { ShareMenu } from '@affine/component/share-menu'; -import { config } from '@affine/env'; import { Unreachable } from '@affine/env/constant'; import type { AffineLegacyCloudWorkspace, @@ -110,7 +109,7 @@ const LocalHeaderShareMenu: React.FC = props => { }; export const HeaderShareMenu: React.FC = props => { - if (!config.enableLegacyCloud) { + if (!runtimeConfig.enableLegacyCloud) { return null; } if (props.workspace.flavour === WorkspaceFlavour.AFFINE) { diff --git a/apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx b/apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx index cb83ec878b..ab32a87141 100644 --- a/apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/header-right-items/sync-user.tsx @@ -1,5 +1,4 @@ import { displayFlex, IconButton, styled, Tooltip } from '@affine/component'; -import { config } from '@affine/env'; import type { LocalWorkspace } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; @@ -82,7 +81,7 @@ export const SyncUser = () => { const t = useAFFiNEI18N(); const transformWorkspace = useTransformWorkspace(); - if (!config.enableLegacyCloud) { + if (!runtimeConfig.enableLegacyCloud) { return null; } diff --git a/apps/web/src/components/blocksuite/workspace-header/header.tsx b/apps/web/src/components/blocksuite/workspace-header/header.tsx index ce69a48e7a..7ec44be567 100644 --- a/apps/web/src/components/blocksuite/workspace-header/header.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/header.tsx @@ -4,6 +4,7 @@ import { appSidebarOpenAtom, } from '@affine/component/app-sidebar'; import { SidebarSwitch } from '@affine/component/app-sidebar/sidebar-header'; +import { isBrowser, isDesktop } from '@affine/env/constant'; import { WorkspaceFlavour } from '@affine/env/workspace'; import { CloseIcon, MinusIcon, RoundedRectangleIcon } from '@blocksuite/icons'; import type { Page } from '@blocksuite/store'; @@ -148,7 +149,7 @@ const HeaderRightItems: Record = { ); }, availableWhen: () => { - return environment.isDesktop && environment.isWindows; + return isDesktop && isBrowser; }, }, }; diff --git a/apps/web/src/components/blocksuite/workspace-header/utils.tsx b/apps/web/src/components/blocksuite/workspace-header/utils.tsx index 63c1c65bad..0aadc03e5e 100644 --- a/apps/web/src/components/blocksuite/workspace-header/utils.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/utils.tsx @@ -1,4 +1,4 @@ -import { env } from '@affine/env'; +import { isDesktop } from '@affine/env/constant'; import { Trans } from '@affine/i18n'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import type React from 'react'; @@ -7,18 +7,18 @@ import { useEffect, useState } from 'react'; const minimumChromeVersion = 102; export const shouldShowWarning = () => { - if (env.isDesktop) { + if (isDesktop) { // even though desktop have compatibility issues, we don't want to show the warning return false; } - if (!env.isBrowser) { + if (!environment.isBrowser) { // disable in SSR return false; } - if (env.isChrome) { - return env.chromeVersion < minimumChromeVersion; + if (environment.isChrome) { + return environment.chromeVersion < minimumChromeVersion; } else { - return !env.isMobile; + return !environment.isMobile; } }; @@ -27,9 +27,11 @@ export const OSWarningMessage: React.FC = () => { const [notChrome, setNotChrome] = useState(false); const [notGoodVersion, setNotGoodVersion] = useState(false); useEffect(() => { - setNotChrome(env.isBrowser && !env.isChrome); + setNotChrome(environment.isBrowser && !environment.isChrome); setNotGoodVersion( - env.isBrowser && env.isChrome && env.chromeVersion < minimumChromeVersion + environment.isBrowser && + environment.isChrome && + environment.chromeVersion < minimumChromeVersion ); }, []); diff --git a/apps/web/src/components/pure/footer/index.tsx b/apps/web/src/components/pure/footer/index.tsx index 4297d97e88..571abeb961 100644 --- a/apps/web/src/components/pure/footer/index.tsx +++ b/apps/web/src/components/pure/footer/index.tsx @@ -1,7 +1,6 @@ import { FlexWrapper } from '@affine/component'; import { IconButton } from '@affine/component'; import { Tooltip } from '@affine/component'; -import { config } from '@affine/env'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import type { AccessTokenMessage } from '@affine/workspace/affine/login'; import { CloudWorkspaceIcon, SignOutIcon } from '@blocksuite/icons'; @@ -62,7 +61,7 @@ export const Footer: React.FC = ({ user, onLogin, onLogout }) => {
} onClick={async () => { - if (!config.enableLegacyCloud) { + if (!runtimeConfig.enableLegacyCloud) { setOpen(true); } else { onLogin(); diff --git a/apps/web/src/components/pure/help-island/index.tsx b/apps/web/src/components/pure/help-island/index.tsx index 9645be5c12..ac040766d8 100644 --- a/apps/web/src/components/pure/help-island/index.tsx +++ b/apps/web/src/components/pure/help-island/index.tsx @@ -1,5 +1,4 @@ import { MuiFade, Tooltip } from '@affine/component'; -import { config, env } from '@affine/env'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { CloseIcon, NewIcon, UserGuideIcon } from '@blocksuite/icons'; import { useAtom } from 'jotai'; @@ -28,7 +27,7 @@ const DEFAULT_SHOW_LIST: IslandItemNames[] = [ const DESKTOP_SHOW_LIST: IslandItemNames[] = [...DEFAULT_SHOW_LIST, 'guide']; export type IslandItemNames = 'whatNew' | 'contact' | 'shortcuts' | 'guide'; export const HelpIsland = ({ - showList = env.isDesktop ? DESKTOP_SHOW_LIST : DEFAULT_SHOW_LIST, + showList = environment.isDesktop ? DESKTOP_SHOW_LIST : DEFAULT_SHOW_LIST, }: { showList?: IslandItemNames[]; }) => { @@ -73,7 +72,7 @@ export const HelpIsland = ({ { - window.open(config.changelogUrl, '_blank'); + window.open(runtimeConfig.changelogUrl, '_blank'); }} > diff --git a/apps/web/src/components/pure/quick-search-modal/index.tsx b/apps/web/src/components/pure/quick-search-modal/index.tsx index f6ed37be6e..5ac4fd5bbb 100644 --- a/apps/web/src/components/pure/quick-search-modal/index.tsx +++ b/apps/web/src/components/pure/quick-search-modal/index.tsx @@ -1,5 +1,4 @@ import { Modal, ModalWrapper } from '@affine/component'; -import { env } from '@affine/env'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { Command } from 'cmdk'; import type { NextRouter } from 'next/router'; @@ -26,10 +25,6 @@ import { StyledShortcut, } from './style'; -const isMac = () => { - return env.isBrowser && env.isMacOs; -}; - export type QuickSearchModalProps = { blockSuiteWorkspace: BlockSuiteWorkspace; open: boolean; @@ -149,7 +144,11 @@ export const QuickSearchModal: React.FC = ({ : t['Quick search placeholder']() } /> - {isMac() ? '⌘ + K' : 'Ctrl + K'} + + {environment.isBrowser && environment.isMacOs + ? '⌘ + K' + : 'Ctrl + K'} + (null); - if (config.enableSQLiteProvider && environment.isDesktop) { + if (runtimeConfig.enableSQLiteProvider && environment.isDesktop) { return ( { - if (environment.isDesktop) { + if (isDesktop) { return window.events?.applicationMenu.onNewPageAction(onClickNewPage); } }, [onClickNewPage]); const [sidebarOpen, setSidebarOpen] = useAtom(appSidebarOpenAtom); useEffect(() => { - if (environment.isDesktop && typeof sidebarOpen === 'boolean') { + if (isDesktop && typeof sidebarOpen === 'boolean') { window.apis?.ui.handleSidebarVisibilityChange(sidebarOpen).catch(err => { console.error(err); }); @@ -177,7 +177,7 @@ export const RootAppSidebar = ({ > {t['Settings']()} - {config.enableNewSettingModal ? ( + {runtimeConfig.enableNewSettingModal ? ( } onClick={onOpenSettingModal}> {t['Settings']()} @@ -203,7 +203,7 @@ export const RootAppSidebar = ({ {blockSuiteWorkspace && ( )} - {config.enableLegacyCloud && + {runtimeConfig.enableLegacyCloud && (currentWorkspace?.flavour === WorkspaceFlavour.AFFINE && currentWorkspace.public ? ( - {environment.isDesktop && } + {isDesktop && }
diff --git a/apps/web/src/components/workspace-header.tsx b/apps/web/src/components/workspace-header.tsx index 952e3b36cd..748d003d62 100644 --- a/apps/web/src/components/workspace-header.tsx +++ b/apps/web/src/components/workspace-header.tsx @@ -5,7 +5,6 @@ import { useAllPageSetting, ViewList, } from '@affine/component/page-list'; -import { config } from '@affine/env'; import type { WorkspaceHeaderProps } from '@affine/env/workspace'; import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/env/workspace'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; @@ -40,7 +39,7 @@ export function WorkspaceHeader({ }} />
- {config.enableAllPageFilter && ( + {runtimeConfig.enableAllPageFilter && (
{setting.currentView.id !== NIL || (setting.currentView.id === NIL && diff --git a/apps/web/src/hooks/affine/use-shortcuts.ts b/apps/web/src/hooks/affine/use-shortcuts.ts index 6088b91d08..e94bcf3161 100644 --- a/apps/web/src/hooks/affine/use-shortcuts.ts +++ b/apps/web/src/hooks/affine/use-shortcuts.ts @@ -1,4 +1,3 @@ -import { env } from '@affine/env'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useMemo } from 'react'; @@ -209,21 +208,21 @@ export const useWinMarkdownShortcuts = (): ShortcutTip => { export const useMarkdownShortcuts = (): ShortcutTip => { const macMarkdownShortcuts = useMacMarkdownShortcuts(); const winMarkdownShortcuts = useWinMarkdownShortcuts(); - const isMac = env.isBrowser && env.isMacOs; + const isMac = environment.isBrowser && environment.isMacOs; return isMac ? macMarkdownShortcuts : winMarkdownShortcuts; }; export const usePageShortcuts = (): ShortcutTip => { const macPageShortcuts = useMacPageKeyboardShortcuts(); const winPageShortcuts = useWinPageKeyboardShortcuts(); - const isMac = env.isBrowser && env.isMacOs; + const isMac = environment.isBrowser && environment.isMacOs; return isMac ? macPageShortcuts : winPageShortcuts; }; export const useEdgelessShortcuts = (): ShortcutTip => { const macEdgelessShortcuts = useMacEdgelessKeyboardShortcuts(); const winEdgelessShortcuts = useWinEdgelessKeyboardShortcuts(); - const isMac = env.isBrowser && env.isMacOs; + const isMac = environment.isBrowser && environment.isMacOs; return isMac ? macEdgelessShortcuts : winEdgelessShortcuts; }; @@ -231,7 +230,7 @@ export const useEdgelessShortcuts = (): ShortcutTip => { export const useGeneralShortcuts = (): ShortcutTip => { const macGeneralShortcuts = useMacGeneralKeyboardShortcuts(); const winGeneralShortcuts = useWinGeneralKeyboardShortcuts(); - const isMac = env.isBrowser && env.isMacOs; + const isMac = environment.isBrowser && environment.isMacOs; return isMac ? macGeneralShortcuts : winGeneralShortcuts; }; diff --git a/apps/web/src/hooks/current/use-current-workspace.ts b/apps/web/src/hooks/current/use-current-workspace.ts index 18e04e5eb7..b6f105c4ec 100644 --- a/apps/web/src/hooks/current/use-current-workspace.ts +++ b/apps/web/src/hooks/current/use-current-workspace.ts @@ -1,3 +1,4 @@ +import { isBrowser } from '@affine/env/constant'; import { rootCurrentPageIdAtom, rootCurrentWorkspaceIdAtom, @@ -19,7 +20,7 @@ export function useCurrentWorkspace(): [ currentWorkspace, useCallback( (id: string | null) => { - if (typeof window !== 'undefined' && id) { + if (isBrowser && id) { localStorage.setItem('last_workspace_id', id); } setPageId(null); diff --git a/apps/web/src/layouts/workspace-layout.tsx b/apps/web/src/layouts/workspace-layout.tsx index cac84fbd56..1e4c38d03e 100644 --- a/apps/web/src/layouts/workspace-layout.tsx +++ b/apps/web/src/layouts/workspace-layout.tsx @@ -9,8 +9,8 @@ import { WorkspaceFallback, } from '@affine/component/workspace'; import { DebugLogger } from '@affine/debug'; -import { config, DEFAULT_HELLO_WORLD_PAGE_ID, env } from '@affine/env'; import { initEmptyPage, initPageWithPreloading } from '@affine/env/blocksuite'; +import { DEFAULT_HELLO_WORLD_PAGE_ID, isDesktop } from '@affine/env/constant'; import { WorkspaceFlavour } from '@affine/env/workspace'; import { setUpLanguage, useI18N } from '@affine/i18n'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; @@ -350,7 +350,7 @@ export const WorkspaceLayoutInner: FC = ({ children }) => { id: pageId, }); assertEquals(page.id, pageId); - if (config.enablePreloading) { + if (runtimeConfig.enablePreloading) { initPageWithPreloading(page).catch(error => { console.error('import error:', error); }); @@ -455,7 +455,7 @@ export const WorkspaceLayoutInner: FC = ({ children }) => { ); const t = useAFFiNEI18N(); - const showList: IslandItemNames[] = env.isDesktop + const showList: IslandItemNames[] = isDesktop ? ['whatNew', 'contact', 'guide'] : ['whatNew', 'contact']; diff --git a/apps/web/src/pages/_app.tsx b/apps/web/src/pages/_app.tsx index 2c88f5a0fc..d4109dda3b 100644 --- a/apps/web/src/pages/_app.tsx +++ b/apps/web/src/pages/_app.tsx @@ -5,7 +5,6 @@ import '../bootstrap'; import { AffineContext } from '@affine/component/context'; import { WorkspaceFallback } from '@affine/component/workspace'; -import { config } from '@affine/env'; import { createI18n, I18nextProvider } from '@affine/i18n'; import type { EmotionCache } from '@emotion/cache'; import { CacheProvider } from '@emotion/react'; @@ -42,9 +41,6 @@ const DebugProvider = ({ children }: PropsWithChildren): ReactElement => { }; const i18n = createI18n(); -if (process.env.NODE_ENV === 'development') { - console.log('Runtime Preset', config); -} const App = function App({ Component, diff --git a/apps/web/src/pages/plugins.tsx b/apps/web/src/pages/plugins.tsx index d22e58c1c6..7ea1bde112 100644 --- a/apps/web/src/pages/plugins.tsx +++ b/apps/web/src/pages/plugins.tsx @@ -1,5 +1,4 @@ import { MainContainer } from '@affine/component/workspace'; -import { config } from '@affine/env'; import { NoSsr } from '@mui/material'; import { affinePluginsAtom } from '@toeverything/plugin-infra/manager'; import { useAtomValue } from 'jotai'; @@ -29,7 +28,7 @@ const Plugins = () => { }; export default function PluginPage(): ReactElement { - if (!config.enablePlugin) { + if (!runtimeConfig.enablePlugin) { return <>; } return ( diff --git a/apps/web/src/providers/modal-provider.tsx b/apps/web/src/providers/modal-provider.tsx index 8ff5f7f2ba..cb87cb07da 100644 --- a/apps/web/src/providers/modal-provider.tsx +++ b/apps/web/src/providers/modal-provider.tsx @@ -1,4 +1,3 @@ -import { env } from '@affine/env'; import { WorkspaceSubPath } from '@affine/env/workspace'; import { rootCurrentWorkspaceIdAtom, @@ -69,7 +68,7 @@ export function CurrentWorkspaceModals() { }, [setOpenDisableCloudAlertModal])} /> - {env.isDesktop && ( + {environment.isDesktop && ( (subscriber => { subscriber.next(initialValue); onSubscribe?.(); - if (typeof window === 'undefined' || !env.isDesktop || !event) { + if (!isBrowser || !environment.isDesktop || !event) { subscriber.complete(); return; } diff --git a/packages/component/src/components/app-sidebar/app-updater-button/index.tsx b/packages/component/src/components/app-sidebar/app-updater-button/index.tsx index 26f0f1ac5b..e208f42993 100644 --- a/packages/component/src/components/app-sidebar/app-updater-button/index.tsx +++ b/packages/component/src/components/app-sidebar/app-updater-button/index.tsx @@ -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(); diff --git a/packages/component/src/components/app-sidebar/index.tsx b/packages/component/src/components/app-sidebar/index.tsx index e5fd5009e6..df774b04b6 100644 --- a/packages/component/src/components/app-sidebar/index.tsx +++ b/packages/component/src/components/app-sidebar/index.tsx @@ -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
; @@ -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} diff --git a/packages/component/src/components/app-sidebar/quick-search-input/index.tsx b/packages/component/src/components/app-sidebar/quick-search-input/index.tsx index 3195e3be74..78debff213 100644 --- a/packages/component/src/components/app-sidebar/quick-search-input/index.tsx +++ b/packages/component/src/components/app-sidebar/quick-search-input/index.tsx @@ -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 { +interface QuickSearchInputProps extends HTMLAttributes { 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 (
{ const open = useAtomValue(appSidebarOpenAtom); return (
- {env.isDesktop && ( + {environment.isDesktop && ( <> - {env.isMacOs &&
} + {environment.isMacOs &&
} { - {!env.isMacOs &&
} + {!environment.isMacOs &&
} )} {open && } diff --git a/packages/component/src/components/image-preview-modal/index.jotai.ts b/packages/component/src/components/image-preview-modal/index.jotai.ts index 326d6a4b76..0564f36e09 100644 --- a/packages/component/src/components/image-preview-modal/index.jotai.ts +++ b/packages/component/src/components/image-preview-modal/index.jotai.ts @@ -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(null); export const hasAnimationPlayedAtom = atom(true); previewBlockIdAtom.onMount = set => { - if (typeof window !== 'undefined') { + if (isBrowser) { const callback = (event: CustomEvent) => { set(event.detail.blockId); }; diff --git a/packages/component/src/components/page-list/operation-cell.tsx b/packages/component/src/components/page-list/operation-cell.tsx index 2fefe861b4..e1c874d7fd 100644 --- a/packages/component/src/components/page-list/operation-cell.tsx +++ b/packages/component/src/components/page-list/operation-cell.tsx @@ -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 = ({ > {favorite ? t['Remove from favorites']() : t['Add to Favorites']()} - {!environment.isDesktop && ( + {!isDesktop && ( }> {t['Open in new tab']()} diff --git a/packages/component/src/components/share-menu/share-page.tsx b/packages/component/src/components/share-menu/share-page.tsx index dc3637fa6b..58c9d0b938 100644 --- a/packages/component/src/components/share-menu/share-page.tsx +++ b/packages/component/src/components/share-menu/share-page.tsx @@ -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'; diff --git a/packages/component/src/components/theme-provider/index.tsx b/packages/component/src/components/theme-provider/index.tsx index 097bafd2bb..98a2a7d2ff 100644 --- a/packages/component/src/components/theme-provider/index.tsx +++ b/packages/component/src/components/theme-provider/index.tsx @@ -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 => { diff --git a/packages/component/src/components/workspace/index.tsx b/packages/component/src/components/workspace/index.tsx index 24bbe5a4a7..1c21aed14c 100644 --- a/packages/component/src/components/workspace/index.tsx +++ b/packages/component/src/components/workspace/index.tsx @@ -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 = ({
{ return (
{props.children}
diff --git a/packages/component/tsconfig.json b/packages/component/tsconfig.json index 931fb932b5..dcf7817330 100644 --- a/packages/component/tsconfig.json +++ b/packages/component/tsconfig.json @@ -5,7 +5,8 @@ "compilerOptions": { "composite": true, "noEmit": false, - "outDir": "lib" + "outDir": "lib", + "types": ["@affine/env"] }, "references": [ { diff --git a/packages/env/package.json b/packages/env/package.json index 465bca209d..c0044d3acb 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -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", diff --git a/packages/env/src/__tests__/subdoc-migration.spec.ts b/packages/env/src/__tests__/subdoc-migration.spec.ts index 72dccc6ed4..c2e847cb9e 100644 --- a/packages/env/src/__tests__/subdoc-migration.spec.ts +++ b/packages/env/src/__tests__/subdoc-migration.spec.ts @@ -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]); }); diff --git a/packages/env/src/api.ts b/packages/env/src/api.ts deleted file mode 100644 index 0d03894577..0000000000 --- a/packages/env/src/api.ts +++ /dev/null @@ -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 }; diff --git a/packages/env/src/blocksuite/subdoc-migration.ts b/packages/env/src/blocksuite/subdoc-migration.ts index d48ab2b17a..d73705378b 100644 --- a/packages/env/src/blocksuite/subdoc-migration.ts +++ b/packages/env/src/blocksuite/subdoc-migration.ts @@ -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; 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') { diff --git a/packages/env/src/constant.ts b/packages/env/src/constant.ts index b12f8c4510..113cf72a96 100644 --- a/packages/env/src/constant.ts +++ b/packages/env/src/constant.ts @@ -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'; diff --git a/packages/env/src/env.d.ts b/packages/env/src/env.d.ts deleted file mode 100644 index 62cc8d30f0..0000000000 --- a/packages/env/src/env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-restricted-imports -import '../hooks/src/use-block-suite-page-meta.ts'; diff --git a/packages/env/src/config.ts b/packages/env/src/global.ts similarity index 78% rename from packages/env/src/config.ts rename to packages/env/src/global.ts index e1bdfc3b83..255b395637 100644 --- a/packages/env/src/config.ts +++ b/packages/env/src/global.ts @@ -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 }; diff --git a/packages/env/src/index.ts b/packages/env/src/index.ts deleted file mode 100644 index 0de38f9e82..0000000000 --- a/packages/env/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './api'; -export * from './config'; -export * from './constant'; diff --git a/packages/hooks/src/__tests__/index.spec.ts b/packages/hooks/src/__tests__/index.spec.ts index 31eece5a22..90d63d04e0 100644 --- a/packages/hooks/src/__tests__/index.spec.ts +++ b/packages/hooks/src/__tests__/index.spec.ts @@ -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'; diff --git a/packages/hooks/src/use-block-suite-workspace-name.ts b/packages/hooks/src/use-block-suite-workspace-name.ts index 70e6ad2849..47768e9805 100644 --- a/packages/hooks/src/use-block-suite-workspace-name.ts +++ b/packages/hooks/src/use-block-suite-workspace-name.ts @@ -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'; diff --git a/packages/i18n/package.json b/packages/i18n/package.json index e53cd8a3b3..62cc4630bc 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -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" }, diff --git a/packages/storybook/.storybook/preview.tsx b/packages/storybook/.storybook/preview.tsx index 90cf0ac7f4..4c70a7ce5f 100644 --- a/packages/storybook/.storybook/preview.tsx +++ b/packages/storybook/.storybook/preview.tsx @@ -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].*' }, diff --git a/packages/storybook/tsconfig.node.json b/packages/storybook/tsconfig.node.json index ee58c84424..69d90ecad8 100644 --- a/packages/storybook/tsconfig.node.json +++ b/packages/storybook/tsconfig.node.json @@ -12,5 +12,10 @@ }, "include": [".storybook/**/*"], "exclude": ["lib"], - "references": [{ "path": "../i18n" }] + "references": [ + { "path": "../i18n" }, + { + "path": "../env" + } + ] } diff --git a/packages/workspace/src/affine/api/index.ts b/packages/workspace/src/affine/api/index.ts index 5dbcdbce1c..f8b11d0f3d 100644 --- a/packages/workspace/src/affine/api/index.ts +++ b/packages/workspace/src/affine/api/index.ts @@ -1,4 +1,4 @@ -import { MessageCode, Messages } from '@affine/env'; +import { MessageCode, Messages } from '@affine/env/constant'; import type { AcceptInvitingParams, DeleteWorkspaceParams, diff --git a/packages/workspace/src/affine/keck/index.ts b/packages/workspace/src/affine/keck/index.ts index f4ec74984d..63fb88fcc2 100644 --- a/packages/workspace/src/affine/keck/index.ts +++ b/packages/workspace/src/affine/keck/index.ts @@ -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 { '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 { } 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); diff --git a/packages/workspace/src/affine/login.ts b/packages/workspace/src/affine/login.ts index fddb6cde4d..b115c2ebf0 100644 --- a/packages/workspace/src/affine/login.ts +++ b/packages/workspace/src/affine/login.ts @@ -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); diff --git a/packages/workspace/src/affine/shared.ts b/packages/workspace/src/affine/shared.ts index 0e47e9eb74..229d71ca22 100644 --- a/packages/workspace/src/affine/shared.ts +++ b/packages/workspace/src/affine/shared.ts @@ -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 & ReturnType; + Object.assign(affineApis, createUserApis(prefixUrl)); Object.assign(affineApis, createWorkspaceApis(prefixUrl)); diff --git a/packages/workspace/src/affine/sync.ts b/packages/workspace/src/affine/sync.ts index 6a08165f6b..29502a5f48 100644 --- a/packages/workspace/src/affine/sync.ts +++ b/packages/workspace/src/affine/sync.ts @@ -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 { diff --git a/packages/workspace/src/atom.ts b/packages/workspace/src/atom.ts index 9899ae4a1b..efe7c9bb5a 100644 --- a/packages/workspace/src/atom.ts +++ b/packages/workspace/src/atom.ts @@ -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(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(null); rootCurrentPageIdAtom.onMount = set => { - if (typeof window !== 'undefined') { + if (isBrowser) { const callback = (url: string) => { const value = url.split('/')[3]; if (value) { diff --git a/packages/workspace/src/local/crud.ts b/packages/workspace/src/local/crud.ts index 71635df85c..458639108d 100644 --- a/packages/workspace/src/local/crud.ts +++ b/packages/workspace/src/local/crud.ts @@ -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 = { : []; // 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( diff --git a/packages/workspace/src/providers/index.ts b/packages/workspace/src/providers/index.ts index f95c2e0932..bebfc7fa03 100644 --- a/packages/workspace/src/providers/index.ts +++ b/packages/workspace/src/providers/index.ts @@ -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)); diff --git a/packages/workspace/src/utils.ts b/packages/workspace/src/utils.ts index c5b91f87fb..28f4d3e65a 100644 --- a/packages/workspace/src/utils.ts +++ b/packages/workspace/src/utils.ts @@ -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, diff --git a/scripts/setup/global.ts b/scripts/setup/global.ts new file mode 100644 index 0000000000..b837d55248 --- /dev/null +++ b/scripts/setup/global.ts @@ -0,0 +1,3 @@ +import { setupGlobal } from '@affine/env/global'; + +setupGlobal(); diff --git a/tsconfig.node.json b/tsconfig.node.json index 794276cb6d..c4b3af6e33 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -7,5 +7,10 @@ "allowSyntheticDefaultImports": true, "outDir": "lib" }, - "include": ["vitest.config.ts", "scripts"] + "include": ["vitest.config.ts", "scripts"], + "references": [ + { + "path": "./packages/env" + } + ] } diff --git a/vitest.config.ts b/vitest.config.ts index 9cf317e2a8..5993101e59 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -26,6 +26,7 @@ export default defineConfig({ resolve(rootDir, './scripts/setup/i18n.ts'), resolve(rootDir, './scripts/setup/search.ts'), resolve(rootDir, './scripts/setup/lottie-web.ts'), + resolve(rootDir, './scripts/setup/global.ts'), ], // split tests that include native addons or not include: process.env.NATIVE_TEST diff --git a/yarn.lock b/yarn.lock index 67c26c3adc..de065ca34a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -277,7 +277,6 @@ __metadata: version: 0.0.0-use.local resolution: "@affine/i18n@workspace:packages/i18n" dependencies: - "@affine/debug": "workspace:*" "@types/node": ^18.16.18 "@types/prettier": ^2.7.3 i18next: ^23.2.3