index.ts70 lines · main
1import type { components } from 'api-types'
2
3import enabledFeaturesRaw from './enabled-features.json' with { type: 'json' }
4
5const enabledFeaturesStaticObj = enabledFeaturesRaw as Omit<typeof enabledFeaturesRaw, '$schema'>
6
7type Profile = components['schemas']['ProfileResponse']
8
9export type Feature = Profile['disabled_features'][number] | keyof typeof enabledFeaturesStaticObj
10
11const disabledFeaturesStaticArray = Object.entries(enabledFeaturesStaticObj)
12 .filter(([_, value]) => !value)
13 .map(([key]) => key as Feature)
14
15function checkFeature(feature: Feature, features: Set<Feature>) {
16 return !features.has(feature)
17}
18
19type SnakeToCamelCase<S extends string> = S extends `${infer First}_${infer Rest}`
20 ? `${First}${SnakeToCamelCase<Capitalize<Rest>>}`
21 : S
22
23type FeatureToCamelCase<S extends Feature> = S extends `${infer P}:${infer R}`
24 ? `${SnakeToCamelCase<P>}${Capitalize<SnakeToCamelCase<R>>}`
25 : SnakeToCamelCase<S>
26
27function featureToCamelCase(feature: Feature) {
28 return feature
29 .replace(/:/g, '_')
30 .split('_')
31 .map((word, index) => (index === 0 ? word : word[0].toUpperCase() + word.slice(1)))
32 .join('') as FeatureToCamelCase<typeof feature>
33}
34
35function isFeatureEnabled<T extends Feature[]>(
36 features: T,
37 runtimeDisabledFeatures?: Feature[]
38): { [key in FeatureToCamelCase<T[number]>]: boolean }
39function isFeatureEnabled(features: Feature, runtimeDisabledFeatures?: Feature[]): boolean
40function isFeatureEnabled<T extends Feature | Feature[]>(
41 features: T,
42 runtimeDisabledFeatures?: Feature[]
43) {
44 // Override is used to produce a filtered version of the docs search index
45 // using the same sync setup as our normal search index
46 if (process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL === 'true') {
47 if (Array.isArray(features)) {
48 return Object.fromEntries(features.map((feature) => [featureToCamelCase(feature), false]))
49 }
50 return false
51 }
52
53 const disabledFeatures = new Set([
54 ...(runtimeDisabledFeatures ?? []),
55 ...disabledFeaturesStaticArray,
56 ])
57
58 if (Array.isArray(features)) {
59 return Object.fromEntries(
60 features.map((feature) => [
61 featureToCamelCase(feature),
62 checkFeature(feature, disabledFeatures),
63 ])
64 )
65 }
66
67 return checkFeature(features, disabledFeatures)
68}
69
70export { isFeatureEnabled }