diff --git a/packages/backend/server/src/core/config.ts b/packages/backend/server/src/core/config.ts
index c6e7549058..6940a77aca 100644
--- a/packages/backend/server/src/core/config.ts
+++ b/packages/backend/server/src/core/config.ts
@@ -46,6 +46,7 @@ export class ServerConfigType {
@Field(() => [ServerFeature], { description: 'enabled server features' })
features!: ServerFeature[];
}
+
export class ServerConfigResolver {
@Query(() => ServerConfigType, {
description: 'server config',
diff --git a/packages/backend/server/src/plugins/payment/index.ts b/packages/backend/server/src/plugins/payment/index.ts
index 0539b9fd90..9a4e33578f 100644
--- a/packages/backend/server/src/plugins/payment/index.ts
+++ b/packages/backend/server/src/plugins/payment/index.ts
@@ -17,11 +17,10 @@ import { StripeWebhook } from './webhook';
UserSubscriptionResolver,
],
controllers: [StripeWebhook],
- // TODO(@forehalo): enable this requirements when conditional query is implemented in frontend
- // requires: [
- // 'plugins.payment.stripe.keys.APIKey',
- // 'plugins.payment.stripe.keys.webhookKey',
- // ],
+ requires: [
+ 'plugins.payment.stripe.keys.APIKey',
+ 'plugins.payment.stripe.keys.webhookKey',
+ ],
contributesTo: ServerFeature.Payment,
if: config => config.flavor.graphql,
})
diff --git a/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx b/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx
index 2f148bae68..287042d2af 100644
--- a/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx
+++ b/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx
@@ -34,7 +34,7 @@ import {
openSignOutModalAtom,
} from '../../../../atoms';
import { useCurrentUser } from '../../../../hooks/affine/use-current-user';
-import { useSelfHosted } from '../../../../hooks/affine/use-server-config';
+import { useServerFeatures } from '../../../../hooks/affine/use-server-config';
import { useMutation } from '../../../../hooks/use-mutation';
import { useQuery } from '../../../../hooks/use-query';
import { useUserSubscription } from '../../../../hooks/use-subscription';
@@ -169,7 +169,7 @@ export const AvatarAndName = () => {
const StoragePanel = () => {
const t = useAFFiNEI18N();
- const isSelfHosted = useSelfHosted();
+ const { payment: hasPaymentFeature } = useServerFeatures();
const { data } = useQuery({
query: allBlobSizesQuery,
@@ -205,7 +205,7 @@ const StoragePanel = () => {
plan={plan}
value={data.collectAllBlobSizes.size}
onUpgrade={onUpgrade}
- upgradable={!isSelfHosted}
+ upgradable={hasPaymentFeature}
/>
);
diff --git a/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx b/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx
index fda5ddd85e..029ffed410 100644
--- a/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx
+++ b/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx
@@ -7,7 +7,7 @@ import {
import type { ReactElement, SVGProps } from 'react';
import { useCurrentLoginStatus } from '../../../../hooks/affine/use-current-login-status';
-import { useSelfHosted } from '../../../../hooks/affine/use-server-config';
+import { useServerFeatures } from '../../../../hooks/affine/use-server-config';
import type { GeneralSettingKey } from '../types';
import { AboutAffine } from './about';
import { AppearanceSettings } from './appearance';
@@ -28,7 +28,7 @@ export type GeneralSettingList = GeneralSettingListItem[];
export const useGeneralSettingList = (): GeneralSettingList => {
const t = useAFFiNEI18N();
const status = useCurrentLoginStatus();
- const isSelfHosted = useSelfHosted();
+ const { payment: hasPaymentFeature } = useServerFeatures();
const settings: GeneralSettingListItem[] = [
{
@@ -51,7 +51,7 @@ export const useGeneralSettingList = (): GeneralSettingList => {
},
];
- if (!isSelfHosted) {
+ if (hasPaymentFeature) {
settings.splice(3, 0, {
key: 'plans',
title: t['com.affine.payment.title'](),
diff --git a/packages/frontend/core/src/components/affine/setting-modal/workspace-setting/new-workspace-setting-detail/index.tsx b/packages/frontend/core/src/components/affine/setting-modal/workspace-setting/new-workspace-setting-detail/index.tsx
index 8e9708f18f..2d178dd85e 100644
--- a/packages/frontend/core/src/components/affine/setting-modal/workspace-setting/new-workspace-setting-detail/index.tsx
+++ b/packages/frontend/core/src/components/affine/setting-modal/workspace-setting/new-workspace-setting-detail/index.tsx
@@ -3,7 +3,7 @@ import {
SettingRow,
SettingWrapper,
} from '@affine/component/setting-components';
-import { useSelfHosted } from '@affine/core/hooks/affine/use-server-config';
+import { useServerFeatures } from '@affine/core/hooks/affine/use-server-config';
import { useWorkspace } from '@affine/core/hooks/use-workspace';
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
@@ -20,7 +20,7 @@ import type { WorkspaceSettingDetailProps } from './types';
export const WorkspaceSettingDetail = (props: WorkspaceSettingDetailProps) => {
const t = useAFFiNEI18N();
- const isSelfHosted = useSelfHosted();
+ const { payment: hasPaymentFeature } = useServerFeatures();
const workspaceMetadata = props.workspaceMetadata;
// useWorkspace hook is a vary heavy operation here, but we need syncing name and avatar changes here,
@@ -49,7 +49,7 @@ export const WorkspaceSettingDetail = (props: WorkspaceSettingDetailProps) => {
-
+
{environment.isDesktop && (
diff --git a/packages/frontend/core/src/hooks/affine/use-server-config.ts b/packages/frontend/core/src/hooks/affine/use-server-config.ts
index 1c6f8afdc4..ef0878d1de 100644
--- a/packages/frontend/core/src/hooks/affine/use-server-config.ts
+++ b/packages/frontend/core/src/hooks/affine/use-server-config.ts
@@ -1,4 +1,5 @@
-import { serverConfigQuery, ServerDeploymentType } from '@affine/graphql';
+import type { ServerFeature } from '@affine/graphql';
+import { serverConfigQuery } from '@affine/graphql';
import type { BareFetcher, Middleware } from 'swr';
import { useQueryImmutable } from '../use-query';
@@ -25,20 +26,22 @@ const useServerConfig = () => {
return config.serverConfig;
};
-export const useServerType = () => {
+type LowercaseServerFeature = Lowercase;
+type ServerFeatureRecord = {
+ [key in LowercaseServerFeature]: boolean;
+};
+
+export const useServerFeatures = (): ServerFeatureRecord => {
const config = useServerConfig();
if (!config) {
- return 'local';
+ return {} as ServerFeatureRecord;
}
- return config.type;
-};
-
-export const useSelfHosted = () => {
- const serverType = useServerType();
-
- return ['local', ServerDeploymentType.Selfhosted].includes(serverType);
+ return Array.from(new Set(config.features)).reduce((acc, cur) => {
+ acc[cur.toLowerCase() as LowercaseServerFeature] = true;
+ return acc;
+ }, {} as ServerFeatureRecord);
};
export const useServerBaseUrl = () => {
diff --git a/packages/frontend/core/src/hooks/use-subscription.ts b/packages/frontend/core/src/hooks/use-subscription.ts
index be6a1a0b78..d6c95a8c10 100644
--- a/packages/frontend/core/src/hooks/use-subscription.ts
+++ b/packages/frontend/core/src/hooks/use-subscription.ts
@@ -1,7 +1,7 @@
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { type SubscriptionQuery, subscriptionQuery } from '@affine/graphql';
-import { useSelfHosted } from './affine/use-server-config';
+import { useServerFeatures } from './affine/use-server-config';
import { useQuery } from './use-query';
export type Subscription = NonNullable<
@@ -14,10 +14,10 @@ const selector = (data: SubscriptionQuery) =>
data.currentUser?.subscription ?? null;
export const useUserSubscription = () => {
- const isSelfHosted = useSelfHosted();
- const { data, mutate } = useQuery({
- query: subscriptionQuery,
- });
+ const { payment: hasPaymentFeature } = useServerFeatures();
+ const { data, mutate } = useQuery(
+ hasPaymentFeature ? { query: subscriptionQuery } : undefined
+ );
const set: SubscriptionMutator = useAsyncCallback(
async (update?: Partial) => {
@@ -39,8 +39,8 @@ export const useUserSubscription = () => {
[mutate]
);
- if (isSelfHosted) {
- return [selector(data), () => {}] as const;
+ if (!hasPaymentFeature) {
+ return [null, () => {}] as const;
}
return [selector(data), set] as const;