mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-24 02:39:42 +02:00
Surface the running server build version in the Help popover so self-hosted operators can confirm what's deployed and include it in bug reports. - Backend exposes it via /api/config's server_version (from main.version), omitempty so older/unstamped builds omit the field. - Unstamped "dev" builds are normalized to empty and the row stays hidden. - The row is suppressed on the managed cloud (frontend host multica.ai) and shown only on self-hosted deployments. - Frontend renders a muted footer row in the Help popover only when the value is non-empty; i18n added for en/ja/ko/zh-Hans.
75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
import { createStore } from "zustand/vanilla";
|
|
import { useStore } from "zustand";
|
|
|
|
interface ConfigState {
|
|
cdnDomain: string;
|
|
// True when cdnDomain serves private content via time-bounded signed URLs
|
|
// (CloudFront signing enabled server-side). Renderers must not treat a raw
|
|
// storage URL on that domain as a loadable media source (MUL-3254).
|
|
cdnSigned: boolean;
|
|
allowSignup: boolean;
|
|
googleClientId: string;
|
|
daemonServerUrl: string;
|
|
daemonAppUrl: string;
|
|
// Self-host gate (#3433): when true, every "Create workspace" affordance
|
|
// must be hidden. Defaults to false so unknown / older servers behave like
|
|
// the managed-cloud case.
|
|
workspaceCreationDisabled: boolean;
|
|
featureFlags: Record<string, boolean>;
|
|
// The running API build version, surfaced in the Help popover so
|
|
// self-hosted operators can confirm what's deployed. Empty for dev builds
|
|
// or servers older than this feature.
|
|
serverVersion: string;
|
|
setCdnConfig: (config: { cdnDomain: string; cdnSigned?: boolean }) => void;
|
|
setAuthConfig: (config: {
|
|
allowSignup: boolean;
|
|
googleClientId?: string;
|
|
workspaceCreationDisabled?: boolean;
|
|
}) => void;
|
|
setDaemonConfig: (config: {
|
|
daemonServerUrl?: string;
|
|
daemonAppUrl?: string;
|
|
}) => void;
|
|
setFeatureFlags: (flags?: Record<string, boolean>) => void;
|
|
setServerVersion: (version?: string) => void;
|
|
}
|
|
|
|
export const configStore = createStore<ConfigState>((set) => ({
|
|
cdnDomain: "",
|
|
cdnSigned: false,
|
|
allowSignup: true,
|
|
googleClientId: "",
|
|
daemonServerUrl: "",
|
|
daemonAppUrl: "",
|
|
workspaceCreationDisabled: false,
|
|
featureFlags: {},
|
|
serverVersion: "",
|
|
setCdnConfig: ({ cdnDomain, cdnSigned = false }) => set({ cdnDomain, cdnSigned }),
|
|
setAuthConfig: ({ allowSignup, googleClientId = "", workspaceCreationDisabled = false }) =>
|
|
set({ allowSignup, googleClientId, workspaceCreationDisabled }),
|
|
setDaemonConfig: ({ daemonServerUrl = "", daemonAppUrl = "" }) =>
|
|
set({ daemonServerUrl, daemonAppUrl }),
|
|
setFeatureFlags: (flags = {}) => set({ featureFlags: { ...flags } }),
|
|
setServerVersion: (version = "") => set({ serverVersion: version }),
|
|
}));
|
|
|
|
export function useConfigStore(): ConfigState;
|
|
export function useConfigStore<T>(selector: (state: ConfigState) => T): T;
|
|
export function useConfigStore<T>(selector?: (state: ConfigState) => T) {
|
|
return useStore(configStore, selector as (state: ConfigState) => T);
|
|
}
|
|
|
|
export function featureFlagEnabled(
|
|
flags: Readonly<Record<string, boolean>> | undefined,
|
|
key: string,
|
|
defaultValue = false,
|
|
): boolean {
|
|
return flags?.[key] ?? defaultValue;
|
|
}
|
|
|
|
export function useFeatureEnabled(key: string, defaultValue = false): boolean {
|
|
return useConfigStore((state) =>
|
|
featureFlagEnabled(state.featureFlags, key, defaultValue),
|
|
);
|
|
}
|