sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
68 lines (57 loc) • 1.86 kB
text/typescript
import {type SanityClient} from '@sanity/client'
import {useMemoObservable} from 'react-rx'
import {type Observable, of} from 'rxjs'
import {catchError, map, shareReplay, startWith} from 'rxjs/operators'
import {useSource} from '../studio'
import {DEFAULT_STUDIO_CLIENT_OPTIONS} from '../studioClient'
import {useClient} from './useClient'
const EMPTY_ARRAY: [] = []
interface Features {
enabled: boolean
error: Error | null
features: string[]
isLoading: boolean
}
const INITIAL_LOADING_STATE: Features = {
enabled: true,
error: null,
features: EMPTY_ARRAY,
isLoading: true,
}
/**
* fetches all the enabled features for this project
*/
function fetchFeatures({versionedClient}: {versionedClient: SanityClient}): Observable<string[]> {
return versionedClient.observable.request<string[]>({
uri: `/features`,
tag: 'features',
})
}
const cachedFeatureRequest = new Map<string, Observable<string[]>>()
/** @internal */
export function useFeatureEnabled(featureKey: string): Features {
const versionedClient = useClient(DEFAULT_STUDIO_CLIENT_OPTIONS)
const {projectId} = useSource()
if (!cachedFeatureRequest.get(projectId)) {
const features = fetchFeatures({versionedClient}).pipe(shareReplay())
cachedFeatureRequest.set(projectId, features)
}
const featureInfo = useMemoObservable(
() =>
(cachedFeatureRequest.get(projectId) || of(EMPTY_ARRAY)).pipe(
map((features = []) => ({
isLoading: false,
enabled: Boolean(features?.includes(featureKey)),
features,
error: null,
})),
startWith(INITIAL_LOADING_STATE),
catchError((error: Error) => {
return of({isLoading: false, enabled: false, features: EMPTY_ARRAY, error})
}),
),
[featureKey, projectId],
INITIAL_LOADING_STATE,
)
return featureInfo
}