useCustomContent.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. import customContentRaw from './custom-content.json'
  2. import { CustomContentTypes } from './CustomContent.types'
  3. // [Joshen] See if we can de-dupe any of the logic here with enabled-features
  4. // For now just getting something working going first
  5. // Also not sure if CustomContentTypes is the right way to go here with trying to dynamically type
  6. const customContentStaticObj = customContentRaw as Omit<typeof customContentRaw, '$schema'>
  7. type CustomContent = keyof typeof customContentStaticObj
  8. type SnakeToCamelCase<S extends string> = S extends `${infer First}_${infer Rest}`
  9. ? `${First}${SnakeToCamelCase<Capitalize<Rest>>}`
  10. : S
  11. type CustomContentToCamelCase<S extends CustomContent> = S extends `${infer P}:${infer R}`
  12. ? `${SnakeToCamelCase<P>}${Capitalize<SnakeToCamelCase<R>>}`
  13. : SnakeToCamelCase<S>
  14. function contentToCamelCase(feature: CustomContent) {
  15. return feature
  16. .replace(/:/g, '_')
  17. .split('_')
  18. .map((word, index) => (index === 0 ? word : word[0].toUpperCase() + word.slice(1)))
  19. .join('') as CustomContentToCamelCase<typeof feature>
  20. }
  21. export const useCustomContent = <T extends CustomContent[]>(
  22. contents: T
  23. ): {
  24. [key in CustomContentToCamelCase<T[number]>]:
  25. | CustomContentTypes[CustomContentToCamelCase<T[number]>]
  26. | null
  27. } => {
  28. // [Joshen] Running into some TS errors without the `as` here - must be overlooking something super simple
  29. return Object.fromEntries(
  30. contents.map((content) => [contentToCamelCase(content), customContentStaticObj[content]])
  31. ) as {
  32. [key in CustomContentToCamelCase<T[number]>]:
  33. | CustomContentTypes[CustomContentToCamelCase<T[number]>]
  34. | null
  35. }
  36. }