react-antd-admin-panel
Version:
Modern TypeScript-first React admin panel builder with Ant Design 6
1 lines • 17.1 kB
Source Map (JSON)
{"version":3,"file":"MainContext-DBk-_ISe.cjs","sources":["../src/main/Store.ts","../src/main/UserState.ts","../src/main/MainContext.tsx"],"sourcesContent":["import type { Store as IStore, StateUpdater } from '../types';\n\ntype Subscriber<T = any> = (value: T) => void;\n\n/**\n * Global Store - Reactive key-value store for application state\n * Supports subscriptions for reactive updates\n * \n * @example\n * const store = new GlobalStore();\n * store.set('theme', 'dark');\n * store.subscribe('theme', (theme) => console.log('Theme changed:', theme));\n * store.get<string>('theme'); // 'dark'\n */\nexport class GlobalStore implements IStore {\n private _data: Map<string, any> = new Map();\n private _subscribers: Map<string, Set<Subscriber>> = new Map();\n\n /**\n * Get a value from the store\n */\n get<T = any>(key: string): T | undefined {\n return this._data.get(key);\n }\n\n /**\n * Set a value in the store\n * Notifies all subscribers of the change\n */\n set<T = any>(key: string, value: T | StateUpdater<T>): void {\n const prevValue = this._data.get(key);\n const newValue = typeof value === 'function' \n ? (value as StateUpdater<T>)(prevValue)\n : value;\n \n this._data.set(key, newValue);\n this._notifySubscribers(key, newValue);\n }\n\n /**\n * Remove a value from the store\n */\n remove(key: string): void {\n this._data.delete(key);\n this._notifySubscribers(key, undefined);\n }\n\n /**\n * Clear all values from the store\n */\n clear(): void {\n const keys = Array.from(this._data.keys());\n this._data.clear();\n keys.forEach(key => this._notifySubscribers(key, undefined));\n }\n\n /**\n * Check if a key exists in the store\n */\n has(key: string): boolean {\n return this._data.has(key);\n }\n\n /**\n * Get all keys in the store\n */\n keys(): string[] {\n return Array.from(this._data.keys());\n }\n\n /**\n * Subscribe to changes for a specific key\n * Returns an unsubscribe function\n */\n subscribe<T = any>(key: string, callback: Subscriber<T>): () => void {\n if (!this._subscribers.has(key)) {\n this._subscribers.set(key, new Set());\n }\n this._subscribers.get(key)!.add(callback);\n\n // Return unsubscribe function\n return () => {\n const subscribers = this._subscribers.get(key);\n if (subscribers) {\n subscribers.delete(callback);\n if (subscribers.size === 0) {\n this._subscribers.delete(key);\n }\n }\n };\n }\n\n /**\n * Notify all subscribers of a value change\n */\n private _notifySubscribers(key: string, value: any): void {\n const subscribers = this._subscribers.get(key);\n if (subscribers) {\n subscribers.forEach(callback => callback(value));\n }\n }\n\n /**\n * Get the store as a plain object\n */\n toObject(): Record<string, any> {\n return Object.fromEntries(this._data);\n }\n}\r\n","import type { User } from '../types';\n\ntype UserSubscriber = (user: User | null) => void;\n\n/**\n * UserState - Manages authenticated user state\n * Provides reactive user context with subscriptions\n * \n * @example\n * const userState = new UserState();\n * userState.set({ id: 1, name: 'John', email: 'john@example.com', role: 'admin' });\n * userState.subscribe((user) => console.log('User changed:', user));\n * userState.hasPermission('users.create');\n */\nexport class UserState {\n private _user: User | null = null;\n private _subscribers: Set<UserSubscriber> = new Set();\n\n /**\n * Get the current user\n */\n get(): User | null {\n return this._user;\n }\n\n /**\n * Set the current user\n */\n set(user: User | null): void {\n this._user = user;\n this._notifySubscribers();\n }\n\n /**\n * Update user properties\n */\n update(updates: Partial<User>): void {\n if (this._user) {\n this._user = { ...this._user, ...updates };\n this._notifySubscribers();\n }\n }\n\n /**\n * Clear the current user (logout)\n */\n clear(): void {\n this._user = null;\n this._notifySubscribers();\n }\n\n /**\n * Check if a user is authenticated\n */\n isAuthenticated(): boolean {\n return this._user !== null;\n }\n\n /**\n * Check if user has a specific role\n */\n hasRole(role: string): boolean {\n return this._user?.role === role;\n }\n\n /**\n * Check if user has any of the specified roles\n */\n hasAnyRole(roles: string[]): boolean {\n return roles.includes(this._user?.role ?? '');\n }\n\n /**\n * Check if user has a specific permission\n */\n hasPermission(permission: string): boolean {\n return this._user?.permissions?.includes(permission) ?? false;\n }\n\n /**\n * Check if user has all specified permissions\n */\n hasAllPermissions(permissions: string[]): boolean {\n if (!this._user?.permissions) return false;\n return permissions.every(p => this._user!.permissions!.includes(p));\n }\n\n /**\n * Check if user has any of the specified permissions\n */\n hasAnyPermission(permissions: string[]): boolean {\n if (!this._user?.permissions) return false;\n return permissions.some(p => this._user!.permissions!.includes(p));\n }\n\n /**\n * Get a user property\n */\n getProperty<K extends keyof User>(key: K): User[K] | undefined {\n return this._user?.[key];\n }\n\n /**\n * Subscribe to user changes\n * Returns an unsubscribe function\n */\n subscribe(callback: UserSubscriber): () => void {\n this._subscribers.add(callback);\n return () => {\n this._subscribers.delete(callback);\n };\n }\n\n /**\n * Notify all subscribers\n */\n private _notifySubscribers(): void {\n this._subscribers.forEach(callback => callback(this._user));\n }\n}\r\n","import React from 'react';\nimport type { MainInstance, MainConfig } from './types';\nimport { GlobalStore } from './Store';\nimport { UserState } from './UserState';\nimport { Get } from '../http/Get';\nimport { Post } from '../http/Post';\n\n/**\n * Main context for accessing app instance throughout the component tree\n */\nexport const MainContext = React.createContext<MainInstance | null>(null);\n\n/**\n * Hook to access the Main instance\n */\nexport function useMain(): MainInstance {\n const context = React.useContext(MainContext);\n if (!context) {\n throw new Error('useMain must be used within a MainProvider');\n }\n return context;\n}\n\n/**\n * Hook to access the current user\n */\nexport function useUser() {\n const main = useMain();\n const [user, setUser] = React.useState(main.User().get());\n\n React.useEffect(() => {\n return main.User().subscribe(setUser);\n }, [main]);\n\n return user;\n}\n\n/**\n * Hook to access a store value\n */\nexport function useStore<T = any>(key: string): T | undefined {\n const main = useMain();\n const [value, setValue] = React.useState<T | undefined>(main.Store().get(key));\n\n React.useEffect(() => {\n return main.Store().subscribe<T>(key, setValue);\n }, [main, key]);\n\n return value;\n}\n\n/**\n * Hook to set store values\n */\nexport function useStoreActions() {\n const main = useMain();\n return {\n set: <T,>(key: string, value: T) => main.Store().set(key, value),\n remove: (key: string) => main.Store().remove(key),\n clear: () => main.Store().clear(),\n };\n}\n\ninterface MainProviderProps {\n config: MainConfig;\n navigate: (path: string) => void;\n children: React.ReactNode;\n}\n\n/**\n * MainProvider - Provides the Main context to the application\n */\nexport function MainProvider({ config, navigate, children }: MainProviderProps): React.ReactElement {\n // Create stable instances\n const storeRef = React.useRef<GlobalStore>(new GlobalStore());\n const userStateRef = React.useRef<UserState>(new UserState());\n const [booted, setBooted] = React.useState(false);\n const [bootError, setBootError] = React.useState<Error | null>(null);\n\n // Create the main instance\n const mainInstance = React.useMemo<MainInstance>(() => ({\n User: () => userStateRef.current,\n Store: () => storeRef.current,\n config: config.config,\n navigate,\n canAccess: (route) => {\n const user = userStateRef.current;\n \n // Check required role\n if (route.requiredRole && !user.hasRole(route.requiredRole)) {\n return false;\n }\n \n // Check required permissions\n if (route.requiredPermissions && !user.hasAllPermissions(route.requiredPermissions)) {\n return false;\n }\n \n return true;\n },\n }), [config.config, navigate]);\n\n // Configure HTTP on mount\n React.useEffect(() => {\n const httpConfig = config.config.http;\n if (httpConfig) {\n Get.configure({\n baseURL: httpConfig.baseURL || config.config.pathToApi,\n timeout: httpConfig.timeout,\n headers: httpConfig.headers,\n });\n Post.configure({\n baseURL: httpConfig.baseURL || config.config.pathToApi,\n timeout: httpConfig.timeout,\n headers: httpConfig.headers,\n });\n\n // Set up interceptors if provided\n if (httpConfig.onRequest || httpConfig.onResponse || httpConfig.onError || httpConfig.onUnauthorized) {\n const axios = Get.getAxios();\n \n if (httpConfig.onRequest) {\n axios.interceptors.request.use(httpConfig.onRequest);\n }\n \n if (httpConfig.onResponse || httpConfig.onError || httpConfig.onUnauthorized) {\n axios.interceptors.response.use(\n httpConfig.onResponse,\n (error) => {\n if (error.response?.status === 401 && httpConfig.onUnauthorized) {\n httpConfig.onUnauthorized();\n }\n if (httpConfig.onError) {\n return httpConfig.onError(error);\n }\n return Promise.reject(error);\n }\n );\n }\n }\n }\n }, [config.config.http, config.config.pathToApi]);\n\n // Run boot sequence\n React.useEffect(() => {\n const runBoot = async () => {\n try {\n if (config.config.boot) {\n await config.config.boot(mainInstance);\n }\n setBooted(true);\n } catch (error) {\n setBootError(error as Error);\n }\n };\n\n runBoot();\n }, [config.config.boot, mainInstance]);\n\n // Show loading or error during boot\n if (bootError) {\n return React.createElement('div', {\n style: { \n display: 'flex', \n justifyContent: 'center', \n alignItems: 'center', \n height: '100vh',\n flexDirection: 'column',\n gap: 16,\n },\n },\n React.createElement('h2', {}, 'Application Error'),\n React.createElement('p', { style: { color: 'red' } }, bootError.message),\n );\n }\n\n if (!booted && config.config.boot) {\n return React.createElement('div', {\n style: { \n display: 'flex', \n justifyContent: 'center', \n alignItems: 'center', \n height: '100vh',\n },\n },\n React.createElement('span', {}, 'Loading...'),\n );\n }\n\n return React.createElement(\n MainContext.Provider,\n { value: mainInstance },\n children,\n );\n}\r\n"],"names":["Get","Post"],"mappings":"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"}