Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/dashboard/src/data/featureflag-query.ts
3606 views
1
/**
2
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import { getPrimaryEmail } from "@gitpod/public-api-common/lib/user-utils";
8
import { useQuery } from "@tanstack/react-query";
9
import { getExperimentsClient } from "../experiments/client";
10
import { useCurrentUser } from "../user-context";
11
import { useCurrentOrg } from "./organizations/orgs-query";
12
import { ClassicPaygSunsetConfig } from "@gitpod/gitpod-protocol/lib/experiments/configcat";
13
14
const defaultClassicPaygSunsetConfig: ClassicPaygSunsetConfig = { enabled: false, exemptedOrganizations: [] };
15
16
const featureFlags = {
17
oidcServiceEnabled: false,
18
// Default to true to enable on gitpod dedicated until ff support is added for dedicated
19
orgGitAuthProviders: true,
20
userGitAuthProviders: false,
21
// Local SSH feature of VS Code Desktop Extension
22
gitpod_desktop_use_local_ssh_proxy: false,
23
enabledOrbitalDiscoveries: "",
24
// dummy specified dataops feature, default false
25
dataops: false,
26
enable_multi_org: false,
27
showBrowserExtensionPromotion: false,
28
enable_experimental_jbtb: false,
29
enabled_configuration_prebuild_full_clone: false,
30
enterprise_onboarding_enabled: false,
31
commit_annotation_setting_enabled: false,
32
classic_payg_sunset_enabled: defaultClassicPaygSunsetConfig,
33
};
34
35
type FeatureFlags = typeof featureFlags;
36
37
// Helper to parse JSON feature flags
38
function parseFeatureFlagValue<T>(flagName: string, rawValue: any, defaultValue: T): T {
39
// Special handling for JSON-based feature flags
40
if (flagName === "classic_payg_sunset_enabled") {
41
try {
42
if (typeof rawValue === "string") {
43
return JSON.parse(rawValue) as T;
44
}
45
// If it's already an object, return as-is
46
if (typeof rawValue === "object" && rawValue !== null) {
47
return rawValue as T;
48
}
49
} catch (error) {
50
console.error(`Failed to parse feature flag ${flagName}:`, error);
51
return defaultValue;
52
}
53
}
54
return rawValue;
55
}
56
57
export const useFeatureFlag = <K extends keyof FeatureFlags>(featureFlag: K): FeatureFlags[K] | boolean => {
58
const user = useCurrentUser();
59
const org = useCurrentOrg().data;
60
61
const queryKey = ["featureFlag", featureFlag, user?.id || "", org?.id || ""];
62
63
const query = useQuery(queryKey, async () => {
64
const defaultValue = featureFlags[featureFlag];
65
// For JSON flags, send stringified default to ConfigCat
66
const configCatDefault =
67
featureFlag === "classic_payg_sunset_enabled" ? JSON.stringify(defaultValue) : defaultValue;
68
69
const rawValue = await getExperimentsClient().getValueAsync(featureFlag, configCatDefault, {
70
user: user && {
71
id: user.id,
72
email: getPrimaryEmail(user),
73
},
74
teamId: org?.id,
75
teamName: org?.name,
76
gitpodHost: window.location.host,
77
});
78
79
return parseFeatureFlagValue(featureFlag, rawValue, defaultValue);
80
});
81
82
return query.data !== undefined ? query.data : featureFlags[featureFlag];
83
};
84
85
export const useIsDataOps = () => {
86
return useFeatureFlag("dataops");
87
};
88
89