index.ts 2.3 KB

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