UNPKG

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

156 lines (138 loc) 3.81 kB
import {type SanityClient} from '@sanity/client' import {useMemo} from 'react' import {useObservable} 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' type FeatureAttributes = Record<string, string | number | boolean | null> interface Feature { id: string variantId: string name: string price: number included: boolean attributes: FeatureAttributes } interface FeatureType { id: string name: string singular: boolean features: Feature[] } interface Resource { id: string name: string unit: string type: string quota: number | null custom: boolean overageAllowed: boolean overageChunkSize: number overageChunkPrice: number maxOverageQuota: number | null } interface Plan { id: string planTypeId: string variantId: string | null productType: string variantOfPlanId: string | null name: string variantName: string | null price: number trialDays: number createdAt: string supersededAt: string | null default: boolean public: boolean orderable: boolean isBasePlan: boolean pricingModel: string resources: Record<string, Resource> featureTypes: Record<string, FeatureType> } /** * @internal */ export interface ProjectSubscriptionsResponse { id: string projectId: string productType: string productId: string customerId: string | null planId: string previousSubscriptionId: string | null status: string startedAt: string startedBy: string endedAt: string endedBy: string trialUntil: string | null plan: Plan resources: Record<string, Resource> featureTypes: Record<string, FeatureType> } interface ProjectSubscriptions { error: Error | null projectSubscriptions: ProjectSubscriptionsResponse | null isLoading: boolean } const INITIAL_LOADING_STATE: ProjectSubscriptions = { error: null, projectSubscriptions: null, isLoading: true, } /** * @internal * fetches subscriptions for this project */ function fetchProjectSubscriptions({ versionedClient, }: { versionedClient: SanityClient }): Observable<ProjectSubscriptionsResponse> { return versionedClient.observable.request<ProjectSubscriptionsResponse>({ uri: `/subscriptions/project/${versionedClient.config().projectId}`, tag: 'project-subscriptions', }) } const cachedProjectSubscriptionsRequest = new Map< string, Observable<ProjectSubscriptionsResponse> >() /** @internal */ export function useProjectSubscriptions(): ProjectSubscriptions { const versionedClient = useClient(DEFAULT_STUDIO_CLIENT_OPTIONS) const {projectId} = useSource() if (!cachedProjectSubscriptionsRequest.get(projectId)) { const projectSubscriptions = fetchProjectSubscriptions({versionedClient}).pipe(shareReplay()) cachedProjectSubscriptionsRequest.set(projectId, projectSubscriptions) } const projectSubscriptionsObservable = useMemo(() => { const projectSubscriptions$ = cachedProjectSubscriptionsRequest.get(projectId) if (!projectSubscriptions$) return of<ProjectSubscriptions>({ isLoading: false, error: null, projectSubscriptions: null, }) return projectSubscriptions$.pipe( map((cachedSubscriptions) => ({ isLoading: false, projectSubscriptions: cachedSubscriptions, error: null, })), startWith(INITIAL_LOADING_STATE), catchError((error: Error) => of<ProjectSubscriptions>({ isLoading: false, projectSubscriptions: null, error, }), ), ) }, [projectId]) return useObservable(projectSubscriptionsObservable, INITIAL_LOADING_STATE) }