useCheckEntitlements.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { useCallback, useMemo } from 'react'
  2. import { useSelectedOrganizationQuery } from './useSelectedOrganization'
  3. import type {
  4. Entitlement,
  5. EntitlementConfig,
  6. EntitlementType,
  7. FeatureKey,
  8. } from '@/data/entitlements/entitlements-query'
  9. import { useEntitlementsQuery } from '@/data/entitlements/entitlements-query'
  10. import { IS_PLATFORM } from '@/lib/constants'
  11. function isNumericConfig(
  12. _config: EntitlementConfig,
  13. type: EntitlementType
  14. ): _config is { enabled: boolean; unlimited: boolean; value: number } {
  15. return type === 'numeric'
  16. }
  17. function isSetConfig(
  18. _config: EntitlementConfig,
  19. type: EntitlementType
  20. ): _config is { enabled: boolean; set: string[] } {
  21. return type === 'set'
  22. }
  23. function getEntitlementNumericValue(entitlement: Entitlement | null): number | undefined {
  24. const entitlementConfig = entitlement?.config
  25. return entitlementConfig &&
  26. entitlement.type &&
  27. isNumericConfig(entitlementConfig, entitlement.type)
  28. ? entitlementConfig.value
  29. : undefined
  30. }
  31. function isEntitlementUnlimited(entitlement: Entitlement | null): boolean {
  32. const entitlementConfig = entitlement?.config
  33. return entitlementConfig &&
  34. entitlement.type &&
  35. isNumericConfig(entitlementConfig, entitlement.type)
  36. ? entitlementConfig.unlimited
  37. : false
  38. }
  39. function getEntitlementSetValues(entitlement: Entitlement | null): string[] {
  40. const entitlementConfig = entitlement?.config
  41. return entitlementConfig && entitlement.type && isSetConfig(entitlementConfig, entitlement.type)
  42. ? entitlementConfig.set
  43. : []
  44. }
  45. function getEntitlementMax(entitlement: Entitlement | null): number | undefined {
  46. return isEntitlementUnlimited(entitlement)
  47. ? Number.MAX_SAFE_INTEGER
  48. : getEntitlementNumericValue(entitlement)
  49. }
  50. export function useHasEntitlementAccess(organizationSlug?: string) {
  51. const shouldGetSelectedOrg = !organizationSlug
  52. const { data: selectedOrg } = useSelectedOrganizationQuery({
  53. enabled: shouldGetSelectedOrg,
  54. })
  55. const finalOrgSlug = organizationSlug || selectedOrg?.slug
  56. const enabled = IS_PLATFORM && !!finalOrgSlug
  57. const { data: entitlementsData } = useEntitlementsQuery({ slug: finalOrgSlug! }, { enabled })
  58. return useCallback(
  59. (key: string) =>
  60. IS_PLATFORM
  61. ? (entitlementsData?.entitlements.find((e) => e.feature.key === key)?.hasAccess ?? false)
  62. : true,
  63. [entitlementsData]
  64. )
  65. }
  66. export function useCheckEntitlements(
  67. featureKey: FeatureKey,
  68. organizationSlug?: string,
  69. options?: {
  70. enabled?: boolean
  71. }
  72. ) {
  73. // If no organizationSlug provided, try to get it from the selected organization
  74. const shouldGetSelectedOrg = !organizationSlug && options?.enabled !== false
  75. const {
  76. data: selectedOrg,
  77. isPending: isLoadingSelectedOrg,
  78. isSuccess: isSuccessSelectedOrg,
  79. } = useSelectedOrganizationQuery({
  80. enabled: shouldGetSelectedOrg,
  81. })
  82. const finalOrgSlug = organizationSlug || selectedOrg?.slug
  83. const enabled = IS_PLATFORM ? options?.enabled !== false && !!finalOrgSlug : false
  84. const {
  85. data: entitlementsData,
  86. isPending: isLoadingEntitlements,
  87. isSuccess: isSuccessEntitlements,
  88. } = useEntitlementsQuery({ slug: finalOrgSlug! }, { enabled })
  89. const { entitlement } = useMemo((): {
  90. entitlement: Entitlement | null
  91. } => {
  92. // If no organization slug, no access
  93. if (!finalOrgSlug) return { entitlement: null }
  94. const entitlement = entitlementsData?.entitlements.find(
  95. (entitlement) => entitlement.feature.key === featureKey
  96. )
  97. return {
  98. entitlement: entitlement ?? null,
  99. }
  100. }, [entitlementsData, featureKey, finalOrgSlug])
  101. const isLoading = shouldGetSelectedOrg
  102. ? isLoadingSelectedOrg || isLoadingEntitlements
  103. : isLoadingEntitlements
  104. const isSuccess = shouldGetSelectedOrg
  105. ? isSuccessSelectedOrg && isSuccessEntitlements
  106. : isSuccessEntitlements
  107. return {
  108. hasAccess: IS_PLATFORM ? (entitlement?.hasAccess ?? false) : true,
  109. isLoading: IS_PLATFORM ? isLoading : false,
  110. isSuccess: IS_PLATFORM ? isSuccess : true,
  111. getEntitlementNumericValue: () => getEntitlementNumericValue(entitlement),
  112. isEntitlementUnlimited: () => isEntitlementUnlimited(entitlement),
  113. getEntitlementSetValues: () => getEntitlementSetValues(entitlement),
  114. getEntitlementMax: () => getEntitlementMax(entitlement),
  115. }
  116. }