UNPKG

@dbs-portal/tool-mock

Version:

API mocking toolkit using MSW for DBS Portal development workflows

333 lines 9.74 kB
/** * Zustand integration for mock state management */ import { isMswSetup } from '../core/setup'; /** * Create mock-aware Zustand store */ export function createMockStore(config) { const { name, initialState, mockData, actions = {}, persist = false, storageKey } = config; // Merge initial state with mock data if mocking is enabled const finalInitialState = isMswSetup() && mockData ? { ...initialState, ...mockData } : initialState; // Create store implementation (simplified) let state = { ...finalInitialState }; const listeners = new Set(); const store = { getState: () => state, setState: (partial) => { const nextState = typeof partial === 'function' ? partial(state) : partial; state = { ...state, ...nextState }; // Notify listeners listeners.forEach(listener => listener()); // Persist if enabled if (persist && storageKey) { try { localStorage.setItem(storageKey, JSON.stringify(state)); } catch (error) { console.warn(`Failed to persist store ${name}:`, error); } } }, subscribe: (listener) => { listeners.add(listener); return () => listeners.delete(listener); }, destroy: () => { listeners.clear(); if (persist && storageKey) { try { localStorage.removeItem(storageKey); } catch (error) { console.warn(`Failed to clear persisted store ${name}:`, error); } } }, // Add mock actions ...Object.entries(actions).reduce((acc, [actionName, actionFn]) => { acc[actionName] = (...args) => { const result = actionFn(...args); // If action returns state update, apply it if (result && typeof result === 'object') { store.setState(result); } return result; }; return acc; }, {}), }; // Load persisted state if available if (persist && storageKey) { try { const persisted = localStorage.getItem(storageKey); if (persisted) { const persistedState = JSON.parse(persisted); state = { ...state, ...persistedState }; } } catch (error) { console.warn(`Failed to load persisted store ${name}:`, error); } } return store; } /** * Mock store manager */ export class MockStoreManager { stores = new Map(); // private _config: ZustandIntegrationConfig // Unused for now constructor(_config = {}) { // this._config = config // Unused for now } /** * Register a mock store */ registerStore(name, storeConfig) { const store = createMockStore({ ...storeConfig, name }); this.stores.set(name, store); return store; } /** * Get registered store */ getStore(name) { return this.stores.get(name); } /** * Update store state */ updateStore(name, update) { const store = this.stores.get(name); if (store) { store.setState(update); } } /** * Reset store to initial state */ resetStore(name) { const store = this.stores.get(name); if (store && store.reset) { store.reset(); } } /** * Clear all stores */ clearAllStores() { this.stores.forEach(store => { if (store.destroy) { store.destroy(); } }); this.stores.clear(); } /** * Get all store names */ getStoreNames() { return Array.from(this.stores.keys()); } /** * Apply global mock state */ applyGlobalMockState(globalState) { if (!isMswSetup()) return; Object.entries(globalState).forEach(([storeName, stateUpdate]) => { this.updateStore(storeName, stateUpdate); }); } } /** * Create mock store hooks for React */ export function createMockStoreHooks(store) { return { /** * Use store hook */ useStore: (selector) => { // Simplified implementation - in real scenario would use React hooks const state = store.getState(); return selector ? selector(state) : state; }, /** * Use store actions */ useStoreActions: () => { return Object.keys(store) .filter(key => typeof store[key] === 'function' && key !== 'getState' && key !== 'setState' && key !== 'subscribe') .reduce((actions, actionName) => { actions[actionName] = store[actionName]; return actions; }, {}); }, }; } /** * Mock data providers for common store patterns */ export const mockStoreProviders = { /** * User store mock data */ userStore: { initialState: { currentUser: null, isAuthenticated: false, loading: false, error: null, }, mockData: { currentUser: { id: '1', email: 'user@example.com', firstName: 'Mock', lastName: 'User', roles: ['user'], }, isAuthenticated: true, }, actions: { login: (credentials) => ({ currentUser: { id: '1', email: credentials.email, firstName: 'Mock', lastName: 'User', }, isAuthenticated: true, loading: false, error: null, }), logout: () => ({ currentUser: null, isAuthenticated: false, loading: false, error: null, }), }, }, /** * UI store mock data */ uiStore: { initialState: { sidebarOpen: true, theme: 'light', notifications: [], loading: false, }, mockData: { notifications: [ { id: '1', type: 'info', message: 'Mock notification', timestamp: new Date().toISOString(), }, ], }, actions: { toggleSidebar: () => (state) => ({ sidebarOpen: !state.sidebarOpen, }), setTheme: (theme) => ({ theme }), addNotification: (notification) => (state) => ({ notifications: [...state.notifications, notification], }), }, }, /** * Data store mock data */ dataStore: { initialState: { items: [], loading: false, error: null, pagination: { page: 1, pageSize: 10, total: 0, }, }, mockData: { items: Array.from({ length: 5 }, (_, i) => ({ id: `item-${i + 1}`, name: `Mock Item ${i + 1}`, description: `Description for mock item ${i + 1}`, createdAt: new Date().toISOString(), })), pagination: { page: 1, pageSize: 10, total: 5, }, }, actions: { setItems: (items) => ({ items }), addItem: (item) => (state) => ({ items: [...state.items, item], }), removeItem: (id) => (state) => ({ items: state.items.filter((item) => item.id !== id), }), setLoading: (loading) => ({ loading }), setError: (error) => ({ error }), }, }, }; /** * Setup mock stores for development */ export function setupMockStores(storeConfigs = {}) { const manager = new MockStoreManager(); // Register provided store configs Object.entries(storeConfigs).forEach(([name, config]) => { manager.registerStore(name, config); }); // Register default mock stores if none provided if (Object.keys(storeConfigs).length === 0) { Object.entries(mockStoreProviders).forEach(([name, config]) => { manager.registerStore(name, { ...config, name }); }); } return manager; } /** * Integration with existing Zustand stores */ export function integrateMockWithZustand(existingStore, mockData, options = {}) { if (!isMswSetup()) { return existingStore; } const { override = false, merge = true } = options; if (override) { // Replace store state entirely existingStore.setState(mockData); } else if (merge) { // Merge mock data with existing state const currentState = existingStore.getState(); existingStore.setState({ ...currentState, ...mockData }); } return existingStore; } /** * Mock store devtools integration */ export function setupMockStoreDevtools(stores) { if (typeof window !== 'undefined' && isMswSetup()) { // Add mock store information to window for debugging ; window.__MOCK_STORES__ = stores; console.log('Mock stores available:', Object.keys(stores)); } } //# sourceMappingURL=zustand.js.map