import type { PropsWithChildren } from 'react' import { createContext, useCallback, useContext, useMemo } from 'react' import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils' import type { ResponseError } from '@/types' type TableKey = `${string}.${string}` type PoliciesDataContextValue = { getPoliciesForTable: (schema: string, table: string) => Array isPoliciesLoading: boolean isPoliciesError: boolean policiesError?: ResponseError | Error exposedSchemas: Set } const PoliciesDataContext = createContext(null) export const usePoliciesData = () => { const context = useContext(PoliciesDataContext) if (!context) throw new Error('usePoliciesData must be used within PoliciesDataProvider') return context } type PoliciesDataProviderProps = { policies: Array isPoliciesLoading: boolean isPoliciesError: boolean policiesError?: ResponseError | Error exposedSchemas: string[] } export const PoliciesDataProvider = ({ children, policies, isPoliciesLoading, isPoliciesError, policiesError, exposedSchemas, }: PropsWithChildren) => { const policiesByTable = useMemo(() => { const map = new Map>() for (const policy of policies) { const key = `${policy.schema}.${policy.table}` satisfies TableKey const existing = map.get(key) if (existing) { existing.push(policy) } else { map.set(key, [policy]) } } for (const list of map.values()) { list.sort((a, b) => a.name.localeCompare(b.name)) } return map }, [policies]) const getPoliciesForTable = useCallback( (schema: string, table: string) => policiesByTable.get(`${schema}.${table}`) ?? [], [policiesByTable] ) const exposedSchemasSet = useMemo(() => new Set(exposedSchemas), [exposedSchemas]) const contextValue = useMemo( () => ({ getPoliciesForTable, isPoliciesLoading, isPoliciesError, policiesError, exposedSchemas: exposedSchemasSet, }), [getPoliciesForTable, isPoliciesLoading, isPoliciesError, policiesError, exposedSchemasSet] ) return ( {children} ) }