/** * Centralized Query Keys for React Query / TanStack Query * Provides consistent query key management across the application * * Benefits: * - Single source of truth for all query keys * - Easy invalidation and refetching * - Type safety for query keys * - Consistent naming conventions */ // Base query key factory export const createQueryKey = ( entity: string, params?: Record, ) => { return params ? [entity, params] : [entity]; }; // Entity-specific query keys export const queryKeys = { // Auth module auth: { all: () => createQueryKey('auth'), session: () => createQueryKey('auth', { type: 'session' }), user: (id?: string) => createQueryKey('auth', { type: 'user', id }), permissions: () => createQueryKey('auth', { type: 'permissions' }), oauthProviders: () => createQueryKey('auth', { type: 'oauth' }), }, // Users module users: { all: (filters?: Record) => createQueryKey('users', filters), byId: (id: string) => createQueryKey('users', { id }), profile: () => createQueryKey('users', { type: 'profile' }), preferences: () => createQueryKey('users', { type: 'preferences' }), invitations: (status?: string) => createQueryKey('users', { type: 'invitations', status }), }, // Tenants module tenants: { all: () => createQueryKey('tenants'), current: () => createQueryKey('tenants', { type: 'current' }), byId: (id: string) => createQueryKey('tenants', { id }), settings: (tenantId?: string) => createQueryKey('tenants', { type: 'settings', tenantId }), usage: (tenantId?: string) => createQueryKey('tenants', { type: 'usage', tenantId }), }, // Billing module billing: { subscriptions: { all: (status?: string) => createQueryKey('billing', { type: 'subscriptions', status }), current: () => createQueryKey('billing', { type: 'subscription', current: true }), byId: (id: string) => createQueryKey('billing', { type: 'subscription', id }), }, invoices: { all: (filters?: Record) => createQueryKey('billing', { type: 'invoices', ...filters }), byId: (id: string) => createQueryKey('billing', { type: 'invoice', id }), downloadUrl: (id: string) => createQueryKey('billing', { type: 'invoice', id, action: 'download' }), }, payments: { all: (filters?: Record) => createQueryKey('billing', { type: 'payments', ...filters }), byId: (id: string) => createQueryKey('billing', { type: 'payment', id }), }, plans: { all: () => createQueryKey('billing', { type: 'plans' }), byId: (id: string) => createQueryKey('billing', { type: 'plan', id }), features: () => createQueryKey('billing', { type: 'planFeatures' }), }, }, // Notifications module notifications: { all: (filters?: Record) => createQueryKey('notifications', filters), unread: (count?: boolean) => createQueryKey('notifications', { unread: true, count }), preferences: () => createQueryKey('notifications', { type: 'preferences' }), devices: () => createQueryKey('notifications', { type: 'devices' }), }, // Feature Flags module featureFlags: { all: () => createQueryKey('featureFlags'), forUser: (userId: string) => createQueryKey('featureFlags', { userId }), forTenant: (tenantId: string) => createQueryKey('featureFlags', { tenantId }), evaluations: (params?: Record) => createQueryKey('featureFlags', { type: 'evaluations', ...params }), }, // Audit module audit: { logs: (filters?: Record) => createQueryKey('audit', { type: 'logs', ...filters }), activities: (filters?: Record) => createQueryKey('audit', { type: 'activities', ...filters }), summary: (period?: string) => createQueryKey('audit', { type: 'summary', period }), }, // AI module ai: { configs: (tenantId?: string) => createQueryKey('ai', { type: 'configs', tenantId }), usage: (filters?: Record) => createQueryKey('ai', { type: 'usage', ...filters }), models: () => createQueryKey('ai', { type: 'models' }), }, // Storage module storage: { files: (filters?: Record) => createQueryKey('storage', { type: 'files', ...filters }), usage: () => createQueryKey('storage', { type: 'usage' }), uploadUrl: (filename: string) => createQueryKey('storage', { type: 'uploadUrl', filename }), }, // Webhooks module webhooks: { all: () => createQueryKey('webhooks'), byId: (id: string) => createQueryKey('webhooks', { id }), deliveries: (webhookId: string, filters?: Record) => createQueryKey('webhooks', { type: 'deliveries', webhookId, ...filters }), logs: (webhookId: string) => createQueryKey('webhooks', { type: 'logs', webhookId }), }, // RBAC module rbac: { roles: { all: () => createQueryKey('rbac', { type: 'roles' }), byId: (id: string) => createQueryKey('rbac', { type: 'role', id }), permissions: (roleId: string) => createQueryKey('rbac', { type: 'permissions', roleId }), }, permissions: { all: () => createQueryKey('rbac', { type: 'permissions' }), byRole: (roleId: string) => createQueryKey('rbac', { type: 'permissions', roleId }), }, userRoles: (userId?: string) => createQueryKey('rbac', { type: 'userRoles', userId }), }, // WhatsApp module whatsapp: { configs: (tenantId?: string) => createQueryKey('whatsapp', { type: 'configs', tenantId }), messages: (filters?: Record) => createQueryKey('whatsapp', { type: 'messages', ...filters }), templates: () => createQueryKey('whatsapp', { type: 'templates' }), }, } as const; // Type helpers for query keys export type QueryKey = typeof queryKeys[keyof typeof queryKeys]; // Helper functions for common operations export const queryKeyHelpers = { /** * Get all query keys for a module */ getModuleKeys: (module: keyof typeof queryKeys) => { return Object.values(queryKeys[module]); }, /** * Check if a query key matches a pattern */ matches: (queryKey: any[], pattern: any[]): boolean => { return JSON.stringify(queryKey.slice(0, pattern.length)) === JSON.stringify(pattern); }, /** * Extract parameters from a query key */ extractParams: (queryKey: any[]): Record => { const params: Record = {}; if (queryKey.length > 1 && typeof queryKey[1] === 'object') { Object.assign(params, queryKey[1]); } return params; }, }; // Export commonly used combinations export const commonQueryKeys = { // User-specific data userData: (userId: string) => [ ...queryKeys.auth.user(userId), ...queryKeys.users.byId(userId), ...queryKeys.users.preferences(), ], // Tenant-specific data tenantData: (tenantId: string) => [ ...queryKeys.tenants.byId(tenantId), ...queryKeys.tenants.settings(tenantId), ...queryKeys.billing.subscriptions.current(), ...queryKeys.featureFlags.forTenant(tenantId), ], // Dashboard data dashboard: () => [ ...queryKeys.notifications.unread(true), ...queryKeys.audit.summary('7d'), ...queryKeys.billing.invoices.all({ limit: 5 }), ...queryKeys.storage.usage(), ], };