@context-action/react
Advanced tools
| const require_comparison = require('./comparison.cjs'); | ||
| let react = require("react"); | ||
| react = require_comparison.__toESM(react); | ||
| let _context_action_mutative = require("@context-action/mutative"); | ||
| let react_jsx_runtime = require("react/jsx-runtime"); | ||
| let _context_action_core = require("@context-action/core"); | ||
| //#region src/stores/core/StoreRegistry.ts | ||
| /** | ||
| * Centralized store registry for managing multiple Store instances | ||
| */ | ||
| var StoreRegistry = class { | ||
| constructor(name = "default") { | ||
| this.stores = /* @__PURE__ */ new Map(); | ||
| this.metadata = /* @__PURE__ */ new WeakMap(); | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this._snapshot = []; | ||
| this.name = name; | ||
| } | ||
| /** | ||
| * Subscribe to registry changes for reactive updates | ||
| */ | ||
| subscribe(listener) { | ||
| this.listeners.add(listener); | ||
| return () => { | ||
| this.listeners.delete(listener); | ||
| }; | ||
| } | ||
| /** | ||
| * Register a new store in the registry | ||
| */ | ||
| register(name, store, metadata) { | ||
| if (this.stores.has(name)) { | ||
| if (this.stores.get(name)) {} | ||
| } | ||
| this.stores.set(name, store); | ||
| if (metadata) this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name, | ||
| ...metadata | ||
| }); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Unregister a store from the registry | ||
| */ | ||
| unregister(name) { | ||
| if (!this.stores.get(name)) return false; | ||
| this.stores.delete(name); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get a store by name | ||
| */ | ||
| getStore(name) { | ||
| return this.stores.get(name); | ||
| } | ||
| /** | ||
| * Check if a store exists | ||
| */ | ||
| hasStore(name) { | ||
| return this.stores.has(name); | ||
| } | ||
| /** | ||
| * Get all registered store names | ||
| */ | ||
| getStoreNames() { | ||
| return Array.from(this.stores.keys()); | ||
| } | ||
| /** | ||
| * Get all stores as entries | ||
| */ | ||
| getAllStores() { | ||
| return new Map(this.stores); | ||
| } | ||
| /** | ||
| * Get store metadata | ||
| */ | ||
| getStoreMetadata(nameOrStore) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| return store ? this.metadata.get(store) : void 0; | ||
| } | ||
| /** | ||
| * Update store metadata | ||
| */ | ||
| updateStoreMetadata(nameOrStore, metadata) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| if (!store) return false; | ||
| const currentMetadata = this.metadata.get(store); | ||
| this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown", | ||
| ...currentMetadata, | ||
| ...metadata | ||
| }); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get registry snapshot for React integration | ||
| */ | ||
| getSnapshot() { | ||
| return this._snapshot; | ||
| } | ||
| /** | ||
| * Clear all stores from registry | ||
| */ | ||
| clear() { | ||
| this.stores.clear(); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Dispose registry and cleanup resources | ||
| */ | ||
| dispose() { | ||
| this.clear(); | ||
| this.listeners.clear(); | ||
| } | ||
| /** | ||
| * Get count of registered stores | ||
| */ | ||
| getStoreCount() { | ||
| return this.stores.size; | ||
| } | ||
| /** | ||
| * Iterate over all stores | ||
| */ | ||
| forEach(callback) { | ||
| this.stores.forEach((store, name) => { | ||
| callback(store, name); | ||
| }); | ||
| } | ||
| /** | ||
| * Get registry statistics | ||
| */ | ||
| getStats() { | ||
| return { | ||
| totalStores: this.stores.size, | ||
| storeNames: this.getStoreNames(), | ||
| registryName: this.name | ||
| }; | ||
| } | ||
| /** | ||
| * Update internal snapshot | ||
| */ | ||
| _updateSnapshot() { | ||
| this._snapshot = Array.from(this.stores.entries()); | ||
| } | ||
| /** | ||
| * Notify all listeners of registry changes | ||
| */ | ||
| _notifyListeners() { | ||
| this.listeners.forEach((listener) => { | ||
| try { | ||
| listener(); | ||
| } catch (error) { | ||
| console.error("Error in registry listener:", error); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Global default registry instance | ||
| */ | ||
| const globalStoreRegistry = new StoreRegistry("global"); | ||
| //#endregion | ||
| //#region src/stores/utils/sync-external-store-utils.ts | ||
| /** | ||
| * @fileoverview useSyncExternalStore 기반 공통 유틸리티 | ||
| * | ||
| * Store 구독 관련 공통 기능을 useSyncExternalStore 기반으로 구현 | ||
| * 모든 Store 훅들이 공유하는 핵심 로직을 제공 | ||
| */ | ||
| /** | ||
| * 향상된 구독 함수 생성 (내부 사용) | ||
| * 디바운싱, 스로틀링, 조건부 구독 기능 제공 | ||
| */ | ||
| function createEnhancedSubscriber(store, options = {}) { | ||
| const { debounce, throttle, condition, debug, name = "unknown" } = options; | ||
| return (callback) => { | ||
| if (!store) return () => {}; | ||
| let debounceTimer = null; | ||
| let throttleTimer = null; | ||
| let lastThrottleTime = 0; | ||
| const enhancedCallback = () => { | ||
| if (condition && !condition()) { | ||
| if (debug) console.debug(`[${name}] Subscription suspended due to condition`); | ||
| return; | ||
| } | ||
| const now = performance.now(); | ||
| if (throttle && throttle > 0) { | ||
| if (now - lastThrottleTime < throttle) { | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| throttleTimer = setTimeout(() => { | ||
| lastThrottleTime = performance.now(); | ||
| callback(); | ||
| }, throttle - (now - lastThrottleTime)); | ||
| return; | ||
| } | ||
| lastThrottleTime = now; | ||
| } | ||
| if (debounce && debounce > 0) { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| debounceTimer = setTimeout(() => { | ||
| callback(); | ||
| if (debug) console.debug(`[${name}] Debounced callback executed after ${debounce}ms`); | ||
| }, debounce); | ||
| return; | ||
| } | ||
| callback(); | ||
| }; | ||
| const unsubscribe = store.subscribe(enhancedCallback); | ||
| return () => { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| unsubscribe(); | ||
| }; | ||
| }; | ||
| } | ||
| /** | ||
| * Null-safe Store 구독 훅 | ||
| * useSyncExternalStore를 기반으로 한 안전한 구독 | ||
| */ | ||
| function useSafeStoreSubscription(store, selector, options = {}) { | ||
| const { initialValue, equalityFn, debounce, throttle, condition, debug, name } = options; | ||
| const stableSubscriptionOptions = (0, react.useMemo)(() => ({ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| }), [ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| ]); | ||
| const needsEnhancedSubscription = Boolean(debounce || throttle || condition); | ||
| const subscribe = (0, react.useCallback)((callback) => { | ||
| if (!store) return () => {}; | ||
| if (needsEnhancedSubscription) return createEnhancedSubscriber(store, stableSubscriptionOptions)(callback); | ||
| return store.subscribe(callback); | ||
| }, [ | ||
| store, | ||
| needsEnhancedSubscription, | ||
| stableSubscriptionOptions | ||
| ]); | ||
| const getSnapshot = (0, react.useCallback)(() => { | ||
| if (!store) return initialValue; | ||
| const snapshot = store.getSnapshot(); | ||
| return selector ? selector(snapshot.value) : snapshot.value; | ||
| }, [ | ||
| store, | ||
| selector, | ||
| initialValue | ||
| ]); | ||
| const cachedSnapshotRef = (0, react.useRef)(void 0); | ||
| const stableGetSnapshot = (0, react.useCallback)(() => { | ||
| const currentSnapshot = getSnapshot(); | ||
| if (equalityFn && cachedSnapshotRef.current !== void 0) { | ||
| if (equalityFn(cachedSnapshotRef.current, currentSnapshot)) return cachedSnapshotRef.current; | ||
| } | ||
| cachedSnapshotRef.current = currentSnapshot; | ||
| return currentSnapshot; | ||
| }, [getSnapshot, equalityFn]); | ||
| const getServerSnapshot = (0, react.useCallback)(() => { | ||
| return initialValue; | ||
| }, [initialValue]); | ||
| return (0, react.useSyncExternalStore)(subscribe, equalityFn ? stableGetSnapshot : getSnapshot, getServerSnapshot); | ||
| } | ||
| /** | ||
| * 기본 동등성 비교 함수들 | ||
| * comparison.ts의 함수들을 래핑하여 hook에서 사용하기 편한 인터페이스 제공 | ||
| */ | ||
| const equalityFunctions = { | ||
| reference: (a, b) => require_comparison.referenceEquals(a, b), | ||
| shallow: (a, b) => require_comparison.shallowEquals(a, b), | ||
| deep: (a, b) => require_comparison.deepEquals(a, b), | ||
| smart: (a, b) => { | ||
| if (require_comparison.referenceEquals(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| return a.every((item, index) => { | ||
| const bItem = b[index]; | ||
| if (typeof item === "object" && item !== null && typeof bItem === "object" && bItem !== null) return require_comparison.shallowEquals(item, bItem); | ||
| return require_comparison.referenceEquals(item, bItem); | ||
| }); | ||
| } | ||
| return require_comparison.shallowEquals(a, b); | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreSelector.ts | ||
| /** | ||
| * Store Selector Hook - Performance optimization through selective subscription | ||
| * | ||
| * Advanced store subscription hooks that prevent unnecessary re-renders by subscribing | ||
| * to specific parts of store data using selector functions and intelligent equality comparison. | ||
| * Essential for building high-performance React applications with complex state management. | ||
| * | ||
| * @module stores/hooks/useStoreSelector | ||
| */ | ||
| const defaultEqualityFn = equalityFunctions.smart; | ||
| const shallowEqual = equalityFunctions.shallow; | ||
| const deepEqual = equalityFunctions.deep; | ||
| const smartEqual = equalityFunctions.smart; | ||
| /** | ||
| * Hook for selective store subscription with performance optimization | ||
| * | ||
| * Subscribes to specific parts of store data using a selector function, | ||
| * triggering re-renders only when the selected value actually changes. | ||
| * Essential for preventing unnecessary re-renders in complex applications. | ||
| * | ||
| * @template T - Type of the store value | ||
| * @template R - Type of the value returned by the selector | ||
| * | ||
| * @param store - Store instance to subscribe to | ||
| * @param selector - Function to extract needed data from store value | ||
| * @param equalityFn - Function to compare previous and new values (default: Object.is) | ||
| * | ||
| * @returns The value returned by the selector function | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usestoreselector-advanced-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function useStoreSelector(store, selector, equalityFn = defaultEqualityFn) { | ||
| "use memo"; | ||
| const stableSelector = (0, react.useCallback)(selector, [selector]); | ||
| const stableEqualityFn = (0, react.useCallback)(equalityFn, [equalityFn]); | ||
| const selectorWarningShownRef = (0, react.useRef)(false); | ||
| if (process.env.NODE_ENV === "development") { | ||
| if (selector !== stableSelector && !selectorWarningShownRef.current) { | ||
| console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name); | ||
| selectorWarningShownRef.current = true; | ||
| } | ||
| } | ||
| const previousValueRef = (0, react.useRef)(void 0); | ||
| const subscribe = (0, react.useCallback)((callback) => { | ||
| return store.subscribe(callback); | ||
| }, [store]); | ||
| const getSnapshot = (0, react.useCallback)(() => { | ||
| try { | ||
| const selectedValue = stableSelector(store.getValue()); | ||
| if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current; | ||
| previousValueRef.current = selectedValue; | ||
| return selectedValue; | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") console.error("useStoreSelector: Error in selector function:", error); | ||
| throw error; | ||
| } | ||
| }, [ | ||
| store, | ||
| stableSelector, | ||
| stableEqualityFn | ||
| ]); | ||
| return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/type-guards.ts | ||
| function isRefState(value) { | ||
| return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean"; | ||
| } | ||
| /** | ||
| * DOM Event 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMEvent(value) { | ||
| return value instanceof Event; | ||
| } | ||
| /** | ||
| * Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체) | ||
| */ | ||
| function isEventLike(value) { | ||
| return typeof value === "object" && value !== null && typeof value.preventDefault === "function"; | ||
| } | ||
| /** | ||
| * target 프로퍼티를 가진 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function hasTargetProperty(value) { | ||
| return typeof value === "object" && value !== null && "target" in value; | ||
| } | ||
| /** | ||
| * DOM Element인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMElement(value) { | ||
| return value instanceof Element; | ||
| } | ||
| /** | ||
| * 객체인지 확인하는 타입 가드 (null 제외) | ||
| */ | ||
| function isObject(value) { | ||
| return typeof value === "object" && value !== null && !Array.isArray(value); | ||
| } | ||
| /** | ||
| * 복합 타입 가드: Event 객체로 의심되는 객체인지 확인 | ||
| * RefState가 아니면서 Event 관련 속성을 가진 객체를 감지 | ||
| */ | ||
| function isSuspiciousEventObject(value, checkNested = true) { | ||
| if (!isObject(value) || isRefState(value)) return false; | ||
| if (isEventLikeObject(value)) return true; | ||
| if (checkNested) { | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const nestedValue = value[key]; | ||
| if (isEventLikeObject(nestedValue)) return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * 단일 객체가 이벤트와 같은지 확인 | ||
| */ | ||
| function isEventLikeObject(value) { | ||
| if (!isObject(value)) return false; | ||
| const hasEventTarget = hasTargetProperty(value); | ||
| const hasPreventDefault = isEventLike(value); | ||
| const isEvent = isDOMEvent(value); | ||
| const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault); | ||
| const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value; | ||
| const constructorName = value?.constructor?.name; | ||
| const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false; | ||
| return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor; | ||
| } | ||
| /** | ||
| * 문제가 될 수 있는 속성들을 찾아내는 함수 | ||
| */ | ||
| function findProblematicProperties(value) { | ||
| if (!isObject(value)) return []; | ||
| const problematicKeys = []; | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const prop = value[key]; | ||
| if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key); | ||
| } | ||
| return problematicKeys; | ||
| } | ||
| /** | ||
| * 통합 타입 가드 객체 | ||
| * 모든 타입 가드 함수들을 하나의 객체로 export | ||
| */ | ||
| const TypeGuards = { | ||
| isRefState, | ||
| isDOMEvent, | ||
| isEventLike, | ||
| hasTargetProperty, | ||
| isDOMElement, | ||
| isObject, | ||
| isSuspiciousEventObject, | ||
| findProblematicProperties | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/utils/error-handling.ts | ||
| /** | ||
| * @fileoverview Error Handling Utilities | ||
| * | ||
| * 일관된 에러 처리를 위한 유틸리티 함수들 | ||
| * Context-Action 프레임워크 전반에 걸친 표준화된 에러 처리 패턴 | ||
| */ | ||
| /** | ||
| * Context-Action 프레임워크의 에러 유형 정의 | ||
| */ | ||
| let ContextActionErrorType = /* @__PURE__ */ function(ContextActionErrorType$1) { | ||
| ContextActionErrorType$1["STORE_ERROR"] = "STORE_ERROR"; | ||
| ContextActionErrorType$1["ACTION_ERROR"] = "ACTION_ERROR"; | ||
| ContextActionErrorType$1["REF_ERROR"] = "REF_ERROR"; | ||
| ContextActionErrorType$1["VALIDATION_ERROR"] = "VALIDATION_ERROR"; | ||
| ContextActionErrorType$1["INITIALIZATION_ERROR"] = "INITIALIZATION_ERROR"; | ||
| ContextActionErrorType$1["TIMEOUT_ERROR"] = "TIMEOUT_ERROR"; | ||
| ContextActionErrorType$1["CIRCULAR_REFERENCE_ERROR"] = "CIRCULAR_REFERENCE_ERROR"; | ||
| return ContextActionErrorType$1; | ||
| }({}); | ||
| /** | ||
| * Context-Action 프레임워크의 표준 에러 클래스 | ||
| */ | ||
| var ContextActionError = class ContextActionError extends Error { | ||
| constructor(type, message, context, originalError) { | ||
| super(message); | ||
| this.name = "ContextActionError"; | ||
| this.type = type; | ||
| this.context = context ?? void 0; | ||
| this.timestamp = Date.now(); | ||
| if (Error.captureStackTrace) Error.captureStackTrace(this, ContextActionError); | ||
| if (originalError) this.stack = `${this.stack}\nCaused by: ${originalError.stack}`; | ||
| } | ||
| }; | ||
| /** | ||
| * 에러 로깅 레벨 | ||
| */ | ||
| let ErrorLogLevel = /* @__PURE__ */ function(ErrorLogLevel$1) { | ||
| ErrorLogLevel$1[ErrorLogLevel$1["SILENT"] = 0] = "SILENT"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["ERROR"] = 1] = "ERROR"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["WARN"] = 2] = "WARN"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["INFO"] = 3] = "INFO"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["DEBUG"] = 4] = "DEBUG"; | ||
| return ErrorLogLevel$1; | ||
| }({}); | ||
| /** | ||
| * 현재 에러 핸들링 설정 | ||
| */ | ||
| let currentErrorConfig = { | ||
| logLevel: process.env.NODE_ENV === "development" ? ErrorLogLevel.DEBUG : ErrorLogLevel.ERROR, | ||
| throwOnError: process.env.NODE_ENV === "development", | ||
| enableStackTrace: true, | ||
| maxLogEntries: 100, | ||
| suppressRepeatedErrors: true, | ||
| logErrors: true | ||
| }; | ||
| /** | ||
| * 에러 로그 저장소 | ||
| */ | ||
| let errorLog = []; | ||
| let errorSignatures = /* @__PURE__ */ new Map(); | ||
| /** | ||
| * 에러 시그니처 생성 (중복 에러 감지용) | ||
| */ | ||
| function createErrorSignature(error) { | ||
| return `${error.type}:${error.message}:${error.context?.component || "unknown"}`; | ||
| } | ||
| /** | ||
| * 표준화된 에러 처리 함수 (통합된 에러 바운더리 사용) | ||
| */ | ||
| function handleError(type, message, context, originalError) { | ||
| const error = new ContextActionError(type, message, context, originalError); | ||
| logError(error); | ||
| if (currentErrorConfig.throwOnError) throw error; | ||
| return error; | ||
| } | ||
| /** | ||
| * 에러 로깅 함수 | ||
| */ | ||
| function logError(error) { | ||
| const signature = createErrorSignature(error); | ||
| if (currentErrorConfig.suppressRepeatedErrors) { | ||
| const existingEntry = errorSignatures.get(signature); | ||
| if (existingEntry) { | ||
| existingEntry.count++; | ||
| existingEntry.lastOccurred = Date.now(); | ||
| if (existingEntry.count % 10 === 0) console.warn(`[Context-Action] Repeated error occurred ${existingEntry.count} times:`, error); | ||
| return; | ||
| } | ||
| } | ||
| const logEntry = { | ||
| error, | ||
| count: 1, | ||
| lastOccurred: Date.now() | ||
| }; | ||
| errorLog.push(logEntry); | ||
| errorSignatures.set(signature, logEntry); | ||
| if (errorLog.length > currentErrorConfig.maxLogEntries) { | ||
| const removedEntry = errorLog.shift(); | ||
| if (removedEntry) { | ||
| const removedSignature = createErrorSignature(removedEntry.error); | ||
| errorSignatures.delete(removedSignature); | ||
| } | ||
| } | ||
| if (typeof globalThis !== "undefined" && globalThis.globalErrorBoundary) globalThis.globalErrorBoundary.reportError(error); | ||
| switch (currentErrorConfig.logLevel) { | ||
| case ErrorLogLevel.DEBUG: | ||
| console.debug("[Context-Action] Debug:", error); | ||
| break; | ||
| case ErrorLogLevel.INFO: | ||
| console.info("[Context-Action] Info:", error); | ||
| break; | ||
| case ErrorLogLevel.WARN: | ||
| console.warn("[Context-Action] Warning:", error); | ||
| break; | ||
| case ErrorLogLevel.ERROR: | ||
| console.error("[Context-Action] Error:", error); | ||
| if (currentErrorConfig.enableStackTrace && error.stack) console.error("Stack trace:", error.stack); | ||
| break; | ||
| case ErrorLogLevel.SILENT: break; | ||
| } | ||
| } | ||
| /** | ||
| * 특정 에러 타입에 대한 전용 핸들러들 | ||
| */ | ||
| const ErrorHandlers = { | ||
| store: (message, context, originalError) => { | ||
| const enhancedMessage = `[Store Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.STORE_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| action: (message, context, originalError) => { | ||
| const enhancedMessage = `[Action Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.ACTION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| ref: (message, context, originalError) => { | ||
| const enhancedMessage = `[Ref Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.REF_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| validation: (message, context, originalError) => { | ||
| const enhancedMessage = `[Validation Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.VALIDATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| initialization: (message, context, originalError) => { | ||
| const enhancedMessage = `[Initialization Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.INITIALIZATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| timeout: (message, context, originalError) => { | ||
| const enhancedMessage = `[Timeout Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.TIMEOUT_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| circularReference: (message, context, originalError) => handleError(ContextActionErrorType.CIRCULAR_REFERENCE_ERROR, message, context, originalError) | ||
| }; | ||
| /** | ||
| * 에러 통계 가져오기 | ||
| */ | ||
| function getErrorStatistics() { | ||
| const errorsByType = Object.values(ContextActionErrorType).reduce((acc, type) => { | ||
| acc[type] = 0; | ||
| return acc; | ||
| }, {}); | ||
| errorLog.forEach((entry) => { | ||
| errorsByType[entry.error.type] += entry.count; | ||
| }); | ||
| const mostFrequentErrors = Array.from(errorSignatures.entries()).map(([signature, entry]) => ({ | ||
| signature, | ||
| count: entry.count, | ||
| lastOccurred: entry.lastOccurred | ||
| })).sort((a, b) => b.count - a.count).slice(0, 10); | ||
| const recentErrors = errorLog.slice(-10).map((entry) => entry.error); | ||
| return { | ||
| totalErrors: errorLog.reduce((sum, entry) => sum + entry.count, 0), | ||
| errorsByType, | ||
| mostFrequentErrors, | ||
| recentErrors | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/core/Store.ts | ||
| /** | ||
| * Deep freeze an object to make it immutable | ||
| * Prevents modifications to the returned value from affecting cached state | ||
| */ | ||
| function deepFreeze(obj) { | ||
| if (obj === null || typeof obj !== "object") return obj; | ||
| const proto = Object.getPrototypeOf(obj); | ||
| if (proto !== Object.prototype && proto !== Array.prototype) return obj; | ||
| Object.freeze(obj); | ||
| for (const key of Object.keys(obj)) { | ||
| const value = obj[key]; | ||
| if (value !== null && typeof value === "object") deepFreeze(value); | ||
| } | ||
| return obj; | ||
| } | ||
| /** | ||
| * Core Store class for centralized state management with memory leak prevention | ||
| * | ||
| * Provides reactive state management with subscription capabilities, optimized for | ||
| * React integration through useSyncExternalStore. Features advanced cleanup mechanisms, | ||
| * automatic resource management, and comprehensive memory leak prevention. | ||
| * | ||
| * Key Features: | ||
| * - Automatic cleanup task registration and execution | ||
| * - Memory leak prevention with disposal patterns | ||
| * - Race condition protection for async operations | ||
| * - Advanced error recovery with exponential backoff | ||
| * - Resource monitoring and threshold management | ||
| * | ||
| * @template T - The type of value stored in this store | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const userStore = createStore('user', { name: '', age: 0 }); | ||
| * | ||
| * // Register cleanup tasks | ||
| * const unregister = userStore.registerCleanup(() => { | ||
| * console.log('Cleaning up user store resources'); | ||
| * }); | ||
| * | ||
| * // Automatic cleanup on disposal | ||
| * userStore.dispose(); | ||
| * ``` | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * @public | ||
| */ | ||
| var Store = class { | ||
| constructor(name, initialValue) { | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this.patchAwareListeners = /* @__PURE__ */ new Set(); | ||
| this._lastPatches = null; | ||
| this._lastClonedValue = null; | ||
| this._lastClonedVersion = 0; | ||
| this._version = 0; | ||
| this.isUpdating = false; | ||
| this.updateQueue = []; | ||
| this.notificationMode = "batched"; | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| this.pendingUpdatesCount = 0; | ||
| this.cleanupTasks = /* @__PURE__ */ new Set(); | ||
| this.isDisposed = false; | ||
| this.errorCount = 0; | ||
| this.lastErrorTime = 0; | ||
| this.MAX_ERROR_COUNT = 5; | ||
| this.ERROR_RESET_TIME = 6e4; | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.cloningEnabled = true; | ||
| this.subscribe = (listener) => { | ||
| if (this.isDisposed) { | ||
| console.warn(`Cannot subscribe to disposed store "${this.name}"`); | ||
| return () => {}; | ||
| } | ||
| const enhancedListener = () => { | ||
| if (this.isDisposed) return; | ||
| try { | ||
| listener(); | ||
| if (this.errorCount > 0) this.errorCount = 0; | ||
| } catch (error) { | ||
| this._handleListenerError(error, listener); | ||
| } | ||
| }; | ||
| this.subscriptionRegistry.set(listener, { | ||
| subscribedAt: Date.now(), | ||
| errorCount: 0, | ||
| enhancedListener | ||
| }); | ||
| this.listeners.add(enhancedListener); | ||
| return () => { | ||
| this.listeners.delete(enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| }; | ||
| }; | ||
| this.subscribeWithPatches = (listener) => { | ||
| if (this.isDisposed) { | ||
| console.warn(`Cannot subscribe to disposed store "${this.name}"`); | ||
| return () => {}; | ||
| } | ||
| this.patchAwareListeners.add(listener); | ||
| return () => this.patchAwareListeners.delete(listener); | ||
| }; | ||
| this.getSnapshot = () => { | ||
| return this._snapshot; | ||
| }; | ||
| this.name = name; | ||
| this._value = initialValue; | ||
| this._snapshot = this._createSnapshot(); | ||
| } | ||
| /** | ||
| * Get the patches from the last state change | ||
| * | ||
| * Returns the JSON patches that describe the most recent update, | ||
| * or null if no patches are available (e.g., initial state or full replacement). | ||
| * | ||
| * @returns Array of JSON patches or null | ||
| */ | ||
| getLastPatches() { | ||
| return this._lastPatches; | ||
| } | ||
| /** | ||
| * 현재 값 직접 가져오기 (액션 핸들러용) | ||
| * 핵심 로직: 불변성을 보장하는 깊은 복사본 반환 | ||
| * | ||
| * @implements lazy-evaluation | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 사용 시나리오: Action handler에서 최신 상태 읽기 | ||
| * 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨 | ||
| */ | ||
| getValue() { | ||
| if (typeof this._value !== "object" || this._value === null) return this._value; | ||
| if (this.cloningEnabled) { | ||
| if (this._lastClonedVersion === this._version && this._lastClonedValue !== null) return this._lastClonedValue; | ||
| this._lastClonedValue = deepFreeze((0, _context_action_mutative.safeGet)(this._value, this.cloningEnabled)); | ||
| this._lastClonedVersion = this._version; | ||
| return this._lastClonedValue; | ||
| } | ||
| return this._value; | ||
| } | ||
| /** | ||
| * Store 값 설정 및 구독자 알림 | ||
| * 핵심 로직: | ||
| * 1. 입력값의 불변성 보장을 위한 깊은 복사 (선택적 skip 가능) | ||
| * 2. 강화된 값 비교 시스템으로 불필요한 리렌더링 방지 | ||
| * 3. Structural sharing을 통한 성능 최적화 | ||
| * 4. 값 변경 시에만 스냅샷 재생성 및 알림 | ||
| * | ||
| * @implements unidirectional-data-flow | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 보안 강화: 입력값을 복사하여 Store 내부 상태가 외부 참조에 의해 변경되지 않도록 보호 | ||
| * 성능 강화: 다층 비교 시스템으로 정확한 변경 감지 및 렌더링 최적화 | ||
| */ | ||
| setValue(value, options) { | ||
| if (TypeGuards.isObject(value)) { | ||
| if (!TypeGuards.isRefState(value) && TypeGuards.isSuspiciousEventObject(value)) { | ||
| const eventHandling = options?.eventHandling || "block"; | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(value); | ||
| const hasPreventDefault = TypeGuards.isEventLike(value); | ||
| const isEvent = TypeGuards.isDOMEvent(value); | ||
| switch (eventHandling) { | ||
| case "allow": break; | ||
| case "transform": | ||
| if (options?.eventTransform) try { | ||
| value = options.eventTransform(value); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Event transformation failed in Store.setValue", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| error: error instanceof Error ? error.message : String(error) | ||
| }); | ||
| return; | ||
| } | ||
| else { | ||
| ErrorHandlers.store("Event transformation requested but no transform function provided", { | ||
| storeName: this.name, | ||
| valueType: typeof value | ||
| }); | ||
| return; | ||
| } | ||
| break; | ||
| case "block": | ||
| default: | ||
| ErrorHandlers.store("Event object detected in Store.setValue - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| constructorName: value?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(value) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| const safeValue = options?.skipClone ? value : (0, _context_action_mutative.safeSet)(value, this.cloningEnabled); | ||
| let hasChanged = true; | ||
| if (!options?.skipComparison) hasChanged = this._compareValues(this._value, safeValue); | ||
| if (hasChanged) { | ||
| if (this.patchAwareListeners.size > 0 && TypeGuards.isObject(this._value) && TypeGuards.isObject(safeValue)) try { | ||
| const [, patches] = (0, _context_action_mutative.produceWithPatches)(this._value, (draft) => { | ||
| const draftKeys = Object.keys(draft); | ||
| const valueKeys = Object.keys(safeValue); | ||
| for (const key of draftKeys) if (!Object.prototype.hasOwnProperty.call(safeValue, key)) delete draft[key]; | ||
| for (const key of valueKeys) draft[key] = safeValue[key]; | ||
| }); | ||
| this._lastPatches = patches; | ||
| } catch { | ||
| this._lastPatches = null; | ||
| } | ||
| else this._lastPatches = null; | ||
| this._value = safeValue; | ||
| this._version++; | ||
| this._snapshot = this._createSnapshot(); | ||
| this._scheduleNotification(); | ||
| } | ||
| } | ||
| /** | ||
| * Update value using updater function with Mutative integration | ||
| * 핵심 로직: | ||
| * 1. Mutative create를 사용하여 draft 객체 제공 (패치 캡처 포함) | ||
| * 2. updater 결과를 불변성을 보장하며 설정 | ||
| * | ||
| * @implements store-immutability | ||
| * 보안 강화: Mutative draft를 통한 안전한 상태 수정 | ||
| */ | ||
| update(updater) { | ||
| if (this.isUpdating) { | ||
| this.updateQueue.push(() => this.update(updater)); | ||
| return; | ||
| } | ||
| try { | ||
| this.isUpdating = true; | ||
| let updatedValue; | ||
| let patches = null; | ||
| try { | ||
| const [nextState, capturedPatches] = (0, _context_action_mutative.produceWithPatches)(this._value, (draft) => { | ||
| const result = updater(draft); | ||
| if (result !== void 0) return result; | ||
| }); | ||
| updatedValue = nextState; | ||
| patches = capturedPatches; | ||
| } catch (mutativeError) { | ||
| if (process.env.NODE_ENV === "development") console.warn("[Store] Mutative update failed, falling back to safe copy method", mutativeError); | ||
| const safeCurrentValue = (0, _context_action_mutative.safeGet)(this._value, this.cloningEnabled); | ||
| try { | ||
| const [nextState, capturedPatches] = (0, _context_action_mutative.produceWithPatches)(safeCurrentValue, (draft) => { | ||
| const result = updater(draft); | ||
| if (result !== void 0) return result; | ||
| }); | ||
| updatedValue = nextState; | ||
| patches = capturedPatches; | ||
| } catch (secondMutativeError) { | ||
| if (process.env.NODE_ENV === "development") console.warn("[Store] Mutative completely failed, using direct update (immutability not guaranteed)", secondMutativeError); | ||
| try { | ||
| const result = updater(safeCurrentValue); | ||
| updatedValue = result !== void 0 ? result : safeCurrentValue; | ||
| } catch (updaterError) { | ||
| if (process.env.NODE_ENV === "development") console.warn("[Store] Updater function threw an error, update aborted", updaterError); | ||
| return; | ||
| } | ||
| patches = null; | ||
| } | ||
| } | ||
| if (TypeGuards.isObject(updatedValue)) { | ||
| if (!TypeGuards.isRefState(updatedValue) && TypeGuards.isSuspiciousEventObject(updatedValue)) { | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(updatedValue); | ||
| const hasPreventDefault = TypeGuards.isEventLike(updatedValue); | ||
| const isEvent = TypeGuards.isDOMEvent(updatedValue); | ||
| ErrorHandlers.store("Event object detected in Store.update result - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| updatedValueType: typeof updatedValue, | ||
| constructorName: updatedValue?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(updatedValue) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| if (this._compareValues(this._value, updatedValue)) { | ||
| this._lastPatches = patches; | ||
| this._value = updatedValue; | ||
| this._version++; | ||
| this._snapshot = this._createSnapshot(); | ||
| this._scheduleNotification(); | ||
| } | ||
| } finally { | ||
| this.isUpdating = false; | ||
| if (this.updateQueue.length > 0) { | ||
| const nextUpdate = this.updateQueue.shift(); | ||
| if (nextUpdate) Promise.resolve().then(nextUpdate); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Get number of active listeners (includes patch-aware listeners) | ||
| */ | ||
| getListenerCount() { | ||
| return this.listeners.size + this.patchAwareListeners.size; | ||
| } | ||
| /** | ||
| * Clear all listeners (includes patch-aware listeners) | ||
| */ | ||
| clearListeners() { | ||
| this.listeners.clear(); | ||
| this.patchAwareListeners.clear(); | ||
| } | ||
| /** | ||
| * Manually notify path-based subscribers without changing state value | ||
| * | ||
| * Useful for external systems (WebSocket, async operations) that need to | ||
| * trigger UI updates for specific paths without actual state changes. | ||
| * | ||
| * @param path - The path to notify subscribers about | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // External async logic | ||
| * async function fetchData(store: Store<AppState>) { | ||
| * store.notifyPath(['ui', 'loading']); // Trigger loading UI | ||
| * const data = await api.fetch(); | ||
| * store.setValue({ ...store.getValue(), data }); | ||
| * } | ||
| * ``` | ||
| */ | ||
| notifyPath(path) { | ||
| if (this.isDisposed) return; | ||
| this._lastPatches = [{ | ||
| op: "replace", | ||
| path, | ||
| value: this._getValueAtPath(path) | ||
| }]; | ||
| this._scheduleNotification(); | ||
| } | ||
| /** | ||
| * Manually notify multiple paths at once | ||
| * | ||
| * @param paths - Array of paths to notify subscribers about | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * store.notifyPaths([ | ||
| * ['ui', 'loading'], | ||
| * ['ui', 'progress'] | ||
| * ]); | ||
| * ``` | ||
| */ | ||
| notifyPaths(paths) { | ||
| if (this.isDisposed) return; | ||
| if (paths.length === 0) return; | ||
| this._lastPatches = paths.map((path) => ({ | ||
| op: "replace", | ||
| path, | ||
| value: this._getValueAtPath(path) | ||
| })); | ||
| this._scheduleNotification(); | ||
| } | ||
| /** | ||
| * Get value at a specific path in the store | ||
| * @private | ||
| */ | ||
| _getValueAtPath(path) { | ||
| let current = this._value; | ||
| for (const segment of path) { | ||
| if (current === null || current === void 0) return; | ||
| current = current[segment]; | ||
| } | ||
| return current; | ||
| } | ||
| /** | ||
| * Register cleanup task for automatic execution on disposal | ||
| * | ||
| * Registers a cleanup function that will be automatically called when the store | ||
| * is disposed. This prevents memory leaks and ensures proper resource cleanup. | ||
| * | ||
| * @param task - Cleanup function to register | ||
| * @returns Unregister function to remove the cleanup task | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const timer = setInterval(() => {}, 1000); | ||
| * const unregister = store.registerCleanup(() => clearInterval(timer)); | ||
| * | ||
| * // Later, remove the cleanup task if needed | ||
| * unregister(); | ||
| * ``` | ||
| */ | ||
| registerCleanup(task) { | ||
| if (this.isDisposed) { | ||
| console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`); | ||
| return () => {}; | ||
| } | ||
| this.cleanupTasks.add(task); | ||
| return () => this.cleanupTasks.delete(task); | ||
| } | ||
| /** | ||
| * Enhanced Store disposal with comprehensive cleanup | ||
| * | ||
| * Performs complete cleanup of all store resources including listeners, | ||
| * timers, cleanup tasks, and internal state. Prevents memory leaks and | ||
| * ensures proper resource disposal. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Manual disposal | ||
| * store.dispose(); | ||
| * | ||
| * // Auto-disposal with useEffect | ||
| * useEffect(() => { | ||
| * return () => store.dispose(); | ||
| * }, [store]); | ||
| * ``` | ||
| */ | ||
| dispose() { | ||
| if (this.isDisposed) return; | ||
| this.isDisposed = true; | ||
| try { | ||
| this.cleanupTasks.forEach((task) => { | ||
| try { | ||
| task(); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error during cleanup task execution", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| }); | ||
| this.cleanupTasks.clear(); | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.clearListeners(); | ||
| if (this.animationFrameId !== null) { | ||
| cancelAnimationFrame(this.animationFrameId); | ||
| this.animationFrameId = null; | ||
| } | ||
| this.pendingNotification = false; | ||
| this.updateQueue.length = 0; | ||
| } catch (error) { | ||
| ErrorHandlers.store("Critical error during store disposal", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| } | ||
| /** | ||
| * Check if store is disposed | ||
| * @returns true if store has been disposed | ||
| */ | ||
| isStoreDisposed() { | ||
| return this.isDisposed; | ||
| } | ||
| /** | ||
| * Store별 커스텀 비교 함수 설정 | ||
| * 이 Store에만 적용되는 특별한 비교 로직 설정 | ||
| * | ||
| * @param comparator - 커스텀 비교 함수 (oldValue, newValue) => boolean | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setCustomComparator(comparator) { | ||
| this.customComparator = comparator; | ||
| } | ||
| /** | ||
| * Store별 비교 옵션 설정 | ||
| * 이 Store에만 적용되는 비교 전략 설정 | ||
| * | ||
| * @param options - 비교 옵션 | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setComparisonOptions(options) { | ||
| this.comparisonOptions = options; | ||
| } | ||
| /** | ||
| * 성능 최적화: Store별 복사 동작 제어 | ||
| * | ||
| * @param enabled - true: 복사 활성화 (안전), false: 복사 비활성화 (성능 우선) | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/performance | ||
| */ | ||
| setCloningEnabled(enabled) { | ||
| this.cloningEnabled = enabled; | ||
| } | ||
| /** | ||
| * 현재 복사 설정 조회 | ||
| */ | ||
| isCloningEnabled() { | ||
| return this.cloningEnabled; | ||
| } | ||
| /** | ||
| * 강화된 값 비교 시스템 | ||
| * 1. 커스텀 비교 함수 우선 사용 | ||
| * 2. Store별 비교 옵션 적용 | ||
| * 3. 성능 최적화된 빠른 비교 fallback | ||
| * 4. 전역 비교 설정 사용 | ||
| * | ||
| * @param oldValue - 이전 값 | ||
| * @param newValue - 새로운 값 | ||
| * @returns true if values are different (change detected), false if same | ||
| * @protected | ||
| */ | ||
| _compareValues(oldValue, newValue) { | ||
| let result; | ||
| try { | ||
| if (this.customComparator) result = !this.customComparator(oldValue, newValue); | ||
| else if (this.comparisonOptions) result = !require_comparison.compareValues(oldValue, newValue, this.comparisonOptions); | ||
| else result = !require_comparison.compareValues(oldValue, newValue, { strategy: "reference" }); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error during value comparison, falling back to reference comparison", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| result = !Object.is(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| _createSnapshot() { | ||
| return { | ||
| value: deepFreeze((0, _context_action_mutative.safeGet)(this._value, this.cloningEnabled)), | ||
| name: this.name, | ||
| lastUpdate: Date.now() | ||
| }; | ||
| } | ||
| /** | ||
| * requestAnimationFrame 기반 알림 스케줄링 | ||
| * 브라우저의 다음 프레임에서 리스너 알림 실행 | ||
| */ | ||
| _scheduleNotification() { | ||
| if (this.notificationMode === "immediate") this._notifyListeners(); | ||
| else this._scheduleWithRAF(); | ||
| } | ||
| /** | ||
| * requestAnimationFrame을 사용한 알림 스케줄링 | ||
| * 누적 가능한 배치 시스템으로 개선 | ||
| */ | ||
| _scheduleWithRAF() { | ||
| this.pendingUpdatesCount++; | ||
| if (!this.pendingNotification) { | ||
| this.pendingNotification = true; | ||
| this.animationFrameId = requestAnimationFrame(() => { | ||
| this._executeNotification(); | ||
| }); | ||
| } | ||
| } | ||
| /** | ||
| * 스케줄된 알림 실행 | ||
| */ | ||
| _executeNotification() { | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| const batchedUpdates = this.pendingUpdatesCount; | ||
| this.pendingUpdatesCount = 0; | ||
| this._notifyListeners(); | ||
| if (process.env.NODE_ENV === "development" && batchedUpdates > 1) console.debug(`[Store:${this.name}] Batched ${batchedUpdates} updates in single frame`); | ||
| } | ||
| /** | ||
| * Handle listener execution errors with recovery strategies | ||
| */ | ||
| _handleListenerError(error, listener) { | ||
| const now = Date.now(); | ||
| if (now - this.lastErrorTime > this.ERROR_RESET_TIME) this.errorCount = 0; | ||
| this.errorCount++; | ||
| this.lastErrorTime = now; | ||
| const metadata = this.subscriptionRegistry.get(listener); | ||
| if (metadata) metadata.errorCount++; | ||
| ErrorHandlers.store("Error in store listener execution", { | ||
| storeName: this.name, | ||
| listenerCount: this.listeners.size, | ||
| errorCount: this.errorCount, | ||
| subscriptionAge: metadata ? now - metadata.subscribedAt : "unknown" | ||
| }, error instanceof Error ? error : void 0); | ||
| if (metadata && metadata.errorCount >= 3) { | ||
| console.warn(`Removing problematic listener from store "${this.name}" after ${metadata.errorCount} errors`); | ||
| this.listeners.delete(metadata.enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| } | ||
| if (this.errorCount >= this.MAX_ERROR_COUNT) { | ||
| console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`); | ||
| this.clearListeners(); | ||
| } | ||
| } | ||
| _notifyListeners() { | ||
| if (this.isDisposed) return; | ||
| this.listeners.forEach((listener) => { | ||
| if (this.isDisposed) return; | ||
| listener(); | ||
| }); | ||
| this.patchAwareListeners.forEach((listener) => { | ||
| if (this.isDisposed) return; | ||
| try { | ||
| listener(this._lastPatches); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error in patch-aware listener execution", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Factory function for creating type-safe Store instances | ||
| * | ||
| * Creates a new Store instance with the specified name and initial value. | ||
| * Provides type safety and integrates seamlessly with React hooks and | ||
| * the Context-Action framework patterns. | ||
| * | ||
| * @template T - The type of values stored in this store | ||
| * | ||
| * @param name - Unique identifier for the store (used for debugging) | ||
| * @param initialValue - Initial value to store | ||
| * | ||
| * @returns Configured Store instance ready for use | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function createStore(name, initialValue) { | ||
| return new Store(name, initialValue); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreValue.ts | ||
| function useStoreValue(store, selectorOrOptions, options) { | ||
| "use memo"; | ||
| const selector = typeof selectorOrOptions === "function" ? selectorOrOptions : void 0; | ||
| const { equalityFn = defaultEqualityFn, condition, debounce, throttle, initialValue, debug = false, name = store?.name || "unknown" } = (typeof selectorOrOptions === "function" ? options : selectorOrOptions) || {}; | ||
| return useSafeStoreSubscription(store, selector, { | ||
| debug, | ||
| name, | ||
| equalityFn, | ||
| initialValue, | ||
| ...debounce !== void 0 && { debounce }, | ||
| ...throttle !== void 0 && { throttle }, | ||
| ...condition && { condition } | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.tsx | ||
| /** | ||
| * @fileoverview Store Error Boundary Component | ||
| * | ||
| * Context-Action Store 시스템을 위한 에러 경계 컴포넌트 | ||
| * Store 관련 에러들을 적절히 처리하고 사용자에게 우아한 fallback UI를 제공 | ||
| */ | ||
| /** | ||
| * Store 시스템을 위한 에러 경계 컴포넌트 | ||
| * | ||
| * Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다. | ||
| * 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는 | ||
| * 사용자 친화적인 메시지를 보여줍니다. | ||
| */ | ||
| var StoreErrorBoundary = class extends react.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.resetTimeoutId = null; | ||
| this.resetErrorBoundary = () => { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| this.setState({ | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }); | ||
| }; | ||
| this.state = { | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }; | ||
| } | ||
| static getDerivedStateFromError(error) { | ||
| return { | ||
| hasError: true, | ||
| error: error instanceof Error && error.name === "ContextActionError" ? error : null, | ||
| errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` | ||
| }; | ||
| } | ||
| componentDidCatch(error, errorInfo) { | ||
| if (error.name === "ContextActionError") { | ||
| const contextActionError = error; | ||
| this.setState({ errorInfo }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } else { | ||
| const contextActionError = ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, { | ||
| component: "StoreErrorBoundary", | ||
| stack: error.stack, | ||
| componentStack: errorInfo.componentStack | ||
| }, error); | ||
| this.setState({ | ||
| error: contextActionError, | ||
| errorInfo | ||
| }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } | ||
| } | ||
| componentDidUpdate(prevProps) { | ||
| const { hasError } = this.state; | ||
| const { resetOnPropsChange, resetKeys } = this.props; | ||
| if (hasError && resetOnPropsChange) { | ||
| if (resetKeys) { | ||
| if (resetKeys.some((key) => { | ||
| return prevProps[key] !== this.props[key]; | ||
| })) this.resetErrorBoundary(); | ||
| } else if (prevProps !== this.props) this.resetErrorBoundary(); | ||
| } | ||
| } | ||
| componentWillUnmount() { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| } | ||
| render() { | ||
| const { hasError, error, errorInfo } = this.state; | ||
| const { children, fallback } = this.props; | ||
| if (hasError) { | ||
| if (fallback) { | ||
| if (typeof fallback === "function") return fallback(error, errorInfo); | ||
| return fallback; | ||
| } | ||
| return this.renderDefaultFallback(); | ||
| } | ||
| return children; | ||
| } | ||
| renderDefaultFallback() { | ||
| if (process.env.NODE_ENV === "development") return this.renderDevelopmentFallback(); | ||
| else return this.renderProductionFallback(); | ||
| } | ||
| renderDevelopmentFallback() { | ||
| const { error, errorInfo, errorId } = this.state; | ||
| const stats = getErrorStatistics(); | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { | ||
| padding: "20px", | ||
| margin: "20px", | ||
| border: "2px solid #ff6b6b", | ||
| borderRadius: "8px", | ||
| backgroundColor: "#ffe0e0", | ||
| fontFamily: "monospace" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { | ||
| style: { | ||
| color: "#d63031", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "🚨 Store Error Boundary" | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error ID:" }), | ||
| " ", | ||
| errorId | ||
| ] | ||
| }), | ||
| error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Type:" }), | ||
| " ", | ||
| error.type, | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Message:" }), | ||
| " ", | ||
| error.message, | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Timestamp:" }), | ||
| " ", | ||
| new Date(error.timestamp).toISOString() | ||
| ] | ||
| }), | ||
| error?.context && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Context:" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "12px" | ||
| }, | ||
| children: JSON.stringify(error.context, null, 2) | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Statistics:" }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| "Total Errors: ", | ||
| stats.totalErrors, | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| "Recent Errors: ", | ||
| stats.recentErrors.length | ||
| ] | ||
| }), | ||
| errorInfo && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { | ||
| style: { | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Component Stack" | ||
| }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "11px", | ||
| whiteSpace: "pre-wrap" | ||
| }, | ||
| children: errorInfo.componentStack | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#00b894", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| renderProductionFallback() { | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { | ||
| padding: "20px", | ||
| textAlign: "center", | ||
| backgroundColor: "#f8f9fa", | ||
| border: "1px solid #dee2e6", | ||
| borderRadius: "8px", | ||
| margin: "20px 0" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "Something went wrong" | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 15px 0" | ||
| }, | ||
| children: "We're sorry, but something unexpected happened. Please try again." | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#007bff", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Enhanced HOC for automatic Store Error Boundary wrapping with security | ||
| * | ||
| * @template P - Component props type | ||
| * @param WrappedComponent - Component to wrap with error boundary | ||
| * @param errorBoundaryProps - Error boundary configuration | ||
| * @returns Enhanced component with comprehensive error handling | ||
| */ | ||
| function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) { | ||
| const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, { | ||
| ...errorBoundaryProps, | ||
| children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WrappedComponent, { ...props }) | ||
| }); | ||
| WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`; | ||
| return WithStoreErrorBoundaryComponent; | ||
| } | ||
| /** | ||
| * 특정 Store와 연결된 에러 경계 생성 헬퍼 | ||
| */ | ||
| function createStoreErrorBoundary(storeName, customFallback) { | ||
| return ({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, { | ||
| fallback: customFallback, | ||
| onError: (error, errorInfo) => { | ||
| console.group(`Store Error in ${storeName}`); | ||
| console.error("Error:", error); | ||
| console.error("Component Stack:", errorInfo.componentStack); | ||
| console.groupEnd(); | ||
| }, | ||
| resetKeys: [storeName], | ||
| children | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.tsx | ||
| function createActionContext(contextNameOrConfig = {}, config) { | ||
| let effectiveConfig; | ||
| let contextName; | ||
| if (typeof contextNameOrConfig === "string") { | ||
| contextName = contextNameOrConfig; | ||
| effectiveConfig = { | ||
| ...config, | ||
| name: config?.name || contextName | ||
| }; | ||
| } else { | ||
| effectiveConfig = contextNameOrConfig; | ||
| contextName = effectiveConfig.name || "ActionContext"; | ||
| } | ||
| if (effectiveConfig.schema && !effectiveConfig.registry?.schema) effectiveConfig = { | ||
| ...effectiveConfig, | ||
| registry: { | ||
| ...effectiveConfig.registry, | ||
| schema: effectiveConfig.schema | ||
| } | ||
| }; | ||
| const FactoryActionContext = (0, react.createContext)(null); | ||
| const Provider = ({ children }) => { | ||
| const actionRegisterRef = (0, react.useRef)(new _context_action_core.ActionRegister(effectiveConfig)); | ||
| const contextValue = (0, react.useMemo)(() => ({ actionRegisterRef }), []); | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FactoryActionContext.Provider, { | ||
| value: contextValue, | ||
| children | ||
| }); | ||
| }; | ||
| const useFactoryActionContext = () => { | ||
| const context = (0, react.useContext)(FactoryActionContext); | ||
| if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider"); | ||
| return context; | ||
| }; | ||
| /** | ||
| * Optimized hook to get stable dispatch functions | ||
| * | ||
| * Returns stable dispatch functions that prevent re-renders and maintain | ||
| * reference equality across component renders. | ||
| * | ||
| * @returns Object with dispatch and dispatchWithResult functions | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useActionDispatcher = () => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| return { | ||
| dispatch: (0, react.useCallback)((action, payload, options) => { | ||
| if (process.env.NODE_ENV === "development") console.log(`React dispatch called for '${String(action)}':`, { | ||
| hasPayload: payload !== void 0, | ||
| hasOptions: options !== void 0, | ||
| timestamp: (/* @__PURE__ */ new Date()).toISOString() | ||
| }); | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]), | ||
| dispatchWithResult: (0, react.useCallback)((action, payload, options) => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]) | ||
| }; | ||
| }; | ||
| const useAction = () => { | ||
| const { dispatch } = useActionDispatcher(); | ||
| return dispatch; | ||
| }; | ||
| const useActionHandler = (action, handler, config$1) => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| const actionId = (0, react.useId)(); | ||
| const handlerRef = (0, react.useRef)(handler); | ||
| handlerRef.current = handler; | ||
| const priority = config$1?.priority ?? 0; | ||
| const id = config$1?.id || `react_${String(action)}_${actionId}`; | ||
| const blocking = config$1?.blocking ?? false; | ||
| const once = config$1?.once ?? false; | ||
| const debounce = config$1?.debounce; | ||
| const throttle = config$1?.throttle; | ||
| const stableConfig = (0, react.useMemo)(() => ({ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| replaceExisting: true, | ||
| ...debounce !== void 0 && { debounce }, | ||
| ...throttle !== void 0 && { throttle } | ||
| }), [ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| debounce, | ||
| throttle | ||
| ]); | ||
| (0, react.useEffect)(() => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) return; | ||
| const wrapperHandler = (payload, controller) => { | ||
| return handlerRef.current(payload, controller); | ||
| }; | ||
| if (process.env.NODE_ENV === "development") console.log(`Registering handler for '${String(action)}'`); | ||
| return register.register(action, wrapperHandler, stableConfig); | ||
| }, [ | ||
| action, | ||
| actionRegisterRef, | ||
| stableConfig | ||
| ]); | ||
| }; | ||
| /** | ||
| * Hook that provides direct access to the ActionRegister instance | ||
| * | ||
| * This hook is useful when you need to: | ||
| * - Register multiple handlers dynamically | ||
| * - Access other ActionRegister methods like clearAction, getHandlers, etc. | ||
| * - Implement complex handler registration logic | ||
| * - Have more control over the registration lifecycle | ||
| * | ||
| * @returns ActionRegister instance or null if not initialized | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useFactoryActionRegister = () => { | ||
| return useFactoryActionContext().actionRegisterRef.current; | ||
| }; | ||
| /** | ||
| * Hook that provides access to the dispatchWithResult function | ||
| * | ||
| * This hook returns a function that dispatches actions and returns detailed | ||
| * execution results including collected handler results, execution metadata, | ||
| * and error information. | ||
| * | ||
| * @returns dispatchWithResult function with full type safety | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result | ||
| */ | ||
| const useFactoryActionDispatchWithResult = () => { | ||
| const context = useFactoryActionContext(); | ||
| const activeControllersRef = (0, react.useRef)(/* @__PURE__ */ new Set()); | ||
| const dispatch = (0, react.useCallback)((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const dispatchWithResult = (0, react.useCallback)((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const abortAll = (0, react.useCallback)(() => { | ||
| activeControllersRef.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| activeControllersRef.current.clear(); | ||
| }, []); | ||
| const resetAbortScope = (0, react.useCallback)(() => { | ||
| abortAll(); | ||
| }, [abortAll]); | ||
| (0, react.useEffect)(() => { | ||
| const controllers = activeControllersRef; | ||
| return () => { | ||
| controllers.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| controllers.current.clear(); | ||
| }; | ||
| }, []); | ||
| return { | ||
| dispatch, | ||
| dispatchWithResult, | ||
| abortAll, | ||
| resetAbortScope | ||
| }; | ||
| }; | ||
| return { | ||
| Provider, | ||
| useActionContext: useFactoryActionContext, | ||
| useActionDispatch: useAction, | ||
| useActionHandler, | ||
| useActionRegister: useFactoryActionRegister, | ||
| useActionDispatchWithResult: useFactoryActionDispatchWithResult, | ||
| context: FactoryActionContext | ||
| }; | ||
| } | ||
| //#endregion | ||
| Object.defineProperty(exports, 'ContextActionError', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return ContextActionError; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'ContextActionErrorType', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return ContextActionErrorType; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'ErrorHandlers', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return ErrorHandlers; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'Store', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return Store; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'StoreErrorBoundary', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return StoreErrorBoundary; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'StoreRegistry', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return StoreRegistry; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'TypeGuards', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return TypeGuards; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createActionContext', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createActionContext; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createStore', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createStore; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createStoreErrorBoundary', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createStoreErrorBoundary; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'defaultEqualityFn', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return defaultEqualityFn; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'handleError', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return handleError; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'useSafeStoreSubscription', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return useSafeStoreSubscription; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'useStoreSelector', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return useStoreSelector; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'useStoreValue', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return useStoreValue; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'withStoreErrorBoundary', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return withStoreErrorBoundary; | ||
| } | ||
| }); |
| import { f as IStore, m as Listener, p as IStoreRegistry, y as Unsubscribe } from "./Store.cjs"; | ||
| import React$1, { Component, ErrorInfo, ReactNode } from "react"; | ||
| import { ActionHandler, ActionRegister, ActionRegisterConfig, ActionSchemaMap, DispatchOptions, ExecutionResult, HandlerConfig } from "@context-action/core"; | ||
| //#region src/stores/core/StoreRegistry.d.ts | ||
| interface StoreMetadata { | ||
| registeredAt: number; | ||
| name: string; | ||
| debug?: boolean; | ||
| } | ||
| declare class StoreRegistry implements IStoreRegistry { | ||
| private stores; | ||
| private metadata; | ||
| private listeners; | ||
| private _snapshot; | ||
| readonly name: string; | ||
| constructor(name?: string); | ||
| subscribe(listener: Listener): Unsubscribe; | ||
| register(name: string, store: IStore<any>, metadata?: Partial<StoreMetadata>): void; | ||
| unregister(name: string): boolean; | ||
| getStore(name: string): IStore<any> | undefined; | ||
| hasStore(name: string): boolean; | ||
| getStoreNames(): string[]; | ||
| getAllStores(): Map<string, IStore<any>>; | ||
| getStoreMetadata(nameOrStore: string | IStore<any>): StoreMetadata | undefined; | ||
| updateStoreMetadata(nameOrStore: string | IStore<any>, metadata: Partial<StoreMetadata>): boolean; | ||
| getSnapshot(): Array<[string, IStore<any>]>; | ||
| clear(): void; | ||
| dispose(): void; | ||
| getStoreCount(): number; | ||
| forEach(callback: (store: IStore<any>, name: string) => void): void; | ||
| getStats(): { | ||
| totalStores: number; | ||
| storeNames: string[]; | ||
| registryName: string; | ||
| }; | ||
| private _updateSnapshot; | ||
| private _notifyListeners; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/error-handling.d.ts | ||
| declare enum ContextActionErrorType { | ||
| STORE_ERROR = "STORE_ERROR", | ||
| ACTION_ERROR = "ACTION_ERROR", | ||
| REF_ERROR = "REF_ERROR", | ||
| VALIDATION_ERROR = "VALIDATION_ERROR", | ||
| INITIALIZATION_ERROR = "INITIALIZATION_ERROR", | ||
| TIMEOUT_ERROR = "TIMEOUT_ERROR", | ||
| CIRCULAR_REFERENCE_ERROR = "CIRCULAR_REFERENCE_ERROR", | ||
| } | ||
| declare class ContextActionError extends Error { | ||
| readonly type: ContextActionErrorType; | ||
| readonly context: Record<string, unknown> | undefined; | ||
| readonly timestamp: number; | ||
| constructor(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error); | ||
| } | ||
| declare function handleError(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error): ContextActionError; | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.d.ts | ||
| interface StoreErrorBoundaryProps { | ||
| children: ReactNode; | ||
| fallback?: ReactNode | ((error: ContextActionError, errorInfo: ErrorInfo) => ReactNode); | ||
| onError?: (error: ContextActionError, errorInfo: ErrorInfo) => void; | ||
| resetOnPropsChange?: boolean; | ||
| resetKeys?: Array<string | number>; | ||
| } | ||
| interface StoreErrorBoundaryState { | ||
| hasError: boolean; | ||
| error: ContextActionError | null; | ||
| errorInfo: ErrorInfo | null; | ||
| errorId: string | null; | ||
| } | ||
| declare class StoreErrorBoundary extends Component<StoreErrorBoundaryProps, StoreErrorBoundaryState> { | ||
| private resetTimeoutId; | ||
| constructor(props: StoreErrorBoundaryProps); | ||
| static getDerivedStateFromError(error: Error): Partial<StoreErrorBoundaryState>; | ||
| componentDidCatch(error: Error, errorInfo: ErrorInfo): void; | ||
| componentDidUpdate(prevProps: StoreErrorBoundaryProps): void; | ||
| componentWillUnmount(): void; | ||
| resetErrorBoundary: () => void; | ||
| render(): React$1.ReactNode; | ||
| private renderDefaultFallback; | ||
| private renderDevelopmentFallback; | ||
| private renderProductionFallback; | ||
| } | ||
| declare function withStoreErrorBoundary<P extends object>(WrappedComponent: React$1.ComponentType<P>, errorBoundaryProps?: Omit<StoreErrorBoundaryProps, 'children'>): React$1.ComponentType<P>; | ||
| declare function createStoreErrorBoundary(storeName: string, customFallback?: ReactNode): React$1.ComponentType<{ | ||
| children: ReactNode; | ||
| }>; | ||
| //#endregion | ||
| //#region src/actions/ActionContext.types.d.ts | ||
| interface ActionContextConfig extends ActionRegisterConfig { | ||
| name?: string; | ||
| schema?: ActionSchemaMap; | ||
| } | ||
| interface ActionContextType<T extends {}> { | ||
| actionRegisterRef: React.RefObject<ActionRegister<T>>; | ||
| } | ||
| interface ActionContextReturn<T extends {}> { | ||
| Provider: React.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useActionContext: () => ActionContextType<T>; | ||
| useActionDispatch: () => ActionRegister<T>['dispatch']; | ||
| useActionHandler: <K extends keyof T>(action: K, handler: ActionHandler<T[K]>, config?: HandlerConfig) => void; | ||
| useActionRegister: () => ActionRegister<T> | null; | ||
| useActionDispatchWithResult: () => { | ||
| dispatch: <K extends keyof T>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<void>; | ||
| dispatchWithResult: <K extends keyof T, R = void>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<ExecutionResult<R>>; | ||
| abortAll: () => void; | ||
| resetAbortScope: () => void; | ||
| }; | ||
| context: React.Context<ActionContextType<T> | null>; | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.d.ts | ||
| declare function createActionContext<T extends {}>(contextName: string, config?: ActionContextConfig): ActionContextReturn<T>; | ||
| declare function createActionContext<T extends {}>(config: ActionContextConfig): ActionContextReturn<T>; | ||
| //#endregion | ||
| export { StoreErrorBoundary as a, createStoreErrorBoundary as c, ContextActionErrorType as d, handleError as f, ActionContextType as i, withStoreErrorBoundary as l, ActionContextConfig as n, StoreErrorBoundaryProps as o, StoreRegistry as p, ActionContextReturn as r, StoreErrorBoundaryState as s, createActionContext as t, ContextActionError as u }; | ||
| //# sourceMappingURL=ActionContext.d.cts.map |
| {"version":3,"file":"ActionContext.d.cts","names":[],"sources":["../src/stores/core/StoreRegistry.ts","../src/stores/utils/error-handling.ts","../src/stores/components/StoreErrorBoundary.tsx","../src/actions/ActionContext.types.ts","../src/actions/ActionContext.tsx"],"sourcesContent":[],"mappings":"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"} |
| import { f as IStore, m as Listener, p as IStoreRegistry, y as Unsubscribe } from "./Store.js"; | ||
| import React$1, { Component, ErrorInfo, ReactNode } from "react"; | ||
| import { ActionHandler, ActionRegister, ActionRegisterConfig, ActionSchemaMap, DispatchOptions, ExecutionResult, HandlerConfig } from "@context-action/core"; | ||
| //#region src/stores/core/StoreRegistry.d.ts | ||
| interface StoreMetadata { | ||
| registeredAt: number; | ||
| name: string; | ||
| debug?: boolean; | ||
| } | ||
| declare class StoreRegistry implements IStoreRegistry { | ||
| private stores; | ||
| private metadata; | ||
| private listeners; | ||
| private _snapshot; | ||
| readonly name: string; | ||
| constructor(name?: string); | ||
| subscribe(listener: Listener): Unsubscribe; | ||
| register(name: string, store: IStore<any>, metadata?: Partial<StoreMetadata>): void; | ||
| unregister(name: string): boolean; | ||
| getStore(name: string): IStore<any> | undefined; | ||
| hasStore(name: string): boolean; | ||
| getStoreNames(): string[]; | ||
| getAllStores(): Map<string, IStore<any>>; | ||
| getStoreMetadata(nameOrStore: string | IStore<any>): StoreMetadata | undefined; | ||
| updateStoreMetadata(nameOrStore: string | IStore<any>, metadata: Partial<StoreMetadata>): boolean; | ||
| getSnapshot(): Array<[string, IStore<any>]>; | ||
| clear(): void; | ||
| dispose(): void; | ||
| getStoreCount(): number; | ||
| forEach(callback: (store: IStore<any>, name: string) => void): void; | ||
| getStats(): { | ||
| totalStores: number; | ||
| storeNames: string[]; | ||
| registryName: string; | ||
| }; | ||
| private _updateSnapshot; | ||
| private _notifyListeners; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/error-handling.d.ts | ||
| declare enum ContextActionErrorType { | ||
| STORE_ERROR = "STORE_ERROR", | ||
| ACTION_ERROR = "ACTION_ERROR", | ||
| REF_ERROR = "REF_ERROR", | ||
| VALIDATION_ERROR = "VALIDATION_ERROR", | ||
| INITIALIZATION_ERROR = "INITIALIZATION_ERROR", | ||
| TIMEOUT_ERROR = "TIMEOUT_ERROR", | ||
| CIRCULAR_REFERENCE_ERROR = "CIRCULAR_REFERENCE_ERROR", | ||
| } | ||
| declare class ContextActionError extends Error { | ||
| readonly type: ContextActionErrorType; | ||
| readonly context: Record<string, unknown> | undefined; | ||
| readonly timestamp: number; | ||
| constructor(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error); | ||
| } | ||
| declare function handleError(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error): ContextActionError; | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.d.ts | ||
| interface StoreErrorBoundaryProps { | ||
| children: ReactNode; | ||
| fallback?: ReactNode | ((error: ContextActionError, errorInfo: ErrorInfo) => ReactNode); | ||
| onError?: (error: ContextActionError, errorInfo: ErrorInfo) => void; | ||
| resetOnPropsChange?: boolean; | ||
| resetKeys?: Array<string | number>; | ||
| } | ||
| interface StoreErrorBoundaryState { | ||
| hasError: boolean; | ||
| error: ContextActionError | null; | ||
| errorInfo: ErrorInfo | null; | ||
| errorId: string | null; | ||
| } | ||
| declare class StoreErrorBoundary extends Component<StoreErrorBoundaryProps, StoreErrorBoundaryState> { | ||
| private resetTimeoutId; | ||
| constructor(props: StoreErrorBoundaryProps); | ||
| static getDerivedStateFromError(error: Error): Partial<StoreErrorBoundaryState>; | ||
| componentDidCatch(error: Error, errorInfo: ErrorInfo): void; | ||
| componentDidUpdate(prevProps: StoreErrorBoundaryProps): void; | ||
| componentWillUnmount(): void; | ||
| resetErrorBoundary: () => void; | ||
| render(): React$1.ReactNode; | ||
| private renderDefaultFallback; | ||
| private renderDevelopmentFallback; | ||
| private renderProductionFallback; | ||
| } | ||
| declare function withStoreErrorBoundary<P extends object>(WrappedComponent: React$1.ComponentType<P>, errorBoundaryProps?: Omit<StoreErrorBoundaryProps, 'children'>): React$1.ComponentType<P>; | ||
| declare function createStoreErrorBoundary(storeName: string, customFallback?: ReactNode): React$1.ComponentType<{ | ||
| children: ReactNode; | ||
| }>; | ||
| //#endregion | ||
| //#region src/actions/ActionContext.types.d.ts | ||
| interface ActionContextConfig extends ActionRegisterConfig { | ||
| name?: string; | ||
| schema?: ActionSchemaMap; | ||
| } | ||
| interface ActionContextType<T extends {}> { | ||
| actionRegisterRef: React.RefObject<ActionRegister<T>>; | ||
| } | ||
| interface ActionContextReturn<T extends {}> { | ||
| Provider: React.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useActionContext: () => ActionContextType<T>; | ||
| useActionDispatch: () => ActionRegister<T>['dispatch']; | ||
| useActionHandler: <K extends keyof T>(action: K, handler: ActionHandler<T[K]>, config?: HandlerConfig) => void; | ||
| useActionRegister: () => ActionRegister<T> | null; | ||
| useActionDispatchWithResult: () => { | ||
| dispatch: <K extends keyof T>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<void>; | ||
| dispatchWithResult: <K extends keyof T, R = void>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<ExecutionResult<R>>; | ||
| abortAll: () => void; | ||
| resetAbortScope: () => void; | ||
| }; | ||
| context: React.Context<ActionContextType<T> | null>; | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.d.ts | ||
| declare function createActionContext<T extends {}>(contextName: string, config?: ActionContextConfig): ActionContextReturn<T>; | ||
| declare function createActionContext<T extends {}>(config: ActionContextConfig): ActionContextReturn<T>; | ||
| //#endregion | ||
| export { StoreErrorBoundary as a, createStoreErrorBoundary as c, ContextActionErrorType as d, handleError as f, ActionContextType as i, withStoreErrorBoundary as l, ActionContextConfig as n, StoreErrorBoundaryProps as o, StoreRegistry as p, ActionContextReturn as r, StoreErrorBoundaryState as s, createActionContext as t, ContextActionError as u }; | ||
| //# sourceMappingURL=ActionContext.d.ts.map |
| {"version":3,"file":"ActionContext.d.ts","names":[],"sources":["../src/stores/core/StoreRegistry.ts","../src/stores/utils/error-handling.ts","../src/stores/components/StoreErrorBoundary.tsx","../src/actions/ActionContext.types.ts","../src/actions/ActionContext.tsx"],"sourcesContent":[],"mappings":"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"} |
| import { i as referenceEquals, n as deepEquals, o as shallowEquals, t as compareValues } from "./comparison.js"; | ||
| import React, { Component, createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useSyncExternalStore } from "react"; | ||
| import { produceWithPatches, safeGet, safeSet } from "@context-action/mutative"; | ||
| import { jsx, jsxs } from "react/jsx-runtime"; | ||
| import { ActionRegister } from "@context-action/core"; | ||
| //#region src/stores/core/StoreRegistry.ts | ||
| /** | ||
| * Centralized store registry for managing multiple Store instances | ||
| */ | ||
| var StoreRegistry = class { | ||
| constructor(name = "default") { | ||
| this.stores = /* @__PURE__ */ new Map(); | ||
| this.metadata = /* @__PURE__ */ new WeakMap(); | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this._snapshot = []; | ||
| this.name = name; | ||
| } | ||
| /** | ||
| * Subscribe to registry changes for reactive updates | ||
| */ | ||
| subscribe(listener) { | ||
| this.listeners.add(listener); | ||
| return () => { | ||
| this.listeners.delete(listener); | ||
| }; | ||
| } | ||
| /** | ||
| * Register a new store in the registry | ||
| */ | ||
| register(name, store, metadata) { | ||
| if (this.stores.has(name)) { | ||
| if (this.stores.get(name)) {} | ||
| } | ||
| this.stores.set(name, store); | ||
| if (metadata) this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name, | ||
| ...metadata | ||
| }); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Unregister a store from the registry | ||
| */ | ||
| unregister(name) { | ||
| if (!this.stores.get(name)) return false; | ||
| this.stores.delete(name); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get a store by name | ||
| */ | ||
| getStore(name) { | ||
| return this.stores.get(name); | ||
| } | ||
| /** | ||
| * Check if a store exists | ||
| */ | ||
| hasStore(name) { | ||
| return this.stores.has(name); | ||
| } | ||
| /** | ||
| * Get all registered store names | ||
| */ | ||
| getStoreNames() { | ||
| return Array.from(this.stores.keys()); | ||
| } | ||
| /** | ||
| * Get all stores as entries | ||
| */ | ||
| getAllStores() { | ||
| return new Map(this.stores); | ||
| } | ||
| /** | ||
| * Get store metadata | ||
| */ | ||
| getStoreMetadata(nameOrStore) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| return store ? this.metadata.get(store) : void 0; | ||
| } | ||
| /** | ||
| * Update store metadata | ||
| */ | ||
| updateStoreMetadata(nameOrStore, metadata) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| if (!store) return false; | ||
| const currentMetadata = this.metadata.get(store); | ||
| this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown", | ||
| ...currentMetadata, | ||
| ...metadata | ||
| }); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get registry snapshot for React integration | ||
| */ | ||
| getSnapshot() { | ||
| return this._snapshot; | ||
| } | ||
| /** | ||
| * Clear all stores from registry | ||
| */ | ||
| clear() { | ||
| this.stores.clear(); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Dispose registry and cleanup resources | ||
| */ | ||
| dispose() { | ||
| this.clear(); | ||
| this.listeners.clear(); | ||
| } | ||
| /** | ||
| * Get count of registered stores | ||
| */ | ||
| getStoreCount() { | ||
| return this.stores.size; | ||
| } | ||
| /** | ||
| * Iterate over all stores | ||
| */ | ||
| forEach(callback) { | ||
| this.stores.forEach((store, name) => { | ||
| callback(store, name); | ||
| }); | ||
| } | ||
| /** | ||
| * Get registry statistics | ||
| */ | ||
| getStats() { | ||
| return { | ||
| totalStores: this.stores.size, | ||
| storeNames: this.getStoreNames(), | ||
| registryName: this.name | ||
| }; | ||
| } | ||
| /** | ||
| * Update internal snapshot | ||
| */ | ||
| _updateSnapshot() { | ||
| this._snapshot = Array.from(this.stores.entries()); | ||
| } | ||
| /** | ||
| * Notify all listeners of registry changes | ||
| */ | ||
| _notifyListeners() { | ||
| this.listeners.forEach((listener) => { | ||
| try { | ||
| listener(); | ||
| } catch (error) { | ||
| console.error("Error in registry listener:", error); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Global default registry instance | ||
| */ | ||
| const globalStoreRegistry = new StoreRegistry("global"); | ||
| //#endregion | ||
| //#region src/stores/utils/sync-external-store-utils.ts | ||
| /** | ||
| * @fileoverview useSyncExternalStore 기반 공통 유틸리티 | ||
| * | ||
| * Store 구독 관련 공통 기능을 useSyncExternalStore 기반으로 구현 | ||
| * 모든 Store 훅들이 공유하는 핵심 로직을 제공 | ||
| */ | ||
| /** | ||
| * 향상된 구독 함수 생성 (내부 사용) | ||
| * 디바운싱, 스로틀링, 조건부 구독 기능 제공 | ||
| */ | ||
| function createEnhancedSubscriber(store, options = {}) { | ||
| const { debounce, throttle, condition, debug, name = "unknown" } = options; | ||
| return (callback) => { | ||
| if (!store) return () => {}; | ||
| let debounceTimer = null; | ||
| let throttleTimer = null; | ||
| let lastThrottleTime = 0; | ||
| const enhancedCallback = () => { | ||
| if (condition && !condition()) { | ||
| if (debug) console.debug(`[${name}] Subscription suspended due to condition`); | ||
| return; | ||
| } | ||
| const now = performance.now(); | ||
| if (throttle && throttle > 0) { | ||
| if (now - lastThrottleTime < throttle) { | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| throttleTimer = setTimeout(() => { | ||
| lastThrottleTime = performance.now(); | ||
| callback(); | ||
| }, throttle - (now - lastThrottleTime)); | ||
| return; | ||
| } | ||
| lastThrottleTime = now; | ||
| } | ||
| if (debounce && debounce > 0) { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| debounceTimer = setTimeout(() => { | ||
| callback(); | ||
| if (debug) console.debug(`[${name}] Debounced callback executed after ${debounce}ms`); | ||
| }, debounce); | ||
| return; | ||
| } | ||
| callback(); | ||
| }; | ||
| const unsubscribe = store.subscribe(enhancedCallback); | ||
| return () => { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| unsubscribe(); | ||
| }; | ||
| }; | ||
| } | ||
| /** | ||
| * Null-safe Store 구독 훅 | ||
| * useSyncExternalStore를 기반으로 한 안전한 구독 | ||
| */ | ||
| function useSafeStoreSubscription(store, selector, options = {}) { | ||
| const { initialValue, equalityFn, debounce, throttle, condition, debug, name } = options; | ||
| const stableSubscriptionOptions = useMemo(() => ({ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| }), [ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| ]); | ||
| const needsEnhancedSubscription = Boolean(debounce || throttle || condition); | ||
| const subscribe = useCallback((callback) => { | ||
| if (!store) return () => {}; | ||
| if (needsEnhancedSubscription) return createEnhancedSubscriber(store, stableSubscriptionOptions)(callback); | ||
| return store.subscribe(callback); | ||
| }, [ | ||
| store, | ||
| needsEnhancedSubscription, | ||
| stableSubscriptionOptions | ||
| ]); | ||
| const getSnapshot = useCallback(() => { | ||
| if (!store) return initialValue; | ||
| const snapshot = store.getSnapshot(); | ||
| return selector ? selector(snapshot.value) : snapshot.value; | ||
| }, [ | ||
| store, | ||
| selector, | ||
| initialValue | ||
| ]); | ||
| const cachedSnapshotRef = useRef(void 0); | ||
| const stableGetSnapshot = useCallback(() => { | ||
| const currentSnapshot = getSnapshot(); | ||
| if (equalityFn && cachedSnapshotRef.current !== void 0) { | ||
| if (equalityFn(cachedSnapshotRef.current, currentSnapshot)) return cachedSnapshotRef.current; | ||
| } | ||
| cachedSnapshotRef.current = currentSnapshot; | ||
| return currentSnapshot; | ||
| }, [getSnapshot, equalityFn]); | ||
| const getServerSnapshot = useCallback(() => { | ||
| return initialValue; | ||
| }, [initialValue]); | ||
| return useSyncExternalStore(subscribe, equalityFn ? stableGetSnapshot : getSnapshot, getServerSnapshot); | ||
| } | ||
| /** | ||
| * 기본 동등성 비교 함수들 | ||
| * comparison.ts의 함수들을 래핑하여 hook에서 사용하기 편한 인터페이스 제공 | ||
| */ | ||
| const equalityFunctions = { | ||
| reference: (a, b) => referenceEquals(a, b), | ||
| shallow: (a, b) => shallowEquals(a, b), | ||
| deep: (a, b) => deepEquals(a, b), | ||
| smart: (a, b) => { | ||
| if (referenceEquals(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| return a.every((item, index) => { | ||
| const bItem = b[index]; | ||
| if (typeof item === "object" && item !== null && typeof bItem === "object" && bItem !== null) return shallowEquals(item, bItem); | ||
| return referenceEquals(item, bItem); | ||
| }); | ||
| } | ||
| return shallowEquals(a, b); | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreSelector.ts | ||
| /** | ||
| * Store Selector Hook - Performance optimization through selective subscription | ||
| * | ||
| * Advanced store subscription hooks that prevent unnecessary re-renders by subscribing | ||
| * to specific parts of store data using selector functions and intelligent equality comparison. | ||
| * Essential for building high-performance React applications with complex state management. | ||
| * | ||
| * @module stores/hooks/useStoreSelector | ||
| */ | ||
| const defaultEqualityFn = equalityFunctions.smart; | ||
| const shallowEqual = equalityFunctions.shallow; | ||
| const deepEqual = equalityFunctions.deep; | ||
| const smartEqual = equalityFunctions.smart; | ||
| /** | ||
| * Hook for selective store subscription with performance optimization | ||
| * | ||
| * Subscribes to specific parts of store data using a selector function, | ||
| * triggering re-renders only when the selected value actually changes. | ||
| * Essential for preventing unnecessary re-renders in complex applications. | ||
| * | ||
| * @template T - Type of the store value | ||
| * @template R - Type of the value returned by the selector | ||
| * | ||
| * @param store - Store instance to subscribe to | ||
| * @param selector - Function to extract needed data from store value | ||
| * @param equalityFn - Function to compare previous and new values (default: Object.is) | ||
| * | ||
| * @returns The value returned by the selector function | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usestoreselector-advanced-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function useStoreSelector(store, selector, equalityFn = defaultEqualityFn) { | ||
| "use memo"; | ||
| const stableSelector = useCallback(selector, [selector]); | ||
| const stableEqualityFn = useCallback(equalityFn, [equalityFn]); | ||
| const selectorWarningShownRef = useRef(false); | ||
| if (selector !== stableSelector && !selectorWarningShownRef.current) { | ||
| console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name); | ||
| selectorWarningShownRef.current = true; | ||
| } | ||
| const previousValueRef = useRef(void 0); | ||
| const subscribe = useCallback((callback) => { | ||
| return store.subscribe(callback); | ||
| }, [store]); | ||
| const getSnapshot = useCallback(() => { | ||
| try { | ||
| const selectedValue = stableSelector(store.getValue()); | ||
| if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current; | ||
| previousValueRef.current = selectedValue; | ||
| return selectedValue; | ||
| } catch (error) { | ||
| console.error("useStoreSelector: Error in selector function:", error); | ||
| throw error; | ||
| } | ||
| }, [ | ||
| store, | ||
| stableSelector, | ||
| stableEqualityFn | ||
| ]); | ||
| return useSyncExternalStore(subscribe, getSnapshot, getSnapshot); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/type-guards.ts | ||
| function isRefState(value) { | ||
| return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean"; | ||
| } | ||
| /** | ||
| * DOM Event 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMEvent(value) { | ||
| return value instanceof Event; | ||
| } | ||
| /** | ||
| * Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체) | ||
| */ | ||
| function isEventLike(value) { | ||
| return typeof value === "object" && value !== null && typeof value.preventDefault === "function"; | ||
| } | ||
| /** | ||
| * target 프로퍼티를 가진 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function hasTargetProperty(value) { | ||
| return typeof value === "object" && value !== null && "target" in value; | ||
| } | ||
| /** | ||
| * DOM Element인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMElement(value) { | ||
| return value instanceof Element; | ||
| } | ||
| /** | ||
| * 객체인지 확인하는 타입 가드 (null 제외) | ||
| */ | ||
| function isObject(value) { | ||
| return typeof value === "object" && value !== null && !Array.isArray(value); | ||
| } | ||
| /** | ||
| * 복합 타입 가드: Event 객체로 의심되는 객체인지 확인 | ||
| * RefState가 아니면서 Event 관련 속성을 가진 객체를 감지 | ||
| */ | ||
| function isSuspiciousEventObject(value, checkNested = true) { | ||
| if (!isObject(value) || isRefState(value)) return false; | ||
| if (isEventLikeObject(value)) return true; | ||
| if (checkNested) { | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const nestedValue = value[key]; | ||
| if (isEventLikeObject(nestedValue)) return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * 단일 객체가 이벤트와 같은지 확인 | ||
| */ | ||
| function isEventLikeObject(value) { | ||
| if (!isObject(value)) return false; | ||
| const hasEventTarget = hasTargetProperty(value); | ||
| const hasPreventDefault = isEventLike(value); | ||
| const isEvent = isDOMEvent(value); | ||
| const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault); | ||
| const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value; | ||
| const constructorName = value?.constructor?.name; | ||
| const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false; | ||
| return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor; | ||
| } | ||
| /** | ||
| * 문제가 될 수 있는 속성들을 찾아내는 함수 | ||
| */ | ||
| function findProblematicProperties(value) { | ||
| if (!isObject(value)) return []; | ||
| const problematicKeys = []; | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const prop = value[key]; | ||
| if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key); | ||
| } | ||
| return problematicKeys; | ||
| } | ||
| /** | ||
| * 통합 타입 가드 객체 | ||
| * 모든 타입 가드 함수들을 하나의 객체로 export | ||
| */ | ||
| const TypeGuards = { | ||
| isRefState, | ||
| isDOMEvent, | ||
| isEventLike, | ||
| hasTargetProperty, | ||
| isDOMElement, | ||
| isObject, | ||
| isSuspiciousEventObject, | ||
| findProblematicProperties | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/utils/error-handling.ts | ||
| /** | ||
| * @fileoverview Error Handling Utilities | ||
| * | ||
| * 일관된 에러 처리를 위한 유틸리티 함수들 | ||
| * Context-Action 프레임워크 전반에 걸친 표준화된 에러 처리 패턴 | ||
| */ | ||
| /** | ||
| * Context-Action 프레임워크의 에러 유형 정의 | ||
| */ | ||
| let ContextActionErrorType = /* @__PURE__ */ function(ContextActionErrorType$1) { | ||
| ContextActionErrorType$1["STORE_ERROR"] = "STORE_ERROR"; | ||
| ContextActionErrorType$1["ACTION_ERROR"] = "ACTION_ERROR"; | ||
| ContextActionErrorType$1["REF_ERROR"] = "REF_ERROR"; | ||
| ContextActionErrorType$1["VALIDATION_ERROR"] = "VALIDATION_ERROR"; | ||
| ContextActionErrorType$1["INITIALIZATION_ERROR"] = "INITIALIZATION_ERROR"; | ||
| ContextActionErrorType$1["TIMEOUT_ERROR"] = "TIMEOUT_ERROR"; | ||
| ContextActionErrorType$1["CIRCULAR_REFERENCE_ERROR"] = "CIRCULAR_REFERENCE_ERROR"; | ||
| return ContextActionErrorType$1; | ||
| }({}); | ||
| /** | ||
| * Context-Action 프레임워크의 표준 에러 클래스 | ||
| */ | ||
| var ContextActionError = class ContextActionError extends Error { | ||
| constructor(type, message, context, originalError) { | ||
| super(message); | ||
| this.name = "ContextActionError"; | ||
| this.type = type; | ||
| this.context = context ?? void 0; | ||
| this.timestamp = Date.now(); | ||
| if (Error.captureStackTrace) Error.captureStackTrace(this, ContextActionError); | ||
| if (originalError) this.stack = `${this.stack}\nCaused by: ${originalError.stack}`; | ||
| } | ||
| }; | ||
| /** | ||
| * 에러 로깅 레벨 | ||
| */ | ||
| let ErrorLogLevel = /* @__PURE__ */ function(ErrorLogLevel$1) { | ||
| ErrorLogLevel$1[ErrorLogLevel$1["SILENT"] = 0] = "SILENT"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["ERROR"] = 1] = "ERROR"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["WARN"] = 2] = "WARN"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["INFO"] = 3] = "INFO"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["DEBUG"] = 4] = "DEBUG"; | ||
| return ErrorLogLevel$1; | ||
| }({}); | ||
| /** | ||
| * 현재 에러 핸들링 설정 | ||
| */ | ||
| let currentErrorConfig = { | ||
| logLevel: ErrorLogLevel.DEBUG, | ||
| throwOnError: true, | ||
| enableStackTrace: true, | ||
| maxLogEntries: 100, | ||
| suppressRepeatedErrors: true, | ||
| logErrors: true | ||
| }; | ||
| /** | ||
| * 에러 로그 저장소 | ||
| */ | ||
| let errorLog = []; | ||
| let errorSignatures = /* @__PURE__ */ new Map(); | ||
| /** | ||
| * 에러 시그니처 생성 (중복 에러 감지용) | ||
| */ | ||
| function createErrorSignature(error) { | ||
| return `${error.type}:${error.message}:${error.context?.component || "unknown"}`; | ||
| } | ||
| /** | ||
| * 표준화된 에러 처리 함수 (통합된 에러 바운더리 사용) | ||
| */ | ||
| function handleError(type, message, context, originalError) { | ||
| const error = new ContextActionError(type, message, context, originalError); | ||
| logError(error); | ||
| if (currentErrorConfig.throwOnError) throw error; | ||
| return error; | ||
| } | ||
| /** | ||
| * 에러 로깅 함수 | ||
| */ | ||
| function logError(error) { | ||
| const signature = createErrorSignature(error); | ||
| if (currentErrorConfig.suppressRepeatedErrors) { | ||
| const existingEntry = errorSignatures.get(signature); | ||
| if (existingEntry) { | ||
| existingEntry.count++; | ||
| existingEntry.lastOccurred = Date.now(); | ||
| if (existingEntry.count % 10 === 0) console.warn(`[Context-Action] Repeated error occurred ${existingEntry.count} times:`, error); | ||
| return; | ||
| } | ||
| } | ||
| const logEntry = { | ||
| error, | ||
| count: 1, | ||
| lastOccurred: Date.now() | ||
| }; | ||
| errorLog.push(logEntry); | ||
| errorSignatures.set(signature, logEntry); | ||
| if (errorLog.length > currentErrorConfig.maxLogEntries) { | ||
| const removedEntry = errorLog.shift(); | ||
| if (removedEntry) { | ||
| const removedSignature = createErrorSignature(removedEntry.error); | ||
| errorSignatures.delete(removedSignature); | ||
| } | ||
| } | ||
| if (typeof globalThis !== "undefined" && globalThis.globalErrorBoundary) globalThis.globalErrorBoundary.reportError(error); | ||
| switch (currentErrorConfig.logLevel) { | ||
| case ErrorLogLevel.DEBUG: | ||
| console.debug("[Context-Action] Debug:", error); | ||
| break; | ||
| case ErrorLogLevel.INFO: | ||
| console.info("[Context-Action] Info:", error); | ||
| break; | ||
| case ErrorLogLevel.WARN: | ||
| console.warn("[Context-Action] Warning:", error); | ||
| break; | ||
| case ErrorLogLevel.ERROR: | ||
| console.error("[Context-Action] Error:", error); | ||
| if (currentErrorConfig.enableStackTrace && error.stack) console.error("Stack trace:", error.stack); | ||
| break; | ||
| case ErrorLogLevel.SILENT: break; | ||
| } | ||
| } | ||
| /** | ||
| * 특정 에러 타입에 대한 전용 핸들러들 | ||
| */ | ||
| const ErrorHandlers = { | ||
| store: (message, context, originalError) => { | ||
| const enhancedMessage = `[Store Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.STORE_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| action: (message, context, originalError) => { | ||
| const enhancedMessage = `[Action Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.ACTION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| ref: (message, context, originalError) => { | ||
| const enhancedMessage = `[Ref Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.REF_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| validation: (message, context, originalError) => { | ||
| const enhancedMessage = `[Validation Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.VALIDATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| initialization: (message, context, originalError) => { | ||
| const enhancedMessage = `[Initialization Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.INITIALIZATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| timeout: (message, context, originalError) => { | ||
| const enhancedMessage = `[Timeout Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.TIMEOUT_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| circularReference: (message, context, originalError) => handleError(ContextActionErrorType.CIRCULAR_REFERENCE_ERROR, message, context, originalError) | ||
| }; | ||
| /** | ||
| * 에러 통계 가져오기 | ||
| */ | ||
| function getErrorStatistics() { | ||
| const errorsByType = Object.values(ContextActionErrorType).reduce((acc, type) => { | ||
| acc[type] = 0; | ||
| return acc; | ||
| }, {}); | ||
| errorLog.forEach((entry) => { | ||
| errorsByType[entry.error.type] += entry.count; | ||
| }); | ||
| const mostFrequentErrors = Array.from(errorSignatures.entries()).map(([signature, entry]) => ({ | ||
| signature, | ||
| count: entry.count, | ||
| lastOccurred: entry.lastOccurred | ||
| })).sort((a, b) => b.count - a.count).slice(0, 10); | ||
| const recentErrors = errorLog.slice(-10).map((entry) => entry.error); | ||
| return { | ||
| totalErrors: errorLog.reduce((sum, entry) => sum + entry.count, 0), | ||
| errorsByType, | ||
| mostFrequentErrors, | ||
| recentErrors | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/core/Store.ts | ||
| /** | ||
| * Deep freeze an object to make it immutable | ||
| * Prevents modifications to the returned value from affecting cached state | ||
| */ | ||
| function deepFreeze(obj) { | ||
| if (obj === null || typeof obj !== "object") return obj; | ||
| const proto = Object.getPrototypeOf(obj); | ||
| if (proto !== Object.prototype && proto !== Array.prototype) return obj; | ||
| Object.freeze(obj); | ||
| for (const key of Object.keys(obj)) { | ||
| const value = obj[key]; | ||
| if (value !== null && typeof value === "object") deepFreeze(value); | ||
| } | ||
| return obj; | ||
| } | ||
| /** | ||
| * Core Store class for centralized state management with memory leak prevention | ||
| * | ||
| * Provides reactive state management with subscription capabilities, optimized for | ||
| * React integration through useSyncExternalStore. Features advanced cleanup mechanisms, | ||
| * automatic resource management, and comprehensive memory leak prevention. | ||
| * | ||
| * Key Features: | ||
| * - Automatic cleanup task registration and execution | ||
| * - Memory leak prevention with disposal patterns | ||
| * - Race condition protection for async operations | ||
| * - Advanced error recovery with exponential backoff | ||
| * - Resource monitoring and threshold management | ||
| * | ||
| * @template T - The type of value stored in this store | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const userStore = createStore('user', { name: '', age: 0 }); | ||
| * | ||
| * // Register cleanup tasks | ||
| * const unregister = userStore.registerCleanup(() => { | ||
| * console.log('Cleaning up user store resources'); | ||
| * }); | ||
| * | ||
| * // Automatic cleanup on disposal | ||
| * userStore.dispose(); | ||
| * ``` | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * @public | ||
| */ | ||
| var Store = class { | ||
| constructor(name, initialValue) { | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this.patchAwareListeners = /* @__PURE__ */ new Set(); | ||
| this._lastPatches = null; | ||
| this._lastClonedValue = null; | ||
| this._lastClonedVersion = 0; | ||
| this._version = 0; | ||
| this.isUpdating = false; | ||
| this.updateQueue = []; | ||
| this.notificationMode = "batched"; | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| this.pendingUpdatesCount = 0; | ||
| this.cleanupTasks = /* @__PURE__ */ new Set(); | ||
| this.isDisposed = false; | ||
| this.errorCount = 0; | ||
| this.lastErrorTime = 0; | ||
| this.MAX_ERROR_COUNT = 5; | ||
| this.ERROR_RESET_TIME = 6e4; | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.cloningEnabled = true; | ||
| this.subscribe = (listener) => { | ||
| if (this.isDisposed) { | ||
| console.warn(`Cannot subscribe to disposed store "${this.name}"`); | ||
| return () => {}; | ||
| } | ||
| const enhancedListener = () => { | ||
| if (this.isDisposed) return; | ||
| try { | ||
| listener(); | ||
| if (this.errorCount > 0) this.errorCount = 0; | ||
| } catch (error) { | ||
| this._handleListenerError(error, listener); | ||
| } | ||
| }; | ||
| this.subscriptionRegistry.set(listener, { | ||
| subscribedAt: Date.now(), | ||
| errorCount: 0, | ||
| enhancedListener | ||
| }); | ||
| this.listeners.add(enhancedListener); | ||
| return () => { | ||
| this.listeners.delete(enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| }; | ||
| }; | ||
| this.subscribeWithPatches = (listener) => { | ||
| if (this.isDisposed) { | ||
| console.warn(`Cannot subscribe to disposed store "${this.name}"`); | ||
| return () => {}; | ||
| } | ||
| this.patchAwareListeners.add(listener); | ||
| return () => this.patchAwareListeners.delete(listener); | ||
| }; | ||
| this.getSnapshot = () => { | ||
| return this._snapshot; | ||
| }; | ||
| this.name = name; | ||
| this._value = initialValue; | ||
| this._snapshot = this._createSnapshot(); | ||
| } | ||
| /** | ||
| * Get the patches from the last state change | ||
| * | ||
| * Returns the JSON patches that describe the most recent update, | ||
| * or null if no patches are available (e.g., initial state or full replacement). | ||
| * | ||
| * @returns Array of JSON patches or null | ||
| */ | ||
| getLastPatches() { | ||
| return this._lastPatches; | ||
| } | ||
| /** | ||
| * 현재 값 직접 가져오기 (액션 핸들러용) | ||
| * 핵심 로직: 불변성을 보장하는 깊은 복사본 반환 | ||
| * | ||
| * @implements lazy-evaluation | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 사용 시나리오: Action handler에서 최신 상태 읽기 | ||
| * 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨 | ||
| */ | ||
| getValue() { | ||
| if (typeof this._value !== "object" || this._value === null) return this._value; | ||
| if (this.cloningEnabled) { | ||
| if (this._lastClonedVersion === this._version && this._lastClonedValue !== null) return this._lastClonedValue; | ||
| this._lastClonedValue = deepFreeze(safeGet(this._value, this.cloningEnabled)); | ||
| this._lastClonedVersion = this._version; | ||
| return this._lastClonedValue; | ||
| } | ||
| return this._value; | ||
| } | ||
| /** | ||
| * Store 값 설정 및 구독자 알림 | ||
| * 핵심 로직: | ||
| * 1. 입력값의 불변성 보장을 위한 깊은 복사 (선택적 skip 가능) | ||
| * 2. 강화된 값 비교 시스템으로 불필요한 리렌더링 방지 | ||
| * 3. Structural sharing을 통한 성능 최적화 | ||
| * 4. 값 변경 시에만 스냅샷 재생성 및 알림 | ||
| * | ||
| * @implements unidirectional-data-flow | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 보안 강화: 입력값을 복사하여 Store 내부 상태가 외부 참조에 의해 변경되지 않도록 보호 | ||
| * 성능 강화: 다층 비교 시스템으로 정확한 변경 감지 및 렌더링 최적화 | ||
| */ | ||
| setValue(value, options) { | ||
| if (TypeGuards.isObject(value)) { | ||
| if (!TypeGuards.isRefState(value) && TypeGuards.isSuspiciousEventObject(value)) { | ||
| const eventHandling = options?.eventHandling || "block"; | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(value); | ||
| const hasPreventDefault = TypeGuards.isEventLike(value); | ||
| const isEvent = TypeGuards.isDOMEvent(value); | ||
| switch (eventHandling) { | ||
| case "allow": break; | ||
| case "transform": | ||
| if (options?.eventTransform) try { | ||
| value = options.eventTransform(value); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Event transformation failed in Store.setValue", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| error: error instanceof Error ? error.message : String(error) | ||
| }); | ||
| return; | ||
| } | ||
| else { | ||
| ErrorHandlers.store("Event transformation requested but no transform function provided", { | ||
| storeName: this.name, | ||
| valueType: typeof value | ||
| }); | ||
| return; | ||
| } | ||
| break; | ||
| case "block": | ||
| default: | ||
| ErrorHandlers.store("Event object detected in Store.setValue - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| constructorName: value?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(value) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| const safeValue = options?.skipClone ? value : safeSet(value, this.cloningEnabled); | ||
| let hasChanged = true; | ||
| if (!options?.skipComparison) hasChanged = this._compareValues(this._value, safeValue); | ||
| if (hasChanged) { | ||
| if (this.patchAwareListeners.size > 0 && TypeGuards.isObject(this._value) && TypeGuards.isObject(safeValue)) try { | ||
| const [, patches] = produceWithPatches(this._value, (draft) => { | ||
| const draftKeys = Object.keys(draft); | ||
| const valueKeys = Object.keys(safeValue); | ||
| for (const key of draftKeys) if (!Object.prototype.hasOwnProperty.call(safeValue, key)) delete draft[key]; | ||
| for (const key of valueKeys) draft[key] = safeValue[key]; | ||
| }); | ||
| this._lastPatches = patches; | ||
| } catch { | ||
| this._lastPatches = null; | ||
| } | ||
| else this._lastPatches = null; | ||
| this._value = safeValue; | ||
| this._version++; | ||
| this._snapshot = this._createSnapshot(); | ||
| this._scheduleNotification(); | ||
| } | ||
| } | ||
| /** | ||
| * Update value using updater function with Mutative integration | ||
| * 핵심 로직: | ||
| * 1. Mutative create를 사용하여 draft 객체 제공 (패치 캡처 포함) | ||
| * 2. updater 결과를 불변성을 보장하며 설정 | ||
| * | ||
| * @implements store-immutability | ||
| * 보안 강화: Mutative draft를 통한 안전한 상태 수정 | ||
| */ | ||
| update(updater) { | ||
| if (this.isUpdating) { | ||
| this.updateQueue.push(() => this.update(updater)); | ||
| return; | ||
| } | ||
| try { | ||
| this.isUpdating = true; | ||
| let updatedValue; | ||
| let patches = null; | ||
| try { | ||
| const [nextState, capturedPatches] = produceWithPatches(this._value, (draft) => { | ||
| const result = updater(draft); | ||
| if (result !== void 0) return result; | ||
| }); | ||
| updatedValue = nextState; | ||
| patches = capturedPatches; | ||
| } catch (mutativeError) { | ||
| console.warn("[Store] Mutative update failed, falling back to safe copy method", mutativeError); | ||
| const safeCurrentValue = safeGet(this._value, this.cloningEnabled); | ||
| try { | ||
| const [nextState, capturedPatches] = produceWithPatches(safeCurrentValue, (draft) => { | ||
| const result = updater(draft); | ||
| if (result !== void 0) return result; | ||
| }); | ||
| updatedValue = nextState; | ||
| patches = capturedPatches; | ||
| } catch (secondMutativeError) { | ||
| console.warn("[Store] Mutative completely failed, using direct update (immutability not guaranteed)", secondMutativeError); | ||
| try { | ||
| const result = updater(safeCurrentValue); | ||
| updatedValue = result !== void 0 ? result : safeCurrentValue; | ||
| } catch (updaterError) { | ||
| console.warn("[Store] Updater function threw an error, update aborted", updaterError); | ||
| return; | ||
| } | ||
| patches = null; | ||
| } | ||
| } | ||
| if (TypeGuards.isObject(updatedValue)) { | ||
| if (!TypeGuards.isRefState(updatedValue) && TypeGuards.isSuspiciousEventObject(updatedValue)) { | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(updatedValue); | ||
| const hasPreventDefault = TypeGuards.isEventLike(updatedValue); | ||
| const isEvent = TypeGuards.isDOMEvent(updatedValue); | ||
| ErrorHandlers.store("Event object detected in Store.update result - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| updatedValueType: typeof updatedValue, | ||
| constructorName: updatedValue?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(updatedValue) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| if (this._compareValues(this._value, updatedValue)) { | ||
| this._lastPatches = patches; | ||
| this._value = updatedValue; | ||
| this._version++; | ||
| this._snapshot = this._createSnapshot(); | ||
| this._scheduleNotification(); | ||
| } | ||
| } finally { | ||
| this.isUpdating = false; | ||
| if (this.updateQueue.length > 0) { | ||
| const nextUpdate = this.updateQueue.shift(); | ||
| if (nextUpdate) Promise.resolve().then(nextUpdate); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Get number of active listeners (includes patch-aware listeners) | ||
| */ | ||
| getListenerCount() { | ||
| return this.listeners.size + this.patchAwareListeners.size; | ||
| } | ||
| /** | ||
| * Clear all listeners (includes patch-aware listeners) | ||
| */ | ||
| clearListeners() { | ||
| this.listeners.clear(); | ||
| this.patchAwareListeners.clear(); | ||
| } | ||
| /** | ||
| * Manually notify path-based subscribers without changing state value | ||
| * | ||
| * Useful for external systems (WebSocket, async operations) that need to | ||
| * trigger UI updates for specific paths without actual state changes. | ||
| * | ||
| * @param path - The path to notify subscribers about | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // External async logic | ||
| * async function fetchData(store: Store<AppState>) { | ||
| * store.notifyPath(['ui', 'loading']); // Trigger loading UI | ||
| * const data = await api.fetch(); | ||
| * store.setValue({ ...store.getValue(), data }); | ||
| * } | ||
| * ``` | ||
| */ | ||
| notifyPath(path) { | ||
| if (this.isDisposed) return; | ||
| this._lastPatches = [{ | ||
| op: "replace", | ||
| path, | ||
| value: this._getValueAtPath(path) | ||
| }]; | ||
| this._scheduleNotification(); | ||
| } | ||
| /** | ||
| * Manually notify multiple paths at once | ||
| * | ||
| * @param paths - Array of paths to notify subscribers about | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * store.notifyPaths([ | ||
| * ['ui', 'loading'], | ||
| * ['ui', 'progress'] | ||
| * ]); | ||
| * ``` | ||
| */ | ||
| notifyPaths(paths) { | ||
| if (this.isDisposed) return; | ||
| if (paths.length === 0) return; | ||
| this._lastPatches = paths.map((path) => ({ | ||
| op: "replace", | ||
| path, | ||
| value: this._getValueAtPath(path) | ||
| })); | ||
| this._scheduleNotification(); | ||
| } | ||
| /** | ||
| * Get value at a specific path in the store | ||
| * @private | ||
| */ | ||
| _getValueAtPath(path) { | ||
| let current = this._value; | ||
| for (const segment of path) { | ||
| if (current === null || current === void 0) return; | ||
| current = current[segment]; | ||
| } | ||
| return current; | ||
| } | ||
| /** | ||
| * Register cleanup task for automatic execution on disposal | ||
| * | ||
| * Registers a cleanup function that will be automatically called when the store | ||
| * is disposed. This prevents memory leaks and ensures proper resource cleanup. | ||
| * | ||
| * @param task - Cleanup function to register | ||
| * @returns Unregister function to remove the cleanup task | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const timer = setInterval(() => {}, 1000); | ||
| * const unregister = store.registerCleanup(() => clearInterval(timer)); | ||
| * | ||
| * // Later, remove the cleanup task if needed | ||
| * unregister(); | ||
| * ``` | ||
| */ | ||
| registerCleanup(task) { | ||
| if (this.isDisposed) { | ||
| console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`); | ||
| return () => {}; | ||
| } | ||
| this.cleanupTasks.add(task); | ||
| return () => this.cleanupTasks.delete(task); | ||
| } | ||
| /** | ||
| * Enhanced Store disposal with comprehensive cleanup | ||
| * | ||
| * Performs complete cleanup of all store resources including listeners, | ||
| * timers, cleanup tasks, and internal state. Prevents memory leaks and | ||
| * ensures proper resource disposal. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Manual disposal | ||
| * store.dispose(); | ||
| * | ||
| * // Auto-disposal with useEffect | ||
| * useEffect(() => { | ||
| * return () => store.dispose(); | ||
| * }, [store]); | ||
| * ``` | ||
| */ | ||
| dispose() { | ||
| if (this.isDisposed) return; | ||
| this.isDisposed = true; | ||
| try { | ||
| this.cleanupTasks.forEach((task) => { | ||
| try { | ||
| task(); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error during cleanup task execution", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| }); | ||
| this.cleanupTasks.clear(); | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.clearListeners(); | ||
| if (this.animationFrameId !== null) { | ||
| cancelAnimationFrame(this.animationFrameId); | ||
| this.animationFrameId = null; | ||
| } | ||
| this.pendingNotification = false; | ||
| this.updateQueue.length = 0; | ||
| } catch (error) { | ||
| ErrorHandlers.store("Critical error during store disposal", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| } | ||
| /** | ||
| * Check if store is disposed | ||
| * @returns true if store has been disposed | ||
| */ | ||
| isStoreDisposed() { | ||
| return this.isDisposed; | ||
| } | ||
| /** | ||
| * Store별 커스텀 비교 함수 설정 | ||
| * 이 Store에만 적용되는 특별한 비교 로직 설정 | ||
| * | ||
| * @param comparator - 커스텀 비교 함수 (oldValue, newValue) => boolean | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setCustomComparator(comparator) { | ||
| this.customComparator = comparator; | ||
| } | ||
| /** | ||
| * Store별 비교 옵션 설정 | ||
| * 이 Store에만 적용되는 비교 전략 설정 | ||
| * | ||
| * @param options - 비교 옵션 | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setComparisonOptions(options) { | ||
| this.comparisonOptions = options; | ||
| } | ||
| /** | ||
| * 성능 최적화: Store별 복사 동작 제어 | ||
| * | ||
| * @param enabled - true: 복사 활성화 (안전), false: 복사 비활성화 (성능 우선) | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/performance | ||
| */ | ||
| setCloningEnabled(enabled) { | ||
| this.cloningEnabled = enabled; | ||
| } | ||
| /** | ||
| * 현재 복사 설정 조회 | ||
| */ | ||
| isCloningEnabled() { | ||
| return this.cloningEnabled; | ||
| } | ||
| /** | ||
| * 강화된 값 비교 시스템 | ||
| * 1. 커스텀 비교 함수 우선 사용 | ||
| * 2. Store별 비교 옵션 적용 | ||
| * 3. 성능 최적화된 빠른 비교 fallback | ||
| * 4. 전역 비교 설정 사용 | ||
| * | ||
| * @param oldValue - 이전 값 | ||
| * @param newValue - 새로운 값 | ||
| * @returns true if values are different (change detected), false if same | ||
| * @protected | ||
| */ | ||
| _compareValues(oldValue, newValue) { | ||
| let result; | ||
| try { | ||
| if (this.customComparator) result = !this.customComparator(oldValue, newValue); | ||
| else if (this.comparisonOptions) result = !compareValues(oldValue, newValue, this.comparisonOptions); | ||
| else result = !compareValues(oldValue, newValue, { strategy: "reference" }); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error during value comparison, falling back to reference comparison", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| result = !Object.is(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| _createSnapshot() { | ||
| return { | ||
| value: deepFreeze(safeGet(this._value, this.cloningEnabled)), | ||
| name: this.name, | ||
| lastUpdate: Date.now() | ||
| }; | ||
| } | ||
| /** | ||
| * requestAnimationFrame 기반 알림 스케줄링 | ||
| * 브라우저의 다음 프레임에서 리스너 알림 실행 | ||
| */ | ||
| _scheduleNotification() { | ||
| if (this.notificationMode === "immediate") this._notifyListeners(); | ||
| else this._scheduleWithRAF(); | ||
| } | ||
| /** | ||
| * requestAnimationFrame을 사용한 알림 스케줄링 | ||
| * 누적 가능한 배치 시스템으로 개선 | ||
| */ | ||
| _scheduleWithRAF() { | ||
| this.pendingUpdatesCount++; | ||
| if (!this.pendingNotification) { | ||
| this.pendingNotification = true; | ||
| this.animationFrameId = requestAnimationFrame(() => { | ||
| this._executeNotification(); | ||
| }); | ||
| } | ||
| } | ||
| /** | ||
| * 스케줄된 알림 실행 | ||
| */ | ||
| _executeNotification() { | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| const batchedUpdates = this.pendingUpdatesCount; | ||
| this.pendingUpdatesCount = 0; | ||
| this._notifyListeners(); | ||
| if (batchedUpdates > 1) console.debug(`[Store:${this.name}] Batched ${batchedUpdates} updates in single frame`); | ||
| } | ||
| /** | ||
| * Handle listener execution errors with recovery strategies | ||
| */ | ||
| _handleListenerError(error, listener) { | ||
| const now = Date.now(); | ||
| if (now - this.lastErrorTime > this.ERROR_RESET_TIME) this.errorCount = 0; | ||
| this.errorCount++; | ||
| this.lastErrorTime = now; | ||
| const metadata = this.subscriptionRegistry.get(listener); | ||
| if (metadata) metadata.errorCount++; | ||
| ErrorHandlers.store("Error in store listener execution", { | ||
| storeName: this.name, | ||
| listenerCount: this.listeners.size, | ||
| errorCount: this.errorCount, | ||
| subscriptionAge: metadata ? now - metadata.subscribedAt : "unknown" | ||
| }, error instanceof Error ? error : void 0); | ||
| if (metadata && metadata.errorCount >= 3) { | ||
| console.warn(`Removing problematic listener from store "${this.name}" after ${metadata.errorCount} errors`); | ||
| this.listeners.delete(metadata.enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| } | ||
| if (this.errorCount >= this.MAX_ERROR_COUNT) { | ||
| console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`); | ||
| this.clearListeners(); | ||
| } | ||
| } | ||
| _notifyListeners() { | ||
| if (this.isDisposed) return; | ||
| this.listeners.forEach((listener) => { | ||
| if (this.isDisposed) return; | ||
| listener(); | ||
| }); | ||
| this.patchAwareListeners.forEach((listener) => { | ||
| if (this.isDisposed) return; | ||
| try { | ||
| listener(this._lastPatches); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error in patch-aware listener execution", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Factory function for creating type-safe Store instances | ||
| * | ||
| * Creates a new Store instance with the specified name and initial value. | ||
| * Provides type safety and integrates seamlessly with React hooks and | ||
| * the Context-Action framework patterns. | ||
| * | ||
| * @template T - The type of values stored in this store | ||
| * | ||
| * @param name - Unique identifier for the store (used for debugging) | ||
| * @param initialValue - Initial value to store | ||
| * | ||
| * @returns Configured Store instance ready for use | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function createStore(name, initialValue) { | ||
| return new Store(name, initialValue); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreValue.ts | ||
| function useStoreValue(store, selectorOrOptions, options) { | ||
| "use memo"; | ||
| const selector = typeof selectorOrOptions === "function" ? selectorOrOptions : void 0; | ||
| const { equalityFn = defaultEqualityFn, condition, debounce, throttle, initialValue, debug = false, name = store?.name || "unknown" } = (typeof selectorOrOptions === "function" ? options : selectorOrOptions) || {}; | ||
| return useSafeStoreSubscription(store, selector, { | ||
| debug, | ||
| name, | ||
| equalityFn, | ||
| initialValue, | ||
| ...debounce !== void 0 && { debounce }, | ||
| ...throttle !== void 0 && { throttle }, | ||
| ...condition && { condition } | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.tsx | ||
| /** | ||
| * @fileoverview Store Error Boundary Component | ||
| * | ||
| * Context-Action Store 시스템을 위한 에러 경계 컴포넌트 | ||
| * Store 관련 에러들을 적절히 처리하고 사용자에게 우아한 fallback UI를 제공 | ||
| */ | ||
| /** | ||
| * Store 시스템을 위한 에러 경계 컴포넌트 | ||
| * | ||
| * Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다. | ||
| * 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는 | ||
| * 사용자 친화적인 메시지를 보여줍니다. | ||
| */ | ||
| var StoreErrorBoundary = class extends Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.resetTimeoutId = null; | ||
| this.resetErrorBoundary = () => { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| this.setState({ | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }); | ||
| }; | ||
| this.state = { | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }; | ||
| } | ||
| static getDerivedStateFromError(error) { | ||
| return { | ||
| hasError: true, | ||
| error: error instanceof Error && error.name === "ContextActionError" ? error : null, | ||
| errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` | ||
| }; | ||
| } | ||
| componentDidCatch(error, errorInfo) { | ||
| if (error.name === "ContextActionError") { | ||
| const contextActionError = error; | ||
| this.setState({ errorInfo }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } else { | ||
| const contextActionError = ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, { | ||
| component: "StoreErrorBoundary", | ||
| stack: error.stack, | ||
| componentStack: errorInfo.componentStack | ||
| }, error); | ||
| this.setState({ | ||
| error: contextActionError, | ||
| errorInfo | ||
| }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } | ||
| } | ||
| componentDidUpdate(prevProps) { | ||
| const { hasError } = this.state; | ||
| const { resetOnPropsChange, resetKeys } = this.props; | ||
| if (hasError && resetOnPropsChange) { | ||
| if (resetKeys) { | ||
| if (resetKeys.some((key) => { | ||
| return prevProps[key] !== this.props[key]; | ||
| })) this.resetErrorBoundary(); | ||
| } else if (prevProps !== this.props) this.resetErrorBoundary(); | ||
| } | ||
| } | ||
| componentWillUnmount() { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| } | ||
| render() { | ||
| const { hasError, error, errorInfo } = this.state; | ||
| const { children, fallback } = this.props; | ||
| if (hasError) { | ||
| if (fallback) { | ||
| if (typeof fallback === "function") return fallback(error, errorInfo); | ||
| return fallback; | ||
| } | ||
| return this.renderDefaultFallback(); | ||
| } | ||
| return children; | ||
| } | ||
| renderDefaultFallback() { | ||
| return this.renderDevelopmentFallback(); | ||
| } | ||
| renderDevelopmentFallback() { | ||
| const { error, errorInfo, errorId } = this.state; | ||
| const stats = getErrorStatistics(); | ||
| return /* @__PURE__ */ jsxs("div", { | ||
| style: { | ||
| padding: "20px", | ||
| margin: "20px", | ||
| border: "2px solid #ff6b6b", | ||
| borderRadius: "8px", | ||
| backgroundColor: "#ffe0e0", | ||
| fontFamily: "monospace" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("h2", { | ||
| style: { | ||
| color: "#d63031", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "🚨 Store Error Boundary" | ||
| }), | ||
| /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("strong", { children: "Error ID:" }), | ||
| " ", | ||
| errorId | ||
| ] | ||
| }), | ||
| error && /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("strong", { children: "Error Type:" }), | ||
| " ", | ||
| error.type, | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| /* @__PURE__ */ jsx("strong", { children: "Message:" }), | ||
| " ", | ||
| error.message, | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| /* @__PURE__ */ jsx("strong", { children: "Timestamp:" }), | ||
| " ", | ||
| new Date(error.timestamp).toISOString() | ||
| ] | ||
| }), | ||
| error?.context && /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ jsx("strong", { children: "Context:" }), /* @__PURE__ */ jsx("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "12px" | ||
| }, | ||
| children: JSON.stringify(error.context, null, 2) | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("strong", { children: "Error Statistics:" }), | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| "Total Errors: ", | ||
| stats.totalErrors, | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| "Recent Errors: ", | ||
| stats.recentErrors.length | ||
| ] | ||
| }), | ||
| errorInfo && /* @__PURE__ */ jsxs("details", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ jsx("summary", { | ||
| style: { | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Component Stack" | ||
| }), /* @__PURE__ */ jsx("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "11px", | ||
| whiteSpace: "pre-wrap" | ||
| }, | ||
| children: errorInfo.componentStack | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ jsx("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#00b894", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| renderProductionFallback() { | ||
| return /* @__PURE__ */ jsxs("div", { | ||
| style: { | ||
| padding: "20px", | ||
| textAlign: "center", | ||
| backgroundColor: "#f8f9fa", | ||
| border: "1px solid #dee2e6", | ||
| borderRadius: "8px", | ||
| margin: "20px 0" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("h3", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "Something went wrong" | ||
| }), | ||
| /* @__PURE__ */ jsx("p", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 15px 0" | ||
| }, | ||
| children: "We're sorry, but something unexpected happened. Please try again." | ||
| }), | ||
| /* @__PURE__ */ jsx("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#007bff", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Enhanced HOC for automatic Store Error Boundary wrapping with security | ||
| * | ||
| * @template P - Component props type | ||
| * @param WrappedComponent - Component to wrap with error boundary | ||
| * @param errorBoundaryProps - Error boundary configuration | ||
| * @returns Enhanced component with comprehensive error handling | ||
| */ | ||
| function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) { | ||
| const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ jsx(StoreErrorBoundary, { | ||
| ...errorBoundaryProps, | ||
| children: /* @__PURE__ */ jsx(WrappedComponent, { ...props }) | ||
| }); | ||
| WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`; | ||
| return WithStoreErrorBoundaryComponent; | ||
| } | ||
| /** | ||
| * 특정 Store와 연결된 에러 경계 생성 헬퍼 | ||
| */ | ||
| function createStoreErrorBoundary(storeName, customFallback) { | ||
| return ({ children }) => /* @__PURE__ */ jsx(StoreErrorBoundary, { | ||
| fallback: customFallback, | ||
| onError: (error, errorInfo) => { | ||
| console.group(`Store Error in ${storeName}`); | ||
| console.error("Error:", error); | ||
| console.error("Component Stack:", errorInfo.componentStack); | ||
| console.groupEnd(); | ||
| }, | ||
| resetKeys: [storeName], | ||
| children | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.tsx | ||
| function createActionContext(contextNameOrConfig = {}, config) { | ||
| let effectiveConfig; | ||
| let contextName; | ||
| if (typeof contextNameOrConfig === "string") { | ||
| contextName = contextNameOrConfig; | ||
| effectiveConfig = { | ||
| ...config, | ||
| name: config?.name || contextName | ||
| }; | ||
| } else { | ||
| effectiveConfig = contextNameOrConfig; | ||
| contextName = effectiveConfig.name || "ActionContext"; | ||
| } | ||
| if (effectiveConfig.schema && !effectiveConfig.registry?.schema) effectiveConfig = { | ||
| ...effectiveConfig, | ||
| registry: { | ||
| ...effectiveConfig.registry, | ||
| schema: effectiveConfig.schema | ||
| } | ||
| }; | ||
| const FactoryActionContext = createContext(null); | ||
| const Provider = ({ children }) => { | ||
| const actionRegisterRef = useRef(new ActionRegister(effectiveConfig)); | ||
| const contextValue = useMemo(() => ({ actionRegisterRef }), []); | ||
| return /* @__PURE__ */ jsx(FactoryActionContext.Provider, { | ||
| value: contextValue, | ||
| children | ||
| }); | ||
| }; | ||
| const useFactoryActionContext = () => { | ||
| const context = useContext(FactoryActionContext); | ||
| if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider"); | ||
| return context; | ||
| }; | ||
| /** | ||
| * Optimized hook to get stable dispatch functions | ||
| * | ||
| * Returns stable dispatch functions that prevent re-renders and maintain | ||
| * reference equality across component renders. | ||
| * | ||
| * @returns Object with dispatch and dispatchWithResult functions | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useActionDispatcher = () => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| return { | ||
| dispatch: useCallback((action, payload, options) => { | ||
| console.log(`React dispatch called for '${String(action)}':`, { | ||
| hasPayload: payload !== void 0, | ||
| hasOptions: options !== void 0, | ||
| timestamp: (/* @__PURE__ */ new Date()).toISOString() | ||
| }); | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]), | ||
| dispatchWithResult: useCallback((action, payload, options) => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]) | ||
| }; | ||
| }; | ||
| const useAction = () => { | ||
| const { dispatch } = useActionDispatcher(); | ||
| return dispatch; | ||
| }; | ||
| const useActionHandler = (action, handler, config$1) => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| const actionId = useId(); | ||
| const handlerRef = useRef(handler); | ||
| handlerRef.current = handler; | ||
| const priority = config$1?.priority ?? 0; | ||
| const id = config$1?.id || `react_${String(action)}_${actionId}`; | ||
| const blocking = config$1?.blocking ?? false; | ||
| const once = config$1?.once ?? false; | ||
| const debounce = config$1?.debounce; | ||
| const throttle = config$1?.throttle; | ||
| const stableConfig = useMemo(() => ({ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| replaceExisting: true, | ||
| ...debounce !== void 0 && { debounce }, | ||
| ...throttle !== void 0 && { throttle } | ||
| }), [ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| debounce, | ||
| throttle | ||
| ]); | ||
| useEffect(() => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) return; | ||
| const wrapperHandler = (payload, controller) => { | ||
| return handlerRef.current(payload, controller); | ||
| }; | ||
| console.log(`Registering handler for '${String(action)}'`); | ||
| return register.register(action, wrapperHandler, stableConfig); | ||
| }, [ | ||
| action, | ||
| actionRegisterRef, | ||
| stableConfig | ||
| ]); | ||
| }; | ||
| /** | ||
| * Hook that provides direct access to the ActionRegister instance | ||
| * | ||
| * This hook is useful when you need to: | ||
| * - Register multiple handlers dynamically | ||
| * - Access other ActionRegister methods like clearAction, getHandlers, etc. | ||
| * - Implement complex handler registration logic | ||
| * - Have more control over the registration lifecycle | ||
| * | ||
| * @returns ActionRegister instance or null if not initialized | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useFactoryActionRegister = () => { | ||
| return useFactoryActionContext().actionRegisterRef.current; | ||
| }; | ||
| /** | ||
| * Hook that provides access to the dispatchWithResult function | ||
| * | ||
| * This hook returns a function that dispatches actions and returns detailed | ||
| * execution results including collected handler results, execution metadata, | ||
| * and error information. | ||
| * | ||
| * @returns dispatchWithResult function with full type safety | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result | ||
| */ | ||
| const useFactoryActionDispatchWithResult = () => { | ||
| const context = useFactoryActionContext(); | ||
| const activeControllersRef = useRef(/* @__PURE__ */ new Set()); | ||
| const dispatch = useCallback((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const dispatchWithResult = useCallback((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const abortAll = useCallback(() => { | ||
| activeControllersRef.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| activeControllersRef.current.clear(); | ||
| }, []); | ||
| const resetAbortScope = useCallback(() => { | ||
| abortAll(); | ||
| }, [abortAll]); | ||
| useEffect(() => { | ||
| const controllers = activeControllersRef; | ||
| return () => { | ||
| controllers.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| controllers.current.clear(); | ||
| }; | ||
| }, []); | ||
| return { | ||
| dispatch, | ||
| dispatchWithResult, | ||
| abortAll, | ||
| resetAbortScope | ||
| }; | ||
| }; | ||
| return { | ||
| Provider, | ||
| useActionContext: useFactoryActionContext, | ||
| useActionDispatch: useAction, | ||
| useActionHandler, | ||
| useActionRegister: useFactoryActionRegister, | ||
| useActionDispatchWithResult: useFactoryActionDispatchWithResult, | ||
| context: FactoryActionContext | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { useStoreValue as a, ContextActionError as c, handleError as d, TypeGuards as f, StoreRegistry as g, useSafeStoreSubscription as h, withStoreErrorBoundary as i, ContextActionErrorType as l, useStoreSelector as m, StoreErrorBoundary as n, Store as o, defaultEqualityFn as p, createStoreErrorBoundary as r, createStore as s, createActionContext as t, ErrorHandlers as u }; | ||
| //# sourceMappingURL=ActionContext.js.map |
Sorry, the diff of this file is too big to display
| //#region rolldown:runtime | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) { | ||
| __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| //#endregion | ||
| //#region src/stores/utils/comparison.ts | ||
| const DEFAULT_COMPARISON_OPTIONS = { | ||
| strategy: "reference", | ||
| maxDepth: 5, | ||
| enableCircularCheck: true | ||
| }; | ||
| let globalComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS }; | ||
| function setGlobalComparisonOptions(options) { | ||
| globalComparisonOptions = { | ||
| ...DEFAULT_COMPARISON_OPTIONS, | ||
| ...options | ||
| }; | ||
| } | ||
| function getGlobalComparisonOptions() { | ||
| return { ...globalComparisonOptions }; | ||
| } | ||
| function referenceEquals(oldValue, newValue) { | ||
| return Object.is(oldValue, newValue); | ||
| } | ||
| function shallowEquals(oldValue, newValue, ignoreKeys = []) { | ||
| if (Object.is(oldValue, newValue)) return true; | ||
| if (oldValue == null || newValue == null) return oldValue === newValue; | ||
| if (typeof oldValue !== "object" || typeof newValue !== "object") return oldValue === newValue; | ||
| if (Array.isArray(oldValue) && Array.isArray(newValue)) { | ||
| if (oldValue.length !== newValue.length) return false; | ||
| for (let i = 0; i < oldValue.length; i++) if (!Object.is(oldValue[i], newValue[i])) return false; | ||
| return true; | ||
| } | ||
| const oldKeys = Object.keys(oldValue).filter((key) => !ignoreKeys.includes(key)); | ||
| const newKeys = Object.keys(newValue).filter((key) => !ignoreKeys.includes(key)); | ||
| if (oldKeys.length !== newKeys.length) return false; | ||
| for (const key of oldKeys) { | ||
| if (!newKeys.includes(key)) return false; | ||
| if (!Object.is(oldValue[key], newValue[key])) return false; | ||
| } | ||
| return true; | ||
| } | ||
| function deepEquals(oldValue, newValue, options = {}) { | ||
| const { maxDepth = 5, ignoreKeys = [], enableCircularCheck = true } = options; | ||
| const visitedPairs = enableCircularCheck ? /* @__PURE__ */ new WeakMap() : null; | ||
| function deepCompare(a, b, depth, path = "") { | ||
| if (depth > maxDepth) return Object.is(a, b); | ||
| if (Object.is(a, b)) return true; | ||
| if (a == null || b == null) return a === b; | ||
| if (typeof a !== typeof b) return false; | ||
| if (typeof a !== "object") return a === b; | ||
| if (visitedPairs && typeof a === "object" && typeof b === "object" && a !== null && b !== null) { | ||
| if (visitedPairs.has(a)) { | ||
| if (visitedPairs.get(a).has(b)) return Object.is(a, b); | ||
| } | ||
| if (!visitedPairs.has(a)) visitedPairs.set(a, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(a).add(b); | ||
| if (!visitedPairs.has(b)) visitedPairs.set(b, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(b).add(a); | ||
| } | ||
| if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); | ||
| if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString(); | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| for (let i = 0; i < a.length; i++) if (!deepCompare(a[i], b[i], depth + 1, `${path}[${i}]`)) return false; | ||
| return true; | ||
| } | ||
| if (Array.isArray(a) || Array.isArray(b)) return false; | ||
| const aKeys = Object.keys(a).filter((key) => !ignoreKeys.includes(key)); | ||
| const bKeys = Object.keys(b).filter((key) => !ignoreKeys.includes(key)); | ||
| if (aKeys.length !== bKeys.length) return false; | ||
| for (const key of aKeys) { | ||
| if (!bKeys.includes(key)) return false; | ||
| if (!deepCompare(a[key], b[key], depth + 1, `${path}.${key}`)) return false; | ||
| } | ||
| return true; | ||
| } | ||
| return deepCompare(oldValue, newValue, 0); | ||
| } | ||
| function compareValues(oldValue, newValue, options = {}) { | ||
| const { strategy, customComparator, maxDepth, ignoreKeys, enableCircularCheck } = { | ||
| ...globalComparisonOptions, | ||
| ...options | ||
| }; | ||
| let result; | ||
| try { | ||
| if (strategy !== "reference" && strategy !== "custom" && typeof oldValue === "object" && typeof newValue === "object") try { | ||
| const oldStr = JSON.stringify(oldValue); | ||
| const newStr = JSON.stringify(newValue); | ||
| if (oldStr.length < 1e3 && newStr.length < 1e3) { | ||
| result = oldStr === newStr; | ||
| return result; | ||
| } | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") console.debug("[ComparisonOptimization] JSON serialization failed, falling back to original strategy:", error); | ||
| } | ||
| switch (strategy) { | ||
| case "reference": | ||
| result = referenceEquals(oldValue, newValue); | ||
| break; | ||
| case "shallow": | ||
| result = shallowEquals(oldValue, newValue, ignoreKeys); | ||
| break; | ||
| case "deep": | ||
| result = deepEquals(oldValue, newValue, { | ||
| ...maxDepth !== void 0 && { maxDepth }, | ||
| ...ignoreKeys !== void 0 && { ignoreKeys }, | ||
| ...enableCircularCheck !== void 0 && { enableCircularCheck } | ||
| }); | ||
| break; | ||
| case "custom": | ||
| if (!customComparator) result = referenceEquals(oldValue, newValue); | ||
| else result = customComparator(oldValue, newValue); | ||
| break; | ||
| default: result = referenceEquals(oldValue, newValue); | ||
| } | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") console.warn("[CompareValues] Comparison failed, falling back to reference equality:", error); | ||
| result = referenceEquals(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| //#endregion | ||
| Object.defineProperty(exports, '__toESM', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __toESM; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'compareValues', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return compareValues; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'deepEquals', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return deepEquals; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'getGlobalComparisonOptions', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return getGlobalComparisonOptions; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'referenceEquals', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return referenceEquals; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'setGlobalComparisonOptions', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return setGlobalComparisonOptions; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'shallowEquals', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return shallowEquals; | ||
| } | ||
| }); |
| //#region src/stores/utils/comparison.ts | ||
| const DEFAULT_COMPARISON_OPTIONS = { | ||
| strategy: "reference", | ||
| maxDepth: 5, | ||
| enableCircularCheck: true | ||
| }; | ||
| let globalComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS }; | ||
| function setGlobalComparisonOptions(options) { | ||
| globalComparisonOptions = { | ||
| ...DEFAULT_COMPARISON_OPTIONS, | ||
| ...options | ||
| }; | ||
| } | ||
| function getGlobalComparisonOptions() { | ||
| return { ...globalComparisonOptions }; | ||
| } | ||
| function referenceEquals(oldValue, newValue) { | ||
| return Object.is(oldValue, newValue); | ||
| } | ||
| function shallowEquals(oldValue, newValue, ignoreKeys = []) { | ||
| if (Object.is(oldValue, newValue)) return true; | ||
| if (oldValue == null || newValue == null) return oldValue === newValue; | ||
| if (typeof oldValue !== "object" || typeof newValue !== "object") return oldValue === newValue; | ||
| if (Array.isArray(oldValue) && Array.isArray(newValue)) { | ||
| if (oldValue.length !== newValue.length) return false; | ||
| for (let i = 0; i < oldValue.length; i++) if (!Object.is(oldValue[i], newValue[i])) return false; | ||
| return true; | ||
| } | ||
| const oldKeys = Object.keys(oldValue).filter((key) => !ignoreKeys.includes(key)); | ||
| const newKeys = Object.keys(newValue).filter((key) => !ignoreKeys.includes(key)); | ||
| if (oldKeys.length !== newKeys.length) return false; | ||
| for (const key of oldKeys) { | ||
| if (!newKeys.includes(key)) return false; | ||
| if (!Object.is(oldValue[key], newValue[key])) return false; | ||
| } | ||
| return true; | ||
| } | ||
| function deepEquals(oldValue, newValue, options = {}) { | ||
| const { maxDepth = 5, ignoreKeys = [], enableCircularCheck = true } = options; | ||
| const visitedPairs = enableCircularCheck ? /* @__PURE__ */ new WeakMap() : null; | ||
| function deepCompare(a, b, depth, path = "") { | ||
| if (depth > maxDepth) return Object.is(a, b); | ||
| if (Object.is(a, b)) return true; | ||
| if (a == null || b == null) return a === b; | ||
| if (typeof a !== typeof b) return false; | ||
| if (typeof a !== "object") return a === b; | ||
| if (visitedPairs && typeof a === "object" && typeof b === "object" && a !== null && b !== null) { | ||
| if (visitedPairs.has(a)) { | ||
| if (visitedPairs.get(a).has(b)) return Object.is(a, b); | ||
| } | ||
| if (!visitedPairs.has(a)) visitedPairs.set(a, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(a).add(b); | ||
| if (!visitedPairs.has(b)) visitedPairs.set(b, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(b).add(a); | ||
| } | ||
| if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); | ||
| if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString(); | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| for (let i = 0; i < a.length; i++) if (!deepCompare(a[i], b[i], depth + 1, `${path}[${i}]`)) return false; | ||
| return true; | ||
| } | ||
| if (Array.isArray(a) || Array.isArray(b)) return false; | ||
| const aKeys = Object.keys(a).filter((key) => !ignoreKeys.includes(key)); | ||
| const bKeys = Object.keys(b).filter((key) => !ignoreKeys.includes(key)); | ||
| if (aKeys.length !== bKeys.length) return false; | ||
| for (const key of aKeys) { | ||
| if (!bKeys.includes(key)) return false; | ||
| if (!deepCompare(a[key], b[key], depth + 1, `${path}.${key}`)) return false; | ||
| } | ||
| return true; | ||
| } | ||
| return deepCompare(oldValue, newValue, 0); | ||
| } | ||
| function compareValues(oldValue, newValue, options = {}) { | ||
| const { strategy, customComparator, maxDepth, ignoreKeys, enableCircularCheck } = { | ||
| ...globalComparisonOptions, | ||
| ...options | ||
| }; | ||
| let result; | ||
| try { | ||
| if (strategy !== "reference" && strategy !== "custom" && typeof oldValue === "object" && typeof newValue === "object") try { | ||
| const oldStr = JSON.stringify(oldValue); | ||
| const newStr = JSON.stringify(newValue); | ||
| if (oldStr.length < 1e3 && newStr.length < 1e3) { | ||
| result = oldStr === newStr; | ||
| return result; | ||
| } | ||
| } catch (error) { | ||
| console.debug("[ComparisonOptimization] JSON serialization failed, falling back to original strategy:", error); | ||
| } | ||
| switch (strategy) { | ||
| case "reference": | ||
| result = referenceEquals(oldValue, newValue); | ||
| break; | ||
| case "shallow": | ||
| result = shallowEquals(oldValue, newValue, ignoreKeys); | ||
| break; | ||
| case "deep": | ||
| result = deepEquals(oldValue, newValue, { | ||
| ...maxDepth !== void 0 && { maxDepth }, | ||
| ...ignoreKeys !== void 0 && { ignoreKeys }, | ||
| ...enableCircularCheck !== void 0 && { enableCircularCheck } | ||
| }); | ||
| break; | ||
| case "custom": | ||
| if (!customComparator) result = referenceEquals(oldValue, newValue); | ||
| else result = customComparator(oldValue, newValue); | ||
| break; | ||
| default: result = referenceEquals(oldValue, newValue); | ||
| } | ||
| } catch (error) { | ||
| console.warn("[CompareValues] Comparison failed, falling back to reference equality:", error); | ||
| result = referenceEquals(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| //#endregion | ||
| export { setGlobalComparisonOptions as a, referenceEquals as i, deepEquals as n, shallowEquals as o, getGlobalComparisonOptions as r, compareValues as t }; | ||
| //# sourceMappingURL=comparison.js.map |
| {"version":3,"file":"comparison.js","names":[],"sources":["../src/stores/utils/comparison.ts"],"sourcesContent":["\n\nexport type ComparisonStrategy = 'reference' | 'shallow' | 'deep' | 'custom';\n\nexport type CustomComparator<T = unknown> = (oldValue: T, newValue: T) => boolean;\n\nexport interface ComparisonOptions<T = unknown> {\n strategy: ComparisonStrategy;\n customComparator?: CustomComparator<T>;\n maxDepth?: number;\n ignoreKeys?: string[];\n enableCircularCheck?: boolean;\n}\n\nconst DEFAULT_COMPARISON_OPTIONS: ComparisonOptions = {\n strategy: 'reference',\n maxDepth: 5,\n enableCircularCheck: true,\n};\n\nlet globalComparisonOptions: ComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS };\n\nexport function setGlobalComparisonOptions(options: Partial<ComparisonOptions>): void {\n globalComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS, ...options };\n}\n\nexport function getGlobalComparisonOptions(): ComparisonOptions {\n return { ...globalComparisonOptions };\n}\n\nexport function referenceEquals<T>(oldValue: T, newValue: T): boolean {\n const result = Object.is(oldValue, newValue);\n return result;\n}\n\nexport function shallowEquals<T>(oldValue: T, newValue: T, ignoreKeys: string[] = []): boolean {\n // 참조가 같으면 즉시 true\n if (Object.is(oldValue, newValue)) {\n return true;\n }\n\n // null/undefined 처리\n if (oldValue == null || newValue == null) {\n const result = oldValue === newValue;\n return result;\n }\n\n // 원시 타입 처리\n if (typeof oldValue !== 'object' || typeof newValue !== 'object') {\n const result = oldValue === newValue;\n return result;\n }\n\n // 배열 처리\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (oldValue.length !== newValue.length) {\n return false;\n }\n \n for (let i = 0; i < oldValue.length; i++) {\n if (!Object.is(oldValue[i], newValue[i])) {\n return false;\n }\n }\n \n return true;\n }\n\n // 객체 처리\n const oldKeys = Object.keys(oldValue as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n const newKeys = Object.keys(newValue as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n\n if (oldKeys.length !== newKeys.length) {\n return false;\n }\n\n for (const key of oldKeys) {\n if (!newKeys.includes(key)) {\n return false;\n }\n \n if (!Object.is((oldValue as Record<string, unknown>)[key], (newValue as Record<string, unknown>)[key])) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function deepEquals<T>(\n oldValue: T, \n newValue: T, \n options: {\n maxDepth?: number;\n ignoreKeys?: string[];\n enableCircularCheck?: boolean;\n } = {}\n): boolean {\n const { maxDepth = 5, ignoreKeys = [], enableCircularCheck = true } = options;\n \n // 개선된 순환 참조 감지 시스템\n const visitedPairs = enableCircularCheck ? new WeakMap<object, WeakSet<object>>() : null;\n \n function deepCompare(a: unknown, b: unknown, depth: number, path = ''): boolean {\n // 최대 깊이 초과 시 참조 비교로 fallback\n if (depth > maxDepth) {\n return Object.is(a, b);\n }\n\n // 참조가 같으면 즉시 true\n if (Object.is(a, b)) {\n return true;\n }\n\n // null/undefined 처리\n if (a == null || b == null) {\n return a === b;\n }\n\n // 타입이 다르면 false\n if (typeof a !== typeof b) {\n return false;\n }\n\n // 원시 타입 처리\n if (typeof a !== 'object') {\n return a === b;\n }\n\n // 개선된 순환 참조 체크\n if (visitedPairs && typeof a === 'object' && typeof b === 'object' && a !== null && b !== null) {\n // 비교 쌍의 순환 참조 확인\n if (visitedPairs.has(a)) {\n const pairedSet = visitedPairs.get(a)!;\n if (pairedSet.has(b)) {\n return Object.is(a, b);\n }\n }\n \n // 방문 기록 추가\n if (!visitedPairs.has(a)) {\n visitedPairs.set(a, new WeakSet());\n }\n visitedPairs.get(a)!.add(b);\n \n // 반대 방향도 기록 (대칭적 추적)\n if (!visitedPairs.has(b)) {\n visitedPairs.set(b, new WeakSet());\n }\n visitedPairs.get(b)!.add(a);\n }\n\n // Date 객체 처리\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n // RegExp 객체 처리\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.toString() === b.toString();\n }\n\n // 배열 처리\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n \n for (let i = 0; i < a.length; i++) {\n if (!deepCompare(a[i], b[i], depth + 1, `${path}[${i}]`)) {\n return false;\n }\n }\n \n return true;\n }\n\n // 배열과 객체 타입 불일치\n if (Array.isArray(a) || Array.isArray(b)) {\n return false;\n }\n\n // 객체 처리\n const aKeys = Object.keys(a as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n const bKeys = Object.keys(b as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (const key of aKeys) {\n if (!bKeys.includes(key)) {\n return false;\n }\n \n if (!deepCompare((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key], depth + 1, `${path}.${key}`)) {\n return false;\n }\n }\n\n return true;\n }\n\n const result = deepCompare(oldValue, newValue, 0);\n \n return result;\n}\n\nexport function compareValues<T>(\n oldValue: T, \n newValue: T, \n options: Partial<ComparisonOptions<T>> = {}\n): boolean {\n const finalOptions = { ...globalComparisonOptions, ...options };\n const { strategy, customComparator, maxDepth, ignoreKeys, enableCircularCheck } = finalOptions;\n\n let result: boolean;\n\n try {\n // HMR 최적화: 자동 전략 선택 (strategy가 'reference'가 아닌 경우)\n if (strategy !== 'reference' && strategy !== 'custom' && typeof oldValue === 'object' && typeof newValue === 'object') {\n // JSON 직렬화 시도로 크기와 복잡도 판단\n try {\n const oldStr = JSON.stringify(oldValue);\n const newStr = JSON.stringify(newValue);\n \n // 작은 객체 (1KB 미만): JSON 문자열 비교가 가장 빠름\n if (oldStr.length < 1000 && newStr.length < 1000) {\n result = oldStr === newStr;\n return result;\n }\n } catch (error) {\n // JSON 직렬화 실패 시 (순환 참조, BigInt, Symbol, Function 등)\n // 디버그 모드에서만 로깅하여 성능 영향 최소화\n if (process.env.NODE_ENV === 'development') {\n console.debug('[ComparisonOptimization] JSON serialization failed, falling back to original strategy:', error);\n }\n // 원래 전략으로 계속 진행 (fallthrough)\n }\n }\n\n // 원래 전략 실행\n switch (strategy) {\n case 'reference':\n result = referenceEquals(oldValue, newValue);\n break;\n \n case 'shallow':\n result = shallowEquals(oldValue, newValue, ignoreKeys);\n break;\n \n case 'deep': {\n const deepOptions = {\n ...(maxDepth !== undefined && { maxDepth }),\n ...(ignoreKeys !== undefined && { ignoreKeys }),\n ...(enableCircularCheck !== undefined && { enableCircularCheck })\n };\n result = deepEquals(oldValue, newValue, deepOptions);\n break;\n }\n \n case 'custom':\n if (!customComparator) {\n result = referenceEquals(oldValue, newValue);\n } else {\n result = customComparator(oldValue, newValue);\n }\n break;\n \n default:\n result = referenceEquals(oldValue, newValue);\n }\n } catch (error) {\n // 비교 중 예상치 못한 오류 발생 시 안전한 참조 비교로 fallback\n if (process.env.NODE_ENV === 'development') {\n console.warn('[CompareValues] Comparison failed, falling back to reference equality:', error);\n }\n result = referenceEquals(oldValue, newValue);\n }\n\n return result;\n}\n\n\n\n"],"mappings":"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"} |
+206
| import { Patches } from "@context-action/mutative"; | ||
| //#region src/stores/core/types.d.ts | ||
| type Listener = () => void; | ||
| type Unsubscribe = () => void; | ||
| type Subscribe = (listener: Listener) => Unsubscribe; | ||
| interface Snapshot<T = unknown> { | ||
| value: T; | ||
| name: string; | ||
| lastUpdate: number; | ||
| version?: number; | ||
| isValid?: boolean; | ||
| validationError?: string; | ||
| metrics?: { | ||
| creationTime: number; | ||
| sizeEstimate?: number; | ||
| notificationCount?: number; | ||
| }; | ||
| security?: { | ||
| validated: boolean; | ||
| sanitized?: boolean; | ||
| trustLevel?: number; | ||
| }; | ||
| } | ||
| interface IStore<T = unknown> { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Snapshot<T>; | ||
| setValue: (value: T, options?: StoreSetValueOptions<T>) => void; | ||
| update: (updater: (current: T) => T | void) => void; | ||
| getValue: () => T; | ||
| getListenerCount?: () => number; | ||
| dispose?: () => void; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| isStoreDisposed?: () => boolean; | ||
| getMetrics?: () => StoreMetrics; | ||
| resetMetrics?: () => void; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| getSecurityOptions?: () => SecurityOptions | undefined; | ||
| notifyPath?: (path: (string | number)[]) => void; | ||
| notifyPaths?: (paths: (string | number)[][]) => void; | ||
| } | ||
| interface IStoreRegistry { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Array<[string, IStore]>; | ||
| register: (name: string, store: IStore, metadata?: StoreMetadata) => void; | ||
| unregister: (name: string) => boolean; | ||
| getStore: (name: string) => IStore | undefined; | ||
| getAllStores: () => Map<string, IStore>; | ||
| hasStore: (name: string) => boolean; | ||
| getStoreCount: () => number; | ||
| getStoreNames: () => string[]; | ||
| clear: () => void; | ||
| forEach: (callback: (store: IStore, name: string) => void) => void; | ||
| dispose?: () => void; | ||
| isDisposed?: () => boolean; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| getHealthStatus?: () => { | ||
| totalStores: number; | ||
| healthyStores: number; | ||
| errorStores: number; | ||
| disposedStores: number; | ||
| memoryUsage?: number; | ||
| }; | ||
| performHealthCheck?: () => Promise<Map<string, boolean>>; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| setAutoCleanup?: (enabled: boolean) => void; | ||
| } | ||
| interface StoreSyncConfig<T, R = Snapshot<T>> { | ||
| defaultValue?: T; | ||
| selector?: (snapshot: Snapshot<T>) => R; | ||
| isEqual?: (prev: R, next: R) => boolean; | ||
| errorBoundary?: boolean; | ||
| suspense?: boolean; | ||
| } | ||
| interface HookOptions<T> { | ||
| defaultValue?: T; | ||
| onError?: (error: Error, retryCount?: number) => void | boolean; | ||
| dependencies?: React.DependencyList; | ||
| enableRetry?: boolean; | ||
| maxRetries?: number; | ||
| retryDelay?: number; | ||
| enableMetrics?: boolean; | ||
| throttle?: number; | ||
| debounce?: number; | ||
| } | ||
| interface StoreSetValueOptions<T> { | ||
| skipClone?: boolean; | ||
| skipComparison?: boolean; | ||
| eventHandling?: 'block' | 'transform' | 'allow'; | ||
| eventTransform?: (event: unknown) => T; | ||
| sanitizer?: (value: T) => T; | ||
| validator?: (value: T) => boolean | string; | ||
| } | ||
| interface StoreMetrics { | ||
| totalSets: number; | ||
| totalGets: number; | ||
| totalUpdates: number; | ||
| totalNotifications: number; | ||
| averageOperationTime: number; | ||
| peakListenerCount: number; | ||
| totalErrors: number; | ||
| } | ||
| interface SecurityOptions { | ||
| preventPrototypePollution?: boolean; | ||
| preventXSS?: boolean; | ||
| maxDepth?: number; | ||
| maxStringLength?: number; | ||
| allowedProperties?: RegExp; | ||
| blockedProperties?: RegExp; | ||
| } | ||
| interface StoreMetadata { | ||
| registeredAt?: number; | ||
| name?: string; | ||
| [key: string]: unknown; | ||
| } | ||
| interface DynamicStoreOptions<T> { | ||
| defaultValue?: T; | ||
| createIfNotExists?: boolean; | ||
| onNotFound?: (storeName: string) => void; | ||
| securityOptions?: SecurityOptions; | ||
| autoCleanup?: boolean; | ||
| enableMetrics?: boolean; | ||
| } | ||
| interface React18Options { | ||
| enableDeferred?: boolean; | ||
| enableTransition?: boolean; | ||
| priorityThreshold?: number; | ||
| enableConcurrent?: boolean; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/comparison.d.ts | ||
| type ComparisonStrategy = 'reference' | 'shallow' | 'deep' | 'custom'; | ||
| type CustomComparator<T = unknown> = (oldValue: T, newValue: T) => boolean; | ||
| interface ComparisonOptions<T = unknown> { | ||
| strategy: ComparisonStrategy; | ||
| customComparator?: CustomComparator<T>; | ||
| maxDepth?: number; | ||
| ignoreKeys?: string[]; | ||
| enableCircularCheck?: boolean; | ||
| } | ||
| declare function setGlobalComparisonOptions(options: Partial<ComparisonOptions>): void; | ||
| declare function getGlobalComparisonOptions(): ComparisonOptions; | ||
| declare function compareValues<T>(oldValue: T, newValue: T, options?: Partial<ComparisonOptions<T>>): boolean; | ||
| //#endregion | ||
| //#region src/stores/core/Store.d.ts | ||
| type PatchAwareListener = (patches: Patches | null) => void; | ||
| declare class Store<T = unknown> implements IStore<T> { | ||
| private listeners; | ||
| private patchAwareListeners; | ||
| private _lastPatches; | ||
| protected _value: T; | ||
| protected _snapshot: Snapshot<T>; | ||
| private _lastClonedValue; | ||
| private _lastClonedVersion; | ||
| private _version; | ||
| private isUpdating; | ||
| private updateQueue; | ||
| private notificationMode; | ||
| private pendingNotification; | ||
| private animationFrameId; | ||
| private pendingUpdatesCount; | ||
| private cleanupTasks; | ||
| private isDisposed; | ||
| private errorCount; | ||
| private lastErrorTime; | ||
| private readonly MAX_ERROR_COUNT; | ||
| private readonly ERROR_RESET_TIME; | ||
| private subscriptionRegistry; | ||
| readonly name: string; | ||
| private customComparator; | ||
| private comparisonOptions; | ||
| private cloningEnabled; | ||
| constructor(name: string, initialValue: T); | ||
| subscribe: (listener: Listener) => Unsubscribe; | ||
| subscribeWithPatches: (listener: PatchAwareListener) => Unsubscribe; | ||
| getLastPatches(): Patches | null; | ||
| getSnapshot: () => Snapshot<T>; | ||
| getValue(): T; | ||
| setValue(value: T, options?: StoreSetValueOptions<T>): void; | ||
| update(updater: (current: T) => T | void): void; | ||
| getListenerCount(): number; | ||
| clearListeners(): void; | ||
| notifyPath(path: (string | number)[]): void; | ||
| notifyPaths(paths: (string | number)[][]): void; | ||
| private _getValueAtPath; | ||
| registerCleanup(task: () => void): () => void; | ||
| dispose(): void; | ||
| isStoreDisposed(): boolean; | ||
| setCustomComparator(comparator: (oldValue: T, newValue: T) => boolean): void; | ||
| setComparisonOptions(options: Partial<ComparisonOptions<T>>): void; | ||
| setCloningEnabled(enabled: boolean): void; | ||
| isCloningEnabled(): boolean; | ||
| protected _compareValues(oldValue: T, newValue: T): boolean; | ||
| protected _createSnapshot(): Snapshot<T>; | ||
| protected _scheduleNotification(): void; | ||
| private _scheduleWithRAF; | ||
| private _executeNotification; | ||
| private _handleListenerError; | ||
| private _notifyListeners; | ||
| } | ||
| declare function createStore<T>(name: string, initialValue: T): Store<T>; | ||
| //#endregion | ||
| export { StoreSetValueOptions as _, ComparisonStrategy as a, getGlobalComparisonOptions as c, HookOptions as d, IStore as f, Snapshot as g, React18Options as h, ComparisonOptions as i, setGlobalComparisonOptions as l, Listener as m, Store as n, CustomComparator as o, IStoreRegistry as p, createStore as r, compareValues as s, PatchAwareListener as t, DynamicStoreOptions as u, StoreSyncConfig as v, Unsubscribe as y }; | ||
| //# sourceMappingURL=Store.d.cts.map |
| {"version":3,"file":"Store.d.cts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"} |
+206
| import { Patches } from "@context-action/mutative"; | ||
| //#region src/stores/core/types.d.ts | ||
| type Listener = () => void; | ||
| type Unsubscribe = () => void; | ||
| type Subscribe = (listener: Listener) => Unsubscribe; | ||
| interface Snapshot<T = unknown> { | ||
| value: T; | ||
| name: string; | ||
| lastUpdate: number; | ||
| version?: number; | ||
| isValid?: boolean; | ||
| validationError?: string; | ||
| metrics?: { | ||
| creationTime: number; | ||
| sizeEstimate?: number; | ||
| notificationCount?: number; | ||
| }; | ||
| security?: { | ||
| validated: boolean; | ||
| sanitized?: boolean; | ||
| trustLevel?: number; | ||
| }; | ||
| } | ||
| interface IStore<T = unknown> { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Snapshot<T>; | ||
| setValue: (value: T, options?: StoreSetValueOptions<T>) => void; | ||
| update: (updater: (current: T) => T | void) => void; | ||
| getValue: () => T; | ||
| getListenerCount?: () => number; | ||
| dispose?: () => void; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| isStoreDisposed?: () => boolean; | ||
| getMetrics?: () => StoreMetrics; | ||
| resetMetrics?: () => void; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| getSecurityOptions?: () => SecurityOptions | undefined; | ||
| notifyPath?: (path: (string | number)[]) => void; | ||
| notifyPaths?: (paths: (string | number)[][]) => void; | ||
| } | ||
| interface IStoreRegistry { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Array<[string, IStore]>; | ||
| register: (name: string, store: IStore, metadata?: StoreMetadata) => void; | ||
| unregister: (name: string) => boolean; | ||
| getStore: (name: string) => IStore | undefined; | ||
| getAllStores: () => Map<string, IStore>; | ||
| hasStore: (name: string) => boolean; | ||
| getStoreCount: () => number; | ||
| getStoreNames: () => string[]; | ||
| clear: () => void; | ||
| forEach: (callback: (store: IStore, name: string) => void) => void; | ||
| dispose?: () => void; | ||
| isDisposed?: () => boolean; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| getHealthStatus?: () => { | ||
| totalStores: number; | ||
| healthyStores: number; | ||
| errorStores: number; | ||
| disposedStores: number; | ||
| memoryUsage?: number; | ||
| }; | ||
| performHealthCheck?: () => Promise<Map<string, boolean>>; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| setAutoCleanup?: (enabled: boolean) => void; | ||
| } | ||
| interface StoreSyncConfig<T, R = Snapshot<T>> { | ||
| defaultValue?: T; | ||
| selector?: (snapshot: Snapshot<T>) => R; | ||
| isEqual?: (prev: R, next: R) => boolean; | ||
| errorBoundary?: boolean; | ||
| suspense?: boolean; | ||
| } | ||
| interface HookOptions<T> { | ||
| defaultValue?: T; | ||
| onError?: (error: Error, retryCount?: number) => void | boolean; | ||
| dependencies?: React.DependencyList; | ||
| enableRetry?: boolean; | ||
| maxRetries?: number; | ||
| retryDelay?: number; | ||
| enableMetrics?: boolean; | ||
| throttle?: number; | ||
| debounce?: number; | ||
| } | ||
| interface StoreSetValueOptions<T> { | ||
| skipClone?: boolean; | ||
| skipComparison?: boolean; | ||
| eventHandling?: 'block' | 'transform' | 'allow'; | ||
| eventTransform?: (event: unknown) => T; | ||
| sanitizer?: (value: T) => T; | ||
| validator?: (value: T) => boolean | string; | ||
| } | ||
| interface StoreMetrics { | ||
| totalSets: number; | ||
| totalGets: number; | ||
| totalUpdates: number; | ||
| totalNotifications: number; | ||
| averageOperationTime: number; | ||
| peakListenerCount: number; | ||
| totalErrors: number; | ||
| } | ||
| interface SecurityOptions { | ||
| preventPrototypePollution?: boolean; | ||
| preventXSS?: boolean; | ||
| maxDepth?: number; | ||
| maxStringLength?: number; | ||
| allowedProperties?: RegExp; | ||
| blockedProperties?: RegExp; | ||
| } | ||
| interface StoreMetadata { | ||
| registeredAt?: number; | ||
| name?: string; | ||
| [key: string]: unknown; | ||
| } | ||
| interface DynamicStoreOptions<T> { | ||
| defaultValue?: T; | ||
| createIfNotExists?: boolean; | ||
| onNotFound?: (storeName: string) => void; | ||
| securityOptions?: SecurityOptions; | ||
| autoCleanup?: boolean; | ||
| enableMetrics?: boolean; | ||
| } | ||
| interface React18Options { | ||
| enableDeferred?: boolean; | ||
| enableTransition?: boolean; | ||
| priorityThreshold?: number; | ||
| enableConcurrent?: boolean; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/comparison.d.ts | ||
| type ComparisonStrategy = 'reference' | 'shallow' | 'deep' | 'custom'; | ||
| type CustomComparator<T = unknown> = (oldValue: T, newValue: T) => boolean; | ||
| interface ComparisonOptions<T = unknown> { | ||
| strategy: ComparisonStrategy; | ||
| customComparator?: CustomComparator<T>; | ||
| maxDepth?: number; | ||
| ignoreKeys?: string[]; | ||
| enableCircularCheck?: boolean; | ||
| } | ||
| declare function setGlobalComparisonOptions(options: Partial<ComparisonOptions>): void; | ||
| declare function getGlobalComparisonOptions(): ComparisonOptions; | ||
| declare function compareValues<T>(oldValue: T, newValue: T, options?: Partial<ComparisonOptions<T>>): boolean; | ||
| //#endregion | ||
| //#region src/stores/core/Store.d.ts | ||
| type PatchAwareListener = (patches: Patches | null) => void; | ||
| declare class Store<T = unknown> implements IStore<T> { | ||
| private listeners; | ||
| private patchAwareListeners; | ||
| private _lastPatches; | ||
| protected _value: T; | ||
| protected _snapshot: Snapshot<T>; | ||
| private _lastClonedValue; | ||
| private _lastClonedVersion; | ||
| private _version; | ||
| private isUpdating; | ||
| private updateQueue; | ||
| private notificationMode; | ||
| private pendingNotification; | ||
| private animationFrameId; | ||
| private pendingUpdatesCount; | ||
| private cleanupTasks; | ||
| private isDisposed; | ||
| private errorCount; | ||
| private lastErrorTime; | ||
| private readonly MAX_ERROR_COUNT; | ||
| private readonly ERROR_RESET_TIME; | ||
| private subscriptionRegistry; | ||
| readonly name: string; | ||
| private customComparator; | ||
| private comparisonOptions; | ||
| private cloningEnabled; | ||
| constructor(name: string, initialValue: T); | ||
| subscribe: (listener: Listener) => Unsubscribe; | ||
| subscribeWithPatches: (listener: PatchAwareListener) => Unsubscribe; | ||
| getLastPatches(): Patches | null; | ||
| getSnapshot: () => Snapshot<T>; | ||
| getValue(): T; | ||
| setValue(value: T, options?: StoreSetValueOptions<T>): void; | ||
| update(updater: (current: T) => T | void): void; | ||
| getListenerCount(): number; | ||
| clearListeners(): void; | ||
| notifyPath(path: (string | number)[]): void; | ||
| notifyPaths(paths: (string | number)[][]): void; | ||
| private _getValueAtPath; | ||
| registerCleanup(task: () => void): () => void; | ||
| dispose(): void; | ||
| isStoreDisposed(): boolean; | ||
| setCustomComparator(comparator: (oldValue: T, newValue: T) => boolean): void; | ||
| setComparisonOptions(options: Partial<ComparisonOptions<T>>): void; | ||
| setCloningEnabled(enabled: boolean): void; | ||
| isCloningEnabled(): boolean; | ||
| protected _compareValues(oldValue: T, newValue: T): boolean; | ||
| protected _createSnapshot(): Snapshot<T>; | ||
| protected _scheduleNotification(): void; | ||
| private _scheduleWithRAF; | ||
| private _executeNotification; | ||
| private _handleListenerError; | ||
| private _notifyListeners; | ||
| } | ||
| declare function createStore<T>(name: string, initialValue: T): Store<T>; | ||
| //#endregion | ||
| export { StoreSetValueOptions as _, ComparisonStrategy as a, getGlobalComparisonOptions as c, HookOptions as d, IStore as f, Snapshot as g, React18Options as h, ComparisonOptions as i, setGlobalComparisonOptions as l, Listener as m, Store as n, CustomComparator as o, IStoreRegistry as p, createStore as r, compareValues as s, PatchAwareListener as t, DynamicStoreOptions as u, StoreSyncConfig as v, Unsubscribe as y }; | ||
| //# sourceMappingURL=Store.d.ts.map |
| {"version":3,"file":"Store.d.ts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"} |
+152
| const require_comparison = require('./comparison.cjs'); | ||
| let react = require("react"); | ||
| react = require_comparison.__toESM(react); | ||
| let _context_action_mutative = require("@context-action/mutative"); | ||
| //#region src/stores/utils/provider-composition.ts | ||
| /** | ||
| * @fileoverview Provider composition utilities for managing multiple contexts | ||
| * @implements provider-composition | ||
| * @memberof store-utilities | ||
| * | ||
| * Utilities for composing multiple Provider components to reduce nesting | ||
| * and improve maintainability when dealing with many split contexts. | ||
| */ | ||
| /** | ||
| * Composes multiple Provider components into a single Provider component that accepts children. | ||
| * Uses React.createElement for direct provider nesting without HOC overhead. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Without composition - nested Provider hell | ||
| * function App() { | ||
| * return ( | ||
| * <UserProvider> | ||
| * <ProductProvider> | ||
| * <OrderProvider> | ||
| * <UIProvider> | ||
| * <AppContent /> | ||
| * </UIProvider> | ||
| * </OrderProvider> | ||
| * </ProductProvider> | ||
| * </UserProvider> | ||
| * ); | ||
| * } | ||
| * | ||
| * // With composition - clean and maintainable | ||
| * const AllProviders = composeProviders( | ||
| * UserProvider, | ||
| * ProductProvider, | ||
| * OrderProvider, | ||
| * UIProvider | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Conditional composition based on features | ||
| * const providers = [ | ||
| * CoreProvider, | ||
| * featureFlags.auth && AuthProvider, | ||
| * featureFlags.analytics && AnalyticsProvider | ||
| * ].filter(Boolean) as ProviderComponent[]; | ||
| * | ||
| * const AppProviders = composeProviders(...providers); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AppProviders> | ||
| * <Routes /> | ||
| * </AppProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Domain-grouped composition | ||
| * const BusinessProviders = composeProviders( | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ); | ||
| * | ||
| * const InfrastructureProviders = composeProviders( | ||
| * DataModelProvider, | ||
| * CacheModelProvider, | ||
| * LoggerModelProvider | ||
| * ); | ||
| * | ||
| * const AllProviders = composeProviders( | ||
| * InfrastructureProviders, | ||
| * BusinessProviders | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Environment-specific composition | ||
| * function createEnvironmentProviders() { | ||
| * const isDevelopment = process.env.NODE_ENV === 'development'; | ||
| * const isProduction = process.env.NODE_ENV === 'production'; | ||
| * | ||
| * const providers = [ | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ]; | ||
| * | ||
| * if (isDevelopment) { | ||
| * providers.push(DebugModelProvider, DevToolsModelProvider); | ||
| * } | ||
| * | ||
| * if (isProduction) { | ||
| * providers.push(AnalyticsModelProvider, ErrorTrackingModelProvider); | ||
| * } | ||
| * | ||
| * return composeProviders(...providers); | ||
| * } | ||
| * | ||
| * function App() { | ||
| * const EnvironmentProviders = createEnvironmentProviders(); | ||
| * | ||
| * return ( | ||
| * <EnvironmentProviders> | ||
| * <AppContent /> | ||
| * </EnvironmentProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param providers - Array of Provider components to compose | ||
| * @returns A single Provider component that wraps children with all providers | ||
| */ | ||
| function composeProviders(...providers) { | ||
| return ({ children }) => { | ||
| return providers.reduceRight((children$1, Provider) => react.default.createElement(Provider, null, children$1), children); | ||
| }; | ||
| } | ||
| //#endregion | ||
| Object.defineProperty(exports, 'composeProviders', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return composeProviders; | ||
| } | ||
| }); |
| import { n as Store } from "./Store.cjs"; | ||
| import { MutativeUtils, deepClone, produce, safeGet, safeSet } from "@context-action/mutative"; | ||
| import React from "react"; | ||
| //#region src/stores/utils/type-helpers.d.ts | ||
| type StoreValue<S> = S extends Store<infer T> ? T : never; | ||
| type StoresValues<S extends readonly Store<any>[]> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreRecordValues<S extends Record<string, Store<any>>> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreSelector<T$1, R> = (value: T$1) => R; | ||
| type EqualityFunction<T$1> = (a: T$1, b: T$1) => boolean; | ||
| type StoreListener = () => void; | ||
| type StoreUpdater<T$1> = (current: T$1) => T$1; | ||
| type PartialBy<T$1, K$1 extends keyof T$1> = Omit<T$1, K$1> & Partial<Pick<T$1, K$1>>; | ||
| type RequiredBy<T$1, K$1 extends keyof T$1> = T$1 & Required<Pick<T$1, K$1>>; | ||
| type DeepReadonly<T$1> = { readonly [P in keyof T$1]: T$1[P] extends (infer U)[] ? DeepReadonlyArray<U> : T$1[P] extends object ? DeepReadonly<T$1[P]> : T$1[P] }; | ||
| interface DeepReadonlyArray<T$1> extends ReadonlyArray<DeepReadonly<T$1>> {} | ||
| interface StoreInitConfig<T$1> { | ||
| name: string; | ||
| initialValue: T$1; | ||
| validateValue?: (value: unknown) => value is T$1; | ||
| transformValue?: (value: unknown) => T$1; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/provider-composition.d.ts | ||
| type ProviderComponent = React.ComponentType<{ | ||
| children: React.ReactNode; | ||
| }>; | ||
| declare function composeProviders(...providers: ProviderComponent[]): ProviderComponent; | ||
| //#endregion | ||
| export { StoreValue as _, safeSet as a, DeepReadonly as c, RequiredBy as d, StoreInitConfig as f, StoreUpdater as g, StoreSelector as h, safeGet as i, EqualityFunction as l, StoreRecordValues as m, deepClone as n, ProviderComponent as o, StoreListener as p, produce as r, composeProviders as s, MutativeUtils as t, PartialBy as u, StoresValues as v }; | ||
| //# sourceMappingURL=utils2.d.cts.map |
| {"version":3,"file":"utils2.d.cts","names":[],"sources":["../src/stores/utils/type-helpers.ts","../src/stores/utils/provider-composition.ts"],"sourcesContent":[],"mappings":";;;;;KAYY,gBAAgB,UAAU,iBAAiB;KAK3C,gCAAgC,8BAC9B,IAAI,WAAW,EAAE;AANnB,KAYA,iBAZU,CAAA,UAYkB,MAZlB,CAAA,MAAA,EAYiC,KAZjC,CAAA,GAAA,CAAA,CAAA,CAAA,GAAA,QAAM,MAad,CAbc,GAaV,UAbU,CAaC,CAbD,CAaG,CAbH,CAAA,CAAA,EAAU;AAAiB,KAmB3C,aAnB2C,CAAA,GAAA,EAAA,CAAA,CAAA,GAAA,CAAA,KAAA,EAmBb,GAnBa,EAAA,GAmBP,CAnBO;AAAC,KAwB5C,gBAxB4C,CAAA,GAAA,CAAA,GAAA,CAAA,CAAA,EAwBlB,GAxBkB,EAAA,CAAA,EAwBZ,GAxBY,EAAA,GAAA,OAAA;AAK5C,KAwBA,aAAA,GAxBY,GAAA,GAAA,IAAA;AAAoB,KA6BhC,YA7BgC,CAAA,GAAA,CAAA,GAAA,CAAA,OAAA,EA6BJ,GA7BI,EAAA,GA6BE,GA7BF;AAC9B,KAiCF,SAjCE,CAAA,GAAA,EAAA,YAAA,MAiC2B,GAjC3B,CAAA,GAiCgC,IAjChC,CAiCqC,GAjCrC,EAiCwC,GAjCxC,CAAA,GAiC6C,OAjC7C,CAiCqD,IAjCrD,CAiC0D,GAjC1D,EAiC6D,GAjC7D,CAAA,CAAA;AAAe,KAsCjB,UAtCiB,CAAA,GAAA,EAAA,YAAA,MAsCa,GAtCb,CAAA,GAsCkB,GAtClB,GAsCsB,QAtCtB,CAsC+B,IAtC/B,CAsCoC,GAtCpC,EAsCuC,GAtCvC,CAAA,CAAA;AAAE,KA2CnB,YA3CmB,CAAA,GAAA,CAAA,GAAA,iBAAb,MA4CK,GA5CL,GA4CS,GA5CT,CA4CW,CA5CX,CAAA,SAAA,CAAA,KAAA,EAAA,CAAA,EAAA,GA6CZ,iBA7CY,CA6CM,CA7CN,CAAA,GA8CZ,GA9CY,CA8CV,CA9CU,CAAA,SAAA,MAAA,GA+CZ,YA/CY,CA+CC,GA/CD,CA+CG,CA/CH,CAAA,CAAA,GAgDZ,GAhDY,CAgDV,CAhDU,CAAA,EAAU;AAM5B,UA6CU,iBA7CmB,CAAA,GAAA,CAAA,SA6CU,aA7CV,CA6CwB,YA7CxB,CA6CqC,GA7CrC,CAAA,CAAA,CAAA;AAAW,UAkDvB,eAlDuB,CAAA,GAAA,CAAA,CAAA;EAC1B,IAAA,EAAA,MAAA;EAAe,YAAA,EAmDb,GAnDa;EAAE,aAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,KAAA,IAoDgB,GApDhB;EAAb,cAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAqDqB,GArDrB;;;;KCXN,iBAAA,GAAoB,KAAA,CAAM;YAA0B,KAAA,CAAM;;iBA+HtD,gBAAA,eACA,sBACb"} |
| import { n as Store } from "./Store.js"; | ||
| import React from "react"; | ||
| import { MutativeUtils, deepClone, produce, safeGet as safeGet$1, safeSet as safeSet$1 } from "@context-action/mutative"; | ||
| //#region src/stores/utils/type-helpers.d.ts | ||
| type StoreValue<S> = S extends Store<infer T> ? T : never; | ||
| type StoresValues<S extends readonly Store<any>[]> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreRecordValues<S extends Record<string, Store<any>>> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreSelector<T$1, R> = (value: T$1) => R; | ||
| type EqualityFunction<T$1> = (a: T$1, b: T$1) => boolean; | ||
| type StoreListener = () => void; | ||
| type StoreUpdater<T$1> = (current: T$1) => T$1; | ||
| type PartialBy<T$1, K$1 extends keyof T$1> = Omit<T$1, K$1> & Partial<Pick<T$1, K$1>>; | ||
| type RequiredBy<T$1, K$1 extends keyof T$1> = T$1 & Required<Pick<T$1, K$1>>; | ||
| type DeepReadonly<T$1> = { readonly [P in keyof T$1]: T$1[P] extends (infer U)[] ? DeepReadonlyArray<U> : T$1[P] extends object ? DeepReadonly<T$1[P]> : T$1[P] }; | ||
| interface DeepReadonlyArray<T$1> extends ReadonlyArray<DeepReadonly<T$1>> {} | ||
| interface StoreInitConfig<T$1> { | ||
| name: string; | ||
| initialValue: T$1; | ||
| validateValue?: (value: unknown) => value is T$1; | ||
| transformValue?: (value: unknown) => T$1; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/provider-composition.d.ts | ||
| type ProviderComponent = React.ComponentType<{ | ||
| children: React.ReactNode; | ||
| }>; | ||
| declare function composeProviders(...providers: ProviderComponent[]): ProviderComponent; | ||
| //#endregion | ||
| export { StoreValue as _, safeSet$1 as a, DeepReadonly as c, RequiredBy as d, StoreInitConfig as f, StoreUpdater as g, StoreSelector as h, safeGet$1 as i, EqualityFunction as l, StoreRecordValues as m, deepClone as n, ProviderComponent as o, StoreListener as p, produce as r, composeProviders as s, MutativeUtils as t, PartialBy as u, StoresValues as v }; | ||
| //# sourceMappingURL=utils2.d.ts.map |
| {"version":3,"file":"utils2.d.ts","names":[],"sources":["../src/stores/utils/type-helpers.ts","../src/stores/utils/provider-composition.ts"],"sourcesContent":[],"mappings":";;;;;KAYY,gBAAgB,UAAU,iBAAiB;KAK3C,gCAAgC,8BAC9B,IAAI,WAAW,EAAE;AANnB,KAYA,iBAZU,CAAA,UAYkB,MAZlB,CAAA,MAAA,EAYiC,KAZjC,CAAA,GAAA,CAAA,CAAA,CAAA,GAAA,QAAM,MAad,CAbc,GAaV,UAbU,CAaC,CAbD,CAaG,CAbH,CAAA,CAAA,EAAU;AAAiB,KAmB3C,aAnB2C,CAAA,GAAA,EAAA,CAAA,CAAA,GAAA,CAAA,KAAA,EAmBb,GAnBa,EAAA,GAmBP,CAnBO;AAAC,KAwB5C,gBAxB4C,CAAA,GAAA,CAAA,GAAA,CAAA,CAAA,EAwBlB,GAxBkB,EAAA,CAAA,EAwBZ,GAxBY,EAAA,GAAA,OAAA;AAK5C,KAwBA,aAAA,GAxBY,GAAA,GAAA,IAAA;AAAoB,KA6BhC,YA7BgC,CAAA,GAAA,CAAA,GAAA,CAAA,OAAA,EA6BJ,GA7BI,EAAA,GA6BE,GA7BF;AAC9B,KAiCF,SAjCE,CAAA,GAAA,EAAA,YAAA,MAiC2B,GAjC3B,CAAA,GAiCgC,IAjChC,CAiCqC,GAjCrC,EAiCwC,GAjCxC,CAAA,GAiC6C,OAjC7C,CAiCqD,IAjCrD,CAiC0D,GAjC1D,EAiC6D,GAjC7D,CAAA,CAAA;AAAe,KAsCjB,UAtCiB,CAAA,GAAA,EAAA,YAAA,MAsCa,GAtCb,CAAA,GAsCkB,GAtClB,GAsCsB,QAtCtB,CAsC+B,IAtC/B,CAsCoC,GAtCpC,EAsCuC,GAtCvC,CAAA,CAAA;AAAE,KA2CnB,YA3CmB,CAAA,GAAA,CAAA,GAAA,iBAAb,MA4CK,GA5CL,GA4CS,GA5CT,CA4CW,CA5CX,CAAA,SAAA,CAAA,KAAA,EAAA,CAAA,EAAA,GA6CZ,iBA7CY,CA6CM,CA7CN,CAAA,GA8CZ,GA9CY,CA8CV,CA9CU,CAAA,SAAA,MAAA,GA+CZ,YA/CY,CA+CC,GA/CD,CA+CG,CA/CH,CAAA,CAAA,GAgDZ,GAhDY,CAgDV,CAhDU,CAAA,EAAU;AAM5B,UA6CU,iBA7CmB,CAAA,GAAA,CAAA,SA6CU,aA7CV,CA6CwB,YA7CxB,CA6CqC,GA7CrC,CAAA,CAAA,CAAA;AAAW,UAkDvB,eAlDuB,CAAA,GAAA,CAAA,CAAA;EAC1B,IAAA,EAAA,MAAA;EAAe,YAAA,EAmDb,GAnDa;EAAE,aAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,KAAA,IAoDgB,GApDhB;EAAb,cAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAqDqB,GArDrB;;;;KCXN,iBAAA,GAAoB,KAAA,CAAM;YAA0B,KAAA,CAAM;;iBA+HtD,gBAAA,eACA,sBACb"} |
+146
| import React from "react"; | ||
| import { MutativeUtils, deepClone, produce, safeGet as safeGet$1, safeSet as safeSet$1 } from "@context-action/mutative"; | ||
| //#region src/stores/utils/provider-composition.ts | ||
| /** | ||
| * @fileoverview Provider composition utilities for managing multiple contexts | ||
| * @implements provider-composition | ||
| * @memberof store-utilities | ||
| * | ||
| * Utilities for composing multiple Provider components to reduce nesting | ||
| * and improve maintainability when dealing with many split contexts. | ||
| */ | ||
| /** | ||
| * Composes multiple Provider components into a single Provider component that accepts children. | ||
| * Uses React.createElement for direct provider nesting without HOC overhead. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Without composition - nested Provider hell | ||
| * function App() { | ||
| * return ( | ||
| * <UserProvider> | ||
| * <ProductProvider> | ||
| * <OrderProvider> | ||
| * <UIProvider> | ||
| * <AppContent /> | ||
| * </UIProvider> | ||
| * </OrderProvider> | ||
| * </ProductProvider> | ||
| * </UserProvider> | ||
| * ); | ||
| * } | ||
| * | ||
| * // With composition - clean and maintainable | ||
| * const AllProviders = composeProviders( | ||
| * UserProvider, | ||
| * ProductProvider, | ||
| * OrderProvider, | ||
| * UIProvider | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Conditional composition based on features | ||
| * const providers = [ | ||
| * CoreProvider, | ||
| * featureFlags.auth && AuthProvider, | ||
| * featureFlags.analytics && AnalyticsProvider | ||
| * ].filter(Boolean) as ProviderComponent[]; | ||
| * | ||
| * const AppProviders = composeProviders(...providers); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AppProviders> | ||
| * <Routes /> | ||
| * </AppProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Domain-grouped composition | ||
| * const BusinessProviders = composeProviders( | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ); | ||
| * | ||
| * const InfrastructureProviders = composeProviders( | ||
| * DataModelProvider, | ||
| * CacheModelProvider, | ||
| * LoggerModelProvider | ||
| * ); | ||
| * | ||
| * const AllProviders = composeProviders( | ||
| * InfrastructureProviders, | ||
| * BusinessProviders | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Environment-specific composition | ||
| * function createEnvironmentProviders() { | ||
| * const isDevelopment = process.env.NODE_ENV === 'development'; | ||
| * const isProduction = process.env.NODE_ENV === 'production'; | ||
| * | ||
| * const providers = [ | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ]; | ||
| * | ||
| * if (isDevelopment) { | ||
| * providers.push(DebugModelProvider, DevToolsModelProvider); | ||
| * } | ||
| * | ||
| * if (isProduction) { | ||
| * providers.push(AnalyticsModelProvider, ErrorTrackingModelProvider); | ||
| * } | ||
| * | ||
| * return composeProviders(...providers); | ||
| * } | ||
| * | ||
| * function App() { | ||
| * const EnvironmentProviders = createEnvironmentProviders(); | ||
| * | ||
| * return ( | ||
| * <EnvironmentProviders> | ||
| * <AppContent /> | ||
| * </EnvironmentProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param providers - Array of Provider components to compose | ||
| * @returns A single Provider component that wraps children with all providers | ||
| */ | ||
| function composeProviders(...providers) { | ||
| return ({ children }) => { | ||
| return providers.reduceRight((children$1, Provider) => React.createElement(Provider, null, children$1), children); | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { safeSet$1 as a, safeGet$1 as i, deepClone as n, composeProviders as o, produce as r, MutativeUtils as t }; | ||
| //# sourceMappingURL=utils2.js.map |
| {"version":3,"file":"utils2.js","names":["children"],"sources":["../src/stores/utils/provider-composition.ts"],"sourcesContent":["/**\n * @fileoverview Provider composition utilities for managing multiple contexts\n * @implements provider-composition\n * @memberof store-utilities\n * \n * Utilities for composing multiple Provider components to reduce nesting\n * and improve maintainability when dealing with many split contexts.\n */\n\nimport React from 'react';\n\n/**\n * Type for Provider components that accept children\n */\nexport type ProviderComponent = React.ComponentType<{ children: React.ReactNode }>;\n\n/**\n * Composes multiple Provider components into a single Provider component that accepts children.\n * Uses React.createElement for direct provider nesting without HOC overhead.\n * \n * @example\n * ```tsx\n * // Without composition - nested Provider hell\n * function App() {\n * return (\n * <UserProvider>\n * <ProductProvider>\n * <OrderProvider>\n * <UIProvider>\n * <AppContent />\n * </UIProvider>\n * </OrderProvider>\n * </ProductProvider>\n * </UserProvider>\n * );\n * }\n * \n * // With composition - clean and maintainable\n * const AllProviders = composeProviders(\n * UserProvider,\n * ProductProvider,\n * OrderProvider,\n * UIProvider\n * );\n * \n * function App() {\n * return (\n * <AllProviders>\n * <AppContent />\n * </AllProviders>\n * );\n * }\n * ```\n * \n * @example\n * ```tsx\n * // Conditional composition based on features\n * const providers = [\n * CoreProvider,\n * featureFlags.auth && AuthProvider,\n * featureFlags.analytics && AnalyticsProvider\n * ].filter(Boolean) as ProviderComponent[];\n * \n * const AppProviders = composeProviders(...providers);\n * \n * function App() {\n * return (\n * <AppProviders>\n * <Routes />\n * </AppProviders>\n * );\n * }\n * ```\n * \n * @example\n * ```tsx\n * // Domain-grouped composition\n * const BusinessProviders = composeProviders(\n * UserModelProvider,\n * ProductModelProvider,\n * OrderModelProvider\n * );\n * \n * const InfrastructureProviders = composeProviders(\n * DataModelProvider,\n * CacheModelProvider,\n * LoggerModelProvider\n * );\n * \n * const AllProviders = composeProviders(\n * InfrastructureProviders,\n * BusinessProviders\n * );\n * \n * function App() {\n * return (\n * <AllProviders>\n * <AppContent />\n * </AllProviders>\n * );\n * }\n * ```\n * \n * @example\n * ```tsx\n * // Environment-specific composition\n * function createEnvironmentProviders() {\n * const isDevelopment = process.env.NODE_ENV === 'development';\n * const isProduction = process.env.NODE_ENV === 'production';\n * \n * const providers = [\n * UserModelProvider,\n * ProductModelProvider,\n * OrderModelProvider\n * ];\n * \n * if (isDevelopment) {\n * providers.push(DebugModelProvider, DevToolsModelProvider);\n * }\n * \n * if (isProduction) {\n * providers.push(AnalyticsModelProvider, ErrorTrackingModelProvider);\n * }\n * \n * return composeProviders(...providers);\n * }\n * \n * function App() {\n * const EnvironmentProviders = createEnvironmentProviders();\n * \n * return (\n * <EnvironmentProviders>\n * <AppContent />\n * </EnvironmentProviders>\n * );\n * }\n * ```\n * \n * @param providers - Array of Provider components to compose\n * @returns A single Provider component that wraps children with all providers\n */\nexport function composeProviders(\n ...providers: ProviderComponent[]\n): ProviderComponent {\n return ({ children }: { children: React.ReactNode }) => {\n return providers.reduceRight(\n (children, Provider) => React.createElement(Provider, null, children),\n children\n );\n };\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6IA,SAAgB,iBACd,GAAG,WACgB;AACnB,SAAQ,EAAE,eAA8C;AACtD,SAAO,UAAU,aACd,YAAU,aAAa,MAAM,cAAc,UAAU,MAAMA,WAAS,EACrE,SACD"} |
+56
-76
@@ -1,9 +0,18 @@ | ||
| const require_error_handling = require('./error-handling-ibCwx4ki.cjs'); | ||
| const require_ActionContext = require('./ActionContext-Bbkccg3d.cjs'); | ||
| const require_utils = require('./utils-ZdkTBqFK.cjs'); | ||
| const require_comparison = require('./comparison.cjs'); | ||
| const require_ActionContext = require('./ActionContext.cjs'); | ||
| const require_utils = require('./utils2.cjs'); | ||
| let react = require("react"); | ||
| react = require_error_handling.__toESM(react); | ||
| let _context_action_mutative = require("@context-action/mutative"); | ||
| //#region src/stores/hooks/useComputedStore.ts | ||
| /** | ||
| * Computed Store Pattern - Automated derived state management | ||
| * | ||
| * Manages automatically computed derived state based on one or more stores. | ||
| * Optimizes performance by recalculating only when dependencies change. | ||
| * Essential for complex applications with derived data relationships. | ||
| * | ||
| * @module stores/hooks/useComputedStore | ||
| */ | ||
| /** | ||
| * Hook for computed store based on a single source store | ||
@@ -32,4 +41,4 @@ * | ||
| const cacheRef = (0, react.useRef)(/* @__PURE__ */ new Map()); | ||
| const lastComputedRef = (0, react.useRef)(); | ||
| const lastInputRef = (0, react.useRef)(); | ||
| const lastComputedRef = (0, react.useRef)(void 0); | ||
| const lastInputRef = (0, react.useRef)(void 0); | ||
| computeRef.current = compute; | ||
@@ -109,48 +118,2 @@ const getCachedValue = (0, react.useCallback)((input) => { | ||
| //#endregion | ||
| //#region src/stores/utils/store-selector.ts | ||
| /** | ||
| * Store sync 상수 정의 | ||
| * 핵심 기능: 안전한 기본값과 에러 처리를 위한 상수 제공 | ||
| */ | ||
| const CONSTANTS = { | ||
| EMPTY_SUBSCRIBE: () => () => {}, | ||
| EMPTY_SNAPSHOT: () => ({ | ||
| value: void 0, | ||
| name: "empty", | ||
| lastUpdate: 0 | ||
| }) | ||
| }; | ||
| /** | ||
| * Store Selector Hook - 선택적 데이터 구독 | ||
| * @implements computed-store | ||
| * @implements fresh-state-access | ||
| * @implements performance-optimization | ||
| * @memberof core-concepts | ||
| * | ||
| * 핵심 기능: selector를 사용하여 Store의 특정 부분만 구독하고 반환 | ||
| * | ||
| * @template T Store 값 타입 | ||
| * @template R 반환 타입 (기본값: Snapshot<T>) | ||
| * @param store - 구독할 Store 인스턴스 | ||
| * @param config - 선택적 설정 (selector, defaultValue) | ||
| * @returns 선택된 값 또는 스냅샷 | ||
| * | ||
| * 핵심 로직 흐름: | ||
| * 1. store.getSnapshot() - 현재 상태 가져오기 | ||
| * 2. selector 적용 (있을 경우) - 필요한 부분만 추출 | ||
| * 3. useSyncExternalStore() - React와 동기화 | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#selective-subscriptions | ||
| */ | ||
| function useStoreSelector(store, config) { | ||
| const { defaultValue, selector } = config ?? {}; | ||
| const getSnapshot = store?.getSnapshot ?? (() => ({ | ||
| ...CONSTANTS.EMPTY_SNAPSHOT(), | ||
| ...defaultValue !== void 0 && { value: defaultValue } | ||
| })); | ||
| const selectedGetSnapshot = selector ? () => selector(getSnapshot()) : getSnapshot; | ||
| return (0, react.useSyncExternalStore)(store?.subscribe ?? CONSTANTS.EMPTY_SUBSCRIBE, selectedGetSnapshot); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/hooks/useLocalStore.ts | ||
@@ -161,5 +124,8 @@ let localStoreCounter = 0; | ||
| if (!storeRef.current) storeRef.current = require_ActionContext.createStore(name || `localStore_${++localStoreCounter}`, initialValue); | ||
| const store = storeRef.current; | ||
| return { | ||
| ...useStoreSelector(storeRef.current), | ||
| store: storeRef.current | ||
| value: require_ActionContext.useStoreValue(store), | ||
| name: store.name, | ||
| lastUpdate: store.getSnapshot().lastUpdate, | ||
| store | ||
| }; | ||
@@ -169,31 +135,45 @@ } | ||
| //#endregion | ||
| exports.ContextActionError = require_error_handling.ContextActionError; | ||
| exports.ContextActionErrorType = require_error_handling.ContextActionErrorType; | ||
| exports.ImmerUtils = require_error_handling.ImmerUtils; | ||
| exports.ContextActionError = require_ActionContext.ContextActionError; | ||
| exports.ContextActionErrorType = require_ActionContext.ContextActionErrorType; | ||
| Object.defineProperty(exports, 'MutativeUtils', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.MutativeUtils; | ||
| } | ||
| }); | ||
| exports.StoreErrorBoundary = require_ActionContext.StoreErrorBoundary; | ||
| exports.StoreRegistry = require_ActionContext.StoreRegistry; | ||
| exports.SubscriptionManager = require_utils.SubscriptionManager; | ||
| exports.TypeUtils = require_utils.TypeUtils; | ||
| exports.compareValues = require_error_handling.compareValues; | ||
| exports.compareValues = require_comparison.compareValues; | ||
| exports.composeProviders = require_utils.composeProviders; | ||
| exports.createActionContext = require_ActionContext.createActionContext; | ||
| exports.createSafeEqualityFn = require_utils.createSafeEqualityFn; | ||
| exports.createStoreConfig = require_utils.createStoreConfig; | ||
| exports.createStoreErrorBoundary = require_ActionContext.createStoreErrorBoundary; | ||
| exports.deepClone = require_error_handling.deepClone; | ||
| exports.deepCloneWithImmer = require_error_handling.deepCloneWithImmer; | ||
| exports.extractStoreValue = require_utils.extractStoreValue; | ||
| exports.extractStoreValues = require_utils.extractStoreValues; | ||
| exports.getGlobalComparisonOptions = require_error_handling.getGlobalComparisonOptions; | ||
| exports.handleContextActionError = require_error_handling.handleError; | ||
| exports.isStore = require_utils.isStore; | ||
| exports.isValidStoreValue = require_utils.isValidStoreValue; | ||
| exports.preloadImmer = require_error_handling.preloadImmer; | ||
| exports.produce = require_error_handling.produce; | ||
| exports.safeGet = require_error_handling.safeGet; | ||
| exports.safeSet = require_error_handling.safeSet; | ||
| exports.setGlobalComparisonOptions = require_error_handling.setGlobalComparisonOptions; | ||
| Object.defineProperty(exports, 'deepClone', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.deepClone; | ||
| } | ||
| }); | ||
| exports.getGlobalComparisonOptions = require_comparison.getGlobalComparisonOptions; | ||
| exports.handleContextActionError = require_ActionContext.handleError; | ||
| Object.defineProperty(exports, 'produce', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.produce; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'safeGet', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.safeGet; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'safeSet', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.safeSet; | ||
| } | ||
| }); | ||
| exports.setGlobalComparisonOptions = require_comparison.setGlobalComparisonOptions; | ||
| exports.useComputedStore = useComputedStore; | ||
| exports.useLocalStore = useLocalStore; | ||
| exports.useSubscriptionManager = require_utils.useSubscriptionManager; | ||
| exports.withStoreErrorBoundary = require_ActionContext.withStoreErrorBoundary; |
@@ -1,4 +0,4 @@ | ||
| import { ComparisonOptions, ComparisonStrategy, CustomComparator, DynamicStoreOptions, HookOptions, React18Options, Snapshot, Store, StoreRegistry, StoreSyncConfig, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store--dj9U0mo.cjs"; | ||
| import { DeepReadonly, EqualityFunction, ImmerUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, useSubscriptionManager } from "./utils-Cq-l1Kd1.cjs"; | ||
| import { ActionContextConfig, ActionContextReturn, ContextActionError, ContextActionErrorType, StoreErrorBoundary, StoreErrorBoundaryProps, StoreErrorBoundaryState, createActionContext, createStoreErrorBoundary, handleError, withStoreErrorBoundary } from "./ActionContext-BnM5V83y.cjs"; | ||
| import { a as ComparisonStrategy, c as getGlobalComparisonOptions, d as HookOptions, g as Snapshot, h as React18Options, i as ComparisonOptions, l as setGlobalComparisonOptions, n as Store, o as CustomComparator, s as compareValues, u as DynamicStoreOptions, v as StoreSyncConfig } from "./Store.cjs"; | ||
| import { a as StoreErrorBoundary, c as createStoreErrorBoundary, d as ContextActionErrorType, f as handleError, l as withStoreErrorBoundary, n as ActionContextConfig, o as StoreErrorBoundaryProps, p as StoreRegistry, r as ActionContextReturn, s as StoreErrorBoundaryState, t as createActionContext, u as ContextActionError } from "./ActionContext.cjs"; | ||
| import { _ as StoreValue, a as safeSet, c as DeepReadonly, d as RequiredBy, f as StoreInitConfig, g as StoreUpdater, h as StoreSelector, i as safeGet, l as EqualityFunction, m as StoreRecordValues, n as deepClone, o as ProviderComponent, p as StoreListener, r as produce, s as composeProviders, t as MutativeUtils, u as PartialBy, v as StoresValues } from "./utils2.cjs"; | ||
@@ -23,3 +23,3 @@ //#region src/stores/hooks/useComputedStore.d.ts | ||
| //#endregion | ||
| export { type ActionContextConfig, type ActionContextReturn, ComparisonOptions, ComparisonStrategy, ContextActionError, ContextActionErrorType, CustomComparator, DeepReadonly, type DynamicStoreOptions, EqualityFunction, type HookOptions, ImmerUtils, PartialBy, ProviderComponent, type React18Options, RequiredBy, StoreErrorBoundary, type StoreErrorBoundaryProps, type StoreErrorBoundaryState, StoreInitConfig, StoreListener, StoreRecordValues, StoreRegistry, StoreSelector, type StoreSyncConfig, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, compareValues, composeProviders, createActionContext, createSafeEqualityFn, createStoreConfig, createStoreErrorBoundary, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, handleError as handleContextActionError, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useComputedStore, useLocalStore, useSubscriptionManager, withStoreErrorBoundary }; | ||
| export { type ActionContextConfig, type ActionContextReturn, ComparisonOptions, ComparisonStrategy, ContextActionError, ContextActionErrorType, CustomComparator, DeepReadonly, type DynamicStoreOptions, EqualityFunction, type HookOptions, MutativeUtils, PartialBy, ProviderComponent, type React18Options, RequiredBy, StoreErrorBoundary, type StoreErrorBoundaryProps, type StoreErrorBoundaryState, StoreInitConfig, StoreListener, StoreRecordValues, StoreRegistry, StoreSelector, type StoreSyncConfig, StoreUpdater, StoreValue, StoresValues, compareValues, composeProviders, createActionContext, createStoreErrorBoundary, deepClone, getGlobalComparisonOptions, handleError as handleContextActionError, produce, safeGet, safeSet, setGlobalComparisonOptions, useComputedStore, useLocalStore, withStoreErrorBoundary }; | ||
| //# sourceMappingURL=advanced.d.cts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"advanced.d.cts","names":[],"sources":["../src/stores/hooks/useComputedStore.ts","../src/stores/hooks/useLocalStore.ts"],"sourcesContent":[],"mappings":";;;;;UA4BiB;mBAEE,MAAM;;;EAFR,YAAA,CAAA,EAWA,CAXA;EAAmB,OAAA,CAAA,EAAA,CAAA,KAAA,EAchB,KAdgB,EAAA,GAAA,IAAA;YAEjB,CAAA,EAAA,MAAA;aAAM,CAAA,EAAA,OAAA;WASR,CAAA,EAAA,MAAA;;AAGQ,iBAgCT,gBAhCS,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,KAAA,EAiChB,KAjCgB,CAiCV,CAjCU,CAAA,EAAA,OAAA,EAAA,CAAA,KAAA,EAkCN,CAlCM,EAAA,GAkCA,CAlCA,EAAA,MAAA,CAAA,EAmCf,mBAnCe,CAmCK,CAnCL,CAAA,CAAA,EAoCtB,CApCsB;;;iBClCT,+BACA,mBAEb,SAAS;SAAc,MAAM"} | ||
| {"version":3,"file":"advanced.d.cts","names":[],"sources":["../src/stores/hooks/useComputedStore.ts","../src/stores/hooks/useLocalStore.ts"],"sourcesContent":[],"mappings":";;;;;UA2BiB;mBAEE,MAAM;;;EAFR,YAAA,CAAA,EAWA,CAXA;EAEE,OAAA,CAAA,EAAA,CAAA,KAAA,EAYC,KAZD,EAAA,GAAA,IAAA;EAAM,UAAA,CAAA,EAAA,MAAA;EASR,WAAA,CAAA,EAAA,OAAA;EAGG,SAAA,CAAA,EAAA,MAAA;;AAgCJ,iBAAA,gBAAgB,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,KAAA,EACvB,KADuB,CACjB,CADiB,CAAA,EAAA,OAAA,EAAA,CAAA,KAAA,EAEb,CAFa,EAAA,GAEP,CAFO,EAAA,MAAA,CAAA,EAGtB,mBAHsB,CAGF,CAHE,CAAA,CAAA,EAI7B,CAJ6B;;;iBCjEhB,+BACA,mBAEb,SAAS;SAAc,MAAM"} |
@@ -1,4 +0,4 @@ | ||
| import { ComparisonOptions, ComparisonStrategy, CustomComparator, DynamicStoreOptions, HookOptions, React18Options, Snapshot, Store, StoreRegistry, StoreSyncConfig, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store-CoQcuZnp.js"; | ||
| import { DeepReadonly, EqualityFunction, ImmerUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, useSubscriptionManager } from "./utils-DGg-aIzZ.js"; | ||
| import { ActionContextConfig, ActionContextReturn, ContextActionError, ContextActionErrorType, StoreErrorBoundary, StoreErrorBoundaryProps, StoreErrorBoundaryState, createActionContext, createStoreErrorBoundary, handleError, withStoreErrorBoundary } from "./ActionContext-Cq5LNd0Y.js"; | ||
| import { a as ComparisonStrategy, c as getGlobalComparisonOptions, d as HookOptions, g as Snapshot, h as React18Options, i as ComparisonOptions, l as setGlobalComparisonOptions, n as Store, o as CustomComparator, s as compareValues, u as DynamicStoreOptions, v as StoreSyncConfig } from "./Store.js"; | ||
| import { a as StoreErrorBoundary, c as createStoreErrorBoundary, d as ContextActionErrorType, f as handleError, l as withStoreErrorBoundary, n as ActionContextConfig, o as StoreErrorBoundaryProps, p as StoreRegistry, r as ActionContextReturn, s as StoreErrorBoundaryState, t as createActionContext, u as ContextActionError } from "./ActionContext.js"; | ||
| import { _ as StoreValue, a as safeSet, c as DeepReadonly, d as RequiredBy, f as StoreInitConfig, g as StoreUpdater, h as StoreSelector, i as safeGet, l as EqualityFunction, m as StoreRecordValues, n as deepClone, o as ProviderComponent, p as StoreListener, r as produce, s as composeProviders, t as MutativeUtils, u as PartialBy, v as StoresValues } from "./utils2.js"; | ||
@@ -23,3 +23,3 @@ //#region src/stores/hooks/useComputedStore.d.ts | ||
| //#endregion | ||
| export { type ActionContextConfig, type ActionContextReturn, ComparisonOptions, ComparisonStrategy, ContextActionError, ContextActionErrorType, CustomComparator, DeepReadonly, type DynamicStoreOptions, EqualityFunction, type HookOptions, ImmerUtils, PartialBy, ProviderComponent, type React18Options, RequiredBy, StoreErrorBoundary, type StoreErrorBoundaryProps, type StoreErrorBoundaryState, StoreInitConfig, StoreListener, StoreRecordValues, StoreRegistry, StoreSelector, type StoreSyncConfig, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, compareValues, composeProviders, createActionContext, createSafeEqualityFn, createStoreConfig, createStoreErrorBoundary, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, handleError as handleContextActionError, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useComputedStore, useLocalStore, useSubscriptionManager, withStoreErrorBoundary }; | ||
| export { type ActionContextConfig, type ActionContextReturn, ComparisonOptions, ComparisonStrategy, ContextActionError, ContextActionErrorType, CustomComparator, DeepReadonly, type DynamicStoreOptions, EqualityFunction, type HookOptions, MutativeUtils, PartialBy, ProviderComponent, type React18Options, RequiredBy, StoreErrorBoundary, type StoreErrorBoundaryProps, type StoreErrorBoundaryState, StoreInitConfig, StoreListener, StoreRecordValues, StoreRegistry, StoreSelector, type StoreSyncConfig, StoreUpdater, StoreValue, StoresValues, compareValues, composeProviders, createActionContext, createStoreErrorBoundary, deepClone, getGlobalComparisonOptions, handleError as handleContextActionError, produce, safeGet, safeSet, setGlobalComparisonOptions, useComputedStore, useLocalStore, withStoreErrorBoundary }; | ||
| //# sourceMappingURL=advanced.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"advanced.d.ts","names":[],"sources":["../src/stores/hooks/useComputedStore.ts","../src/stores/hooks/useLocalStore.ts"],"sourcesContent":[],"mappings":";;;;;UA4BiB;mBAEE,MAAM;;;EAFR,YAAA,CAAA,EAWA,CAXA;EAAmB,OAAA,CAAA,EAAA,CAAA,KAAA,EAchB,KAdgB,EAAA,GAAA,IAAA;YAEjB,CAAA,EAAA,MAAA;aAAM,CAAA,EAAA,OAAA;WASR,CAAA,EAAA,MAAA;;AAGQ,iBAgCT,gBAhCS,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,KAAA,EAiChB,KAjCgB,CAiCV,CAjCU,CAAA,EAAA,OAAA,EAAA,CAAA,KAAA,EAkCN,CAlCM,EAAA,GAkCA,CAlCA,EAAA,MAAA,CAAA,EAmCf,mBAnCe,CAmCK,CAnCL,CAAA,CAAA,EAoCtB,CApCsB;;;iBClCT,+BACA,mBAEb,SAAS;SAAc,MAAM"} | ||
| {"version":3,"file":"advanced.d.ts","names":[],"sources":["../src/stores/hooks/useComputedStore.ts","../src/stores/hooks/useLocalStore.ts"],"sourcesContent":[],"mappings":";;;;;UA2BiB;mBAEE,MAAM;;;EAFR,YAAA,CAAA,EAWA,CAXA;EAEE,OAAA,CAAA,EAAA,CAAA,KAAA,EAYC,KAZD,EAAA,GAAA,IAAA;EAAM,UAAA,CAAA,EAAA,MAAA;EASR,WAAA,CAAA,EAAA,OAAA;EAGG,SAAA,CAAA,EAAA,MAAA;;AAgCJ,iBAAA,gBAAgB,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,KAAA,EACvB,KADuB,CACjB,CADiB,CAAA,EAAA,OAAA,EAAA,CAAA,KAAA,EAEb,CAFa,EAAA,GAEP,CAFO,EAAA,MAAA,CAAA,EAGtB,mBAHsB,CAGF,CAHE,CAAA,CAAA,EAI7B,CAJ6B;;;iBCjEhB,+BACA,mBAEb,SAAS;SAAc,MAAM"} |
+21
-55
@@ -1,8 +0,17 @@ | ||
| import { StoreErrorBoundary, StoreRegistry, createActionContext, createStore, createStoreErrorBoundary, defaultEqualityFn, useSafeStoreSubscription, withStoreErrorBoundary } from "./ActionContext-BIIFgZEq.js"; | ||
| import { ContextActionError, ContextActionErrorType, ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getGlobalComparisonOptions, handleError, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions } from "./error-handling-CkdfKCZ0.js"; | ||
| import { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager } from "./utils-B_r1_2dw.js"; | ||
| import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react"; | ||
| import { a as useStoreValue, c as ContextActionError, d as handleError, g as StoreRegistry, h as useSafeStoreSubscription, i as withStoreErrorBoundary, l as ContextActionErrorType, n as StoreErrorBoundary, p as defaultEqualityFn, r as createStoreErrorBoundary, s as createStore, t as createActionContext } from "./ActionContext.js"; | ||
| import { a as setGlobalComparisonOptions, r as getGlobalComparisonOptions, t as compareValues } from "./comparison.js"; | ||
| import { a as safeSet, i as safeGet, n as deepClone, o as composeProviders, r as produce, t as MutativeUtils } from "./utils2.js"; | ||
| import { useCallback, useRef } from "react"; | ||
| //#region src/stores/hooks/useComputedStore.ts | ||
| /** | ||
| * Computed Store Pattern - Automated derived state management | ||
| * | ||
| * Manages automatically computed derived state based on one or more stores. | ||
| * Optimizes performance by recalculating only when dependencies change. | ||
| * Essential for complex applications with derived data relationships. | ||
| * | ||
| * @module stores/hooks/useComputedStore | ||
| */ | ||
| /** | ||
| * Hook for computed store based on a single source store | ||
@@ -31,4 +40,4 @@ * | ||
| const cacheRef = useRef(/* @__PURE__ */ new Map()); | ||
| const lastComputedRef = useRef(); | ||
| const lastInputRef = useRef(); | ||
| const lastComputedRef = useRef(void 0); | ||
| const lastInputRef = useRef(void 0); | ||
| computeRef.current = compute; | ||
@@ -108,48 +117,2 @@ const getCachedValue = useCallback((input) => { | ||
| //#endregion | ||
| //#region src/stores/utils/store-selector.ts | ||
| /** | ||
| * Store sync 상수 정의 | ||
| * 핵심 기능: 안전한 기본값과 에러 처리를 위한 상수 제공 | ||
| */ | ||
| const CONSTANTS = { | ||
| EMPTY_SUBSCRIBE: () => () => {}, | ||
| EMPTY_SNAPSHOT: () => ({ | ||
| value: void 0, | ||
| name: "empty", | ||
| lastUpdate: 0 | ||
| }) | ||
| }; | ||
| /** | ||
| * Store Selector Hook - 선택적 데이터 구독 | ||
| * @implements computed-store | ||
| * @implements fresh-state-access | ||
| * @implements performance-optimization | ||
| * @memberof core-concepts | ||
| * | ||
| * 핵심 기능: selector를 사용하여 Store의 특정 부분만 구독하고 반환 | ||
| * | ||
| * @template T Store 값 타입 | ||
| * @template R 반환 타입 (기본값: Snapshot<T>) | ||
| * @param store - 구독할 Store 인스턴스 | ||
| * @param config - 선택적 설정 (selector, defaultValue) | ||
| * @returns 선택된 값 또는 스냅샷 | ||
| * | ||
| * 핵심 로직 흐름: | ||
| * 1. store.getSnapshot() - 현재 상태 가져오기 | ||
| * 2. selector 적용 (있을 경우) - 필요한 부분만 추출 | ||
| * 3. useSyncExternalStore() - React와 동기화 | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#selective-subscriptions | ||
| */ | ||
| function useStoreSelector(store, config) { | ||
| const { defaultValue, selector } = config ?? {}; | ||
| const getSnapshot = store?.getSnapshot ?? (() => ({ | ||
| ...CONSTANTS.EMPTY_SNAPSHOT(), | ||
| ...defaultValue !== void 0 && { value: defaultValue } | ||
| })); | ||
| const selectedGetSnapshot = selector ? () => selector(getSnapshot()) : getSnapshot; | ||
| return useSyncExternalStore(store?.subscribe ?? CONSTANTS.EMPTY_SUBSCRIBE, selectedGetSnapshot); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/hooks/useLocalStore.ts | ||
@@ -160,5 +123,8 @@ let localStoreCounter = 0; | ||
| if (!storeRef.current) storeRef.current = createStore(name || `localStore_${++localStoreCounter}`, initialValue); | ||
| const store = storeRef.current; | ||
| return { | ||
| ...useStoreSelector(storeRef.current), | ||
| store: storeRef.current | ||
| value: useStoreValue(store), | ||
| name: store.name, | ||
| lastUpdate: store.getSnapshot().lastUpdate, | ||
| store | ||
| }; | ||
@@ -168,3 +134,3 @@ } | ||
| //#endregion | ||
| export { ContextActionError, ContextActionErrorType, ImmerUtils, StoreErrorBoundary, StoreRegistry, SubscriptionManager, TypeUtils, compareValues, composeProviders, createActionContext, createSafeEqualityFn, createStoreConfig, createStoreErrorBoundary, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, handleError as handleContextActionError, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useComputedStore, useLocalStore, useSubscriptionManager, withStoreErrorBoundary }; | ||
| export { ContextActionError, ContextActionErrorType, MutativeUtils, StoreErrorBoundary, StoreRegistry, compareValues, composeProviders, createActionContext, createStoreErrorBoundary, deepClone, getGlobalComparisonOptions, handleError as handleContextActionError, produce, safeGet, safeSet, setGlobalComparisonOptions, useComputedStore, useLocalStore, withStoreErrorBoundary }; | ||
| //# sourceMappingURL=advanced.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"advanced.js","names":[],"sources":["../src/stores/hooks/useComputedStore.ts","../src/stores/utils/store-selector.ts","../src/stores/hooks/useLocalStore.ts"],"sourcesContent":["/**\n * Computed Store Pattern - Automated derived state management\n * \n * Manages automatically computed derived state based on one or more stores.\n * Optimizes performance by recalculating only when dependencies change.\n * Essential for complex applications with derived data relationships.\n * \n * @module stores/hooks/useComputedStore\n */\n\nimport { useMemo, useRef, useCallback, useEffect, useState } from 'react';\nimport { createStore } from '../core/Store';\nimport type { Store } from '../core/Store';\nimport { defaultEqualityFn } from './useStoreSelector';\nimport { useSafeStoreSubscription, useMultiStoreSubscription } from '../utils/sync-external-store-utils';\n\n/**\n * Configuration options for computed store hooks\n * \n * Comprehensive configuration interface for controlling computed store behavior,\n * including performance optimizations, debugging, error handling, and caching strategies.\n * \n * @template R - Type of the computed value\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#performance-optimized-with-caching\n * \n * @public\n */\nexport interface ComputedStoreConfig<R> {\n /** Equality comparison function for computed values */\n equalityFn?: (a: R, b: R) => boolean;\n \n /** Enable debug logging for computation tracking */\n debug?: boolean;\n \n /** Name identifier for the computed store (used in debugging) */\n name?: string;\n \n /** Initial value used before first computation */\n initialValue?: R;\n \n /** Error handler for computation failures */\n onError?: (error: Error) => void;\n \n /** Debounce delay for computation in milliseconds */\n debounceMs?: number;\n \n /** Enable result caching for performance optimization */\n enableCache?: boolean;\n \n /** Maximum number of cached results to maintain */\n cacheSize?: number;\n}\n\n/**\n * Hook for computed store based on a single source store\n * \n * Creates a derived value that automatically recalculates when the source store changes.\n * Includes performance optimizations like caching, debouncing, and intelligent re-computation\n * to prevent unnecessary work. Perfect for derived state patterns.\n * \n * @template T - Type of the source store value\n * @template R - Type of the computed result\n * \n * @param store - Source store to derive from\n * @param compute - Function to compute derived value from store value\n * @param config - Optional configuration for performance and debugging\n * \n * @returns The computed value that updates when source store changes\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usecomputedstore-patterns\n * \n * @public\n */\nexport function useComputedStore<T, R>(\n store: Store<T>,\n compute: (value: T) => R,\n config: ComputedStoreConfig<R> = {}\n): R {\n const {\n equalityFn = defaultEqualityFn,\n debug = false,\n name = 'computed',\n onError,\n debounceMs,\n enableCache = false,\n cacheSize = 10,\n initialValue\n } = config;\n\n // Refs for stable references\n const computeRef = useRef(compute);\n const cacheRef = useRef<Map<T, R>>(new Map());\n const lastComputedRef = useRef<R>();\n const lastInputRef = useRef<T>();\n\n // Update compute function ref on every render\n computeRef.current = compute;\n\n // Cache management functions\n const getCachedValue = useCallback((input: T): R | undefined => {\n if (!enableCache) return undefined;\n\n // Check if we have exact same input reference\n if (lastInputRef.current === input && lastComputedRef.current !== undefined) {\n return lastComputedRef.current;\n }\n\n // Check cache map\n for (const [cachedInput, cachedOutput] of cacheRef.current) {\n if (defaultEqualityFn(cachedInput, input)) {\n if (debug) {\n console.debug(`useComputedStore [${name}]: Using cached value`);\n }\n return cachedOutput;\n }\n }\n\n return undefined;\n }, [enableCache, debug, name]);\n\n const setCachedValue = useCallback((input: T, output: R) => {\n if (!enableCache) return;\n\n // Update last computed values\n lastInputRef.current = input;\n lastComputedRef.current = output;\n\n // Update cache map\n cacheRef.current.set(input, output);\n\n // Limit cache size\n if (cacheRef.current.size > cacheSize) {\n const firstKey = cacheRef.current.keys().next().value;\n if (firstKey !== undefined) {\n cacheRef.current.delete(firstKey);\n }\n }\n\n if (debug) {\n console.debug(`useComputedStore [${name}]: Cache updated`, {\n cacheSize: cacheRef.current.size,\n input,\n output\n });\n }\n }, [enableCache, cacheSize, debug, name]);\n\n // Computation selector function for useSyncExternalStore\n const computeSelector = useCallback((value: T): R => {\n try {\n // Check cache first\n const cached = getCachedValue(value);\n if (cached !== undefined) {\n return cached;\n }\n\n // Perform computation\n const startTime = debug ? performance.now() : 0;\n const result = computeRef.current(value);\n\n if (debug) {\n const duration = performance.now() - startTime;\n console.debug(`useComputedStore [${name}]: Computed in ${duration.toFixed(2)}ms`, {\n input: value,\n result\n });\n }\n\n // Cache the result and update last computed\n setCachedValue(value, result);\n lastComputedRef.current = result;\n\n return result;\n } catch (error) {\n if (onError) {\n onError(error as Error);\n // Return last valid value or initial value on error\n const fallbackValue = lastComputedRef.current !== undefined\n ? lastComputedRef.current\n : initialValue as R;\n return fallbackValue;\n }\n\n if (debug) {\n console.error(`useComputedStore [${name}]: Error in computation:`, error);\n }\n\n // Re-throw if no error handler\n throw error;\n }\n }, [getCachedValue, setCachedValue, debug, name, onError, initialValue]);\n\n // Use optimized subscription with selector\n const computedValue = useSafeStoreSubscription(\n store,\n computeSelector,\n {\n equalityFn,\n debounce: debounceMs,\n debug,\n name: `computed-${name}`,\n initialValue\n }\n );\n\n return computedValue as R;\n}\n\n/**\n * 여러 Store 기반 Computed Hook\n * \n * @template T1, T2, R Store 타입들과 결과 타입\n * @param stores 의존성 Store들\n * @param compute 계산 함수\n * @param config 설정 옵션\n * @returns 계산된 값\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usecomputedstore-patterns\n */\nexport function useMultiComputedStore<R>(\n stores: Store<any>[],\n compute: (values: any[]) => R,\n config?: ComputedStoreConfig<R>\n): R {\n const finalConfig = config || {};\n const {\n equalityFn = defaultEqualityFn,\n debug = false,\n name = 'multiComputed',\n onError,\n enableCache = false,\n cacheSize = 10,\n initialValue\n } = finalConfig;\n\n // Refs for stable references\n const computeRef = useRef(compute);\n const cacheRef = useRef<Map<string, R>>(new Map());\n const lastComputedRef = useRef<R>();\n const lastInputsRef = useRef<any[]>();\n\n // Update compute function ref\n computeRef.current = compute;\n\n // Create cache key from inputs\n const getCacheKey = useCallback((inputs: any[]): string => {\n try {\n return JSON.stringify(inputs);\n } catch {\n // Fallback for non-serializable inputs\n return inputs.map((v, i) => `${i}:${typeof v}`).join(',');\n }\n }, []);\n\n // Cache management\n const getCachedValue = useCallback((inputs: any[]): R | undefined => {\n if (!enableCache) return undefined;\n\n // Check if inputs are exactly the same reference\n if (lastInputsRef.current === inputs && lastComputedRef.current !== undefined) {\n return lastComputedRef.current;\n }\n\n // Check if inputs are equal to last inputs\n if (lastInputsRef.current &&\n lastInputsRef.current.length === inputs.length &&\n lastInputsRef.current.every((v, i) => defaultEqualityFn(v, inputs[i]))) {\n return lastComputedRef.current;\n }\n\n // Check cache map\n const key = getCacheKey(inputs);\n const cached = cacheRef.current.get(key);\n\n if (cached !== undefined && debug) {\n console.debug(`useMultiComputedStore [${name}]: Using cached value`);\n }\n\n return cached;\n }, [enableCache, debug, name, getCacheKey]);\n\n const setCachedValue = useCallback((inputs: any[], output: R) => {\n if (!enableCache) return;\n\n // Update last computed values\n lastInputsRef.current = inputs;\n lastComputedRef.current = output;\n\n // Update cache map\n const key = getCacheKey(inputs);\n cacheRef.current.set(key, output);\n\n // Limit cache size\n if (cacheRef.current.size > cacheSize) {\n const firstKey = cacheRef.current.keys().next().value;\n if (firstKey !== undefined) {\n cacheRef.current.delete(firstKey);\n }\n }\n\n if (debug) {\n console.debug(`useMultiComputedStore [${name}]: Cache updated`, {\n cacheSize: cacheRef.current.size,\n inputs,\n output\n });\n }\n }, [enableCache, cacheSize, debug, name, getCacheKey]);\n\n // Computation selector for multi-store subscription\n const computeSelector = useCallback((values: any[]): R => {\n try {\n // Check cache first\n const cached = getCachedValue(values);\n if (cached !== undefined) {\n return cached;\n }\n\n // Perform computation\n const startTime = debug ? performance.now() : 0;\n const result = computeRef.current(values);\n\n if (debug) {\n const duration = performance.now() - startTime;\n console.debug(`useMultiComputedStore [${name}]: Computed in ${duration.toFixed(2)}ms`, {\n inputs: values,\n result\n });\n }\n\n // Cache the result and update last computed\n setCachedValue(values, result);\n lastComputedRef.current = result;\n\n return result;\n } catch (error) {\n if (onError) {\n onError(error as Error);\n // Return last valid value or initial value on error\n const fallbackValue = lastComputedRef.current !== undefined\n ? lastComputedRef.current\n : initialValue as R;\n return fallbackValue;\n }\n\n if (debug) {\n console.error(`useMultiComputedStore [${name}]: Error in computation:`, error);\n }\n\n throw error;\n }\n }, [getCachedValue, setCachedValue, debug, name, onError, initialValue]);\n\n // Use optimized multi-store subscription\n const computedValue = useMultiStoreSubscription(\n stores as any,\n computeSelector,\n equalityFn\n );\n\n return computedValue;\n}\n\n/**\n * Computed Store 인스턴스를 생성하는 Hook\n * \n * 계산된 값을 실제 Store 인스턴스로 반환하여 다른 곳에서 구독할 수 있게 합니다.\n * \n * @template T1, T2, R Store 타입들과 결과 타입\n * @param dependencies 의존성 Store들\n * @param compute 계산 함수\n * @param config 설정 옵션\n * @returns 계산된 값을 가진 Store 인스턴스\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#computed-store-instances\n */\nexport function useComputedStoreInstance<R>(\n dependencies: Store<any>[],\n compute: (values: any[]) => R,\n config?: ComputedStoreConfig<R>\n): Store<R> {\n const finalConfig = config || {};\n const computedValue = useMultiComputedStore(dependencies, compute, config);\n \n // Computed Store 인스턴스를 메모이제이션\n const computedStore = useMemo(() => {\n const storeName = finalConfig.name || `computed-${Date.now()}`;\n const store = createStore(storeName, computedValue);\n \n if (finalConfig.debug) {\n console.log(`useComputedStoreInstance: Created store [${storeName}]`);\n }\n \n return store;\n }, [finalConfig.name, finalConfig.debug, computedValue]);\n \n // 계산된 값이 변경될 때마다 Store 업데이트\n useEffect(() => {\n computedStore.setValue(computedValue);\n }, [computedValue, computedStore]);\n \n return computedStore;\n}\n\n/**\n * 비동기 계산을 지원하는 Computed Store Hook\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#async-computed-patterns\n */\nexport function useAsyncComputedStore<R>(\n dependencies: Store<any>[],\n compute: (values: any[]) => Promise<R>,\n config: ComputedStoreConfig<R> & { \n loadingValue?: R;\n errorValue?: R;\n } = {}\n): { \n value: R; \n loading: boolean; \n error: Error | null; \n reload: () => void;\n} {\n const {\n initialValue,\n loadingValue,\n errorValue,\n name = 'asyncComputed',\n debug = false,\n onError\n } = config;\n \n // Dependencies 값 구독 - Hook 규칙을 지키기 위해 수정\n const currentValues = useMemo(() => {\n return dependencies.map(store => store.getValue());\n }, [dependencies]);\n const [state, setState] = useState<{\n value: R;\n loading: boolean;\n error: Error | null;\n }>(() => ({\n value: initialValue || loadingValue as R,\n loading: false,\n error: null\n }));\n \n const computeRef = useRef(compute);\n computeRef.current = compute;\n \n const reload = useCallback(async () => {\n setState(prev => ({ ...prev, loading: true, error: null }));\n \n try {\n const result = await computeRef.current(currentValues);\n setState({ value: result, loading: false, error: null });\n \n if (debug) {\n console.debug(`useAsyncComputedStore [${name}]: Async computation completed`, result);\n }\n } catch (error) {\n const err = error as Error;\n setState({ \n value: errorValue !== undefined ? errorValue : state.value, \n loading: false, \n error: err \n });\n \n if (onError) {\n onError(err);\n } else if (debug) {\n console.error(`useAsyncComputedStore [${name}]: Async computation failed:`, err);\n }\n }\n }, [currentValues, errorValue, state.value, name, debug, onError]);\n \n // 의존성 변경 시 재계산\n useEffect(() => {\n reload();\n }, [reload]);\n \n return {\n value: state.value,\n loading: state.loading,\n error: state.error,\n reload\n };\n}","import { useSyncExternalStore } from 'react';\nimport type { IStore, Snapshot, StoreSyncConfig } from '../core/types';\n\n/**\n * Store sync 상수 정의\n * 핵심 기능: 안전한 기본값과 에러 처리를 위한 상수 제공\n */\nconst CONSTANTS = {\n // store가 없을 때 사용하는 빈 구독 함수\n EMPTY_SUBSCRIBE: () => () => {},\n // store가 없을 때 사용하는 빈 스냅샷 생성\n EMPTY_SNAPSHOT: <T>(): Snapshot<T> => ({\n value: undefined as T,\n name: 'empty',\n lastUpdate: 0\n })\n} as const;\n\n/**\n * Store Selector Hook - 선택적 데이터 구독\n * @implements computed-store\n * @implements fresh-state-access\n * @implements performance-optimization\n * @memberof core-concepts\n * \n * 핵심 기능: selector를 사용하여 Store의 특정 부분만 구독하고 반환\n * \n * @template T Store 값 타입\n * @template R 반환 타입 (기본값: Snapshot<T>)\n * @param store - 구독할 Store 인스턴스\n * @param config - 선택적 설정 (selector, defaultValue)\n * @returns 선택된 값 또는 스냅샷\n * \n * 핵심 로직 흐름:\n * 1. store.getSnapshot() - 현재 상태 가져오기\n * 2. selector 적용 (있을 경우) - 필요한 부분만 추출\n * 3. useSyncExternalStore() - React와 동기화\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#selective-subscriptions\n */\nexport function useStoreSelector<T, R = Snapshot<T>>(\n store: IStore<T> | undefined | null,\n config?: StoreSyncConfig<T, R>\n): R {\n const { defaultValue, selector } = config ?? {};\n\n // Store 스냅샷 가져오기 함수 (fallback 포함)\n const getSnapshot = store?.getSnapshot ?? (() => ({\n ...CONSTANTS.EMPTY_SNAPSHOT<T>(),\n ...(defaultValue !== undefined && { value: defaultValue })\n }));\n\n // Selector 적용하여 필요한 데이터만 추출\n const selectedGetSnapshot = selector\n ? () => selector(getSnapshot())\n : getSnapshot;\n\n // React의 useSyncExternalStore로 동기화\n return useSyncExternalStore(\n store?.subscribe ?? CONSTANTS.EMPTY_SUBSCRIBE,\n selectedGetSnapshot as () => R\n );\n}\n\n","import { useRef } from 'react';\nimport { Store, createStore } from '../core/Store';\nimport { useStoreSelector } from '../utils/store-selector';\nimport type { Snapshot } from '../core/types';\n\n// Counter for generating unique store names (more efficient than Date.now + Math.random)\nlet localStoreCounter = 0;\n\nexport function useLocalStore<T>(\n initialValue: T,\n name?: string\n): Snapshot<T> & { store: Store<T> } {\n const storeRef = useRef<Store<T> | null>(null);\n\n if (!storeRef.current) {\n // Use a simple counter for store naming instead of expensive Date.now() + Math.random()\n const storeName = name || `localStore_${++localStoreCounter}`;\n storeRef.current = createStore(storeName, initialValue);\n }\n\n const snapshot = useStoreSelector(storeRef.current);\n\n return {\n ...snapshot,\n store: storeRef.current\n };\n}\n\n"],"mappings":"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"} | ||
| {"version":3,"file":"advanced.js","names":[],"sources":["../src/stores/hooks/useComputedStore.ts","../src/stores/hooks/useLocalStore.ts"],"sourcesContent":["/**\n * Computed Store Pattern - Automated derived state management\n * \n * Manages automatically computed derived state based on one or more stores.\n * Optimizes performance by recalculating only when dependencies change.\n * Essential for complex applications with derived data relationships.\n * \n * @module stores/hooks/useComputedStore\n */\n\nimport { useRef, useCallback } from 'react';\nimport type { Store } from '../core/Store';\nimport { defaultEqualityFn } from './useStoreSelector';\nimport { useSafeStoreSubscription } from '../utils/sync-external-store-utils';\n\n/**\n * Configuration options for computed store hooks\n * \n * Comprehensive configuration interface for controlling computed store behavior,\n * including performance optimizations, debugging, error handling, and caching strategies.\n * \n * @template R - Type of the computed value\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#performance-optimized-with-caching\n * \n * @public\n */\nexport interface ComputedStoreConfig<R> {\n /** Equality comparison function for computed values */\n equalityFn?: (a: R, b: R) => boolean;\n \n /** Enable debug logging for computation tracking */\n debug?: boolean;\n \n /** Name identifier for the computed store (used in debugging) */\n name?: string;\n \n /** Initial value used before first computation */\n initialValue?: R;\n \n /** Error handler for computation failures */\n onError?: (error: Error) => void;\n \n /** Debounce delay for computation in milliseconds */\n debounceMs?: number;\n \n /** Enable result caching for performance optimization */\n enableCache?: boolean;\n \n /** Maximum number of cached results to maintain */\n cacheSize?: number;\n}\n\n/**\n * Hook for computed store based on a single source store\n * \n * Creates a derived value that automatically recalculates when the source store changes.\n * Includes performance optimizations like caching, debouncing, and intelligent re-computation\n * to prevent unnecessary work. Perfect for derived state patterns.\n * \n * @template T - Type of the source store value\n * @template R - Type of the computed result\n * \n * @param store - Source store to derive from\n * @param compute - Function to compute derived value from store value\n * @param config - Optional configuration for performance and debugging\n * \n * @returns The computed value that updates when source store changes\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usecomputedstore-patterns\n * \n * @public\n */\nexport function useComputedStore<T, R>(\n store: Store<T>,\n compute: (value: T) => R,\n config: ComputedStoreConfig<R> = {}\n): R {\n const {\n equalityFn = defaultEqualityFn,\n debug = false,\n name = 'computed',\n onError,\n debounceMs,\n enableCache = false,\n cacheSize = 10,\n initialValue\n } = config;\n\n // Refs for stable references\n const computeRef = useRef(compute);\n const cacheRef = useRef<Map<T, R>>(new Map());\n const lastComputedRef = useRef<R | undefined>(undefined);\n const lastInputRef = useRef<T | undefined>(undefined);\n\n // Update compute function ref on every render\n computeRef.current = compute;\n\n // Cache management functions\n const getCachedValue = useCallback((input: T): R | undefined => {\n if (!enableCache) return undefined;\n\n // Check if we have exact same input reference\n if (lastInputRef.current === input && lastComputedRef.current !== undefined) {\n return lastComputedRef.current;\n }\n\n // Check cache map\n for (const [cachedInput, cachedOutput] of cacheRef.current) {\n if (defaultEqualityFn(cachedInput, input)) {\n if (debug) {\n console.debug(`useComputedStore [${name}]: Using cached value`);\n }\n return cachedOutput;\n }\n }\n\n return undefined;\n }, [enableCache, debug, name]);\n\n const setCachedValue = useCallback((input: T, output: R) => {\n if (!enableCache) return;\n\n // Update last computed values\n lastInputRef.current = input;\n lastComputedRef.current = output;\n\n // Update cache map\n cacheRef.current.set(input, output);\n\n // Limit cache size\n if (cacheRef.current.size > cacheSize) {\n const firstKey = cacheRef.current.keys().next().value;\n if (firstKey !== undefined) {\n cacheRef.current.delete(firstKey);\n }\n }\n\n if (debug) {\n console.debug(`useComputedStore [${name}]: Cache updated`, {\n cacheSize: cacheRef.current.size,\n input,\n output\n });\n }\n }, [enableCache, cacheSize, debug, name]);\n\n // Computation selector function for useSyncExternalStore\n const computeSelector = useCallback((value: T): R => {\n try {\n // Check cache first\n const cached = getCachedValue(value);\n if (cached !== undefined) {\n return cached;\n }\n\n // Perform computation\n const startTime = debug ? performance.now() : 0;\n const result = computeRef.current(value);\n\n if (debug) {\n const duration = performance.now() - startTime;\n console.debug(`useComputedStore [${name}]: Computed in ${duration.toFixed(2)}ms`, {\n input: value,\n result\n });\n }\n\n // Cache the result and update last computed\n setCachedValue(value, result);\n lastComputedRef.current = result;\n\n return result;\n } catch (error) {\n if (onError) {\n onError(error as Error);\n // Return last valid value or initial value on error\n const fallbackValue = lastComputedRef.current !== undefined\n ? lastComputedRef.current\n : initialValue as R;\n return fallbackValue;\n }\n\n if (debug) {\n console.error(`useComputedStore [${name}]: Error in computation:`, error);\n }\n\n // Re-throw if no error handler\n throw error;\n }\n }, [getCachedValue, setCachedValue, debug, name, onError, initialValue]);\n\n // Use optimized subscription with selector\n const computedValue = useSafeStoreSubscription(\n store,\n computeSelector,\n {\n equalityFn,\n debounce: debounceMs,\n debug,\n name: `computed-${name}`,\n initialValue\n }\n );\n\n return computedValue as R;\n}\n","import { useRef } from 'react';\nimport { Store, createStore } from '../core/Store';\nimport { useStoreValue } from './useStoreValue';\nimport type { Snapshot } from '../core/types';\n\n// Counter for generating unique store names (more efficient than Date.now + Math.random)\nlet localStoreCounter = 0;\n\nexport function useLocalStore<T>(\n initialValue: T,\n name?: string\n): Snapshot<T> & { store: Store<T> } {\n const storeRef = useRef<Store<T> | null>(null);\n\n if (!storeRef.current) {\n // Use a simple counter for store naming instead of expensive Date.now() + Math.random()\n const storeName = name || `localStore_${++localStoreCounter}`;\n storeRef.current = createStore(storeName, initialValue);\n }\n\n const store = storeRef.current;\n const value = useStoreValue(store);\n\n return {\n value,\n name: store.name,\n lastUpdate: store.getSnapshot().lastUpdate,\n store\n };\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEA,SAAgB,iBACd,OACA,SACA,SAAiC,EAAE,EAChC;CACH,MAAM,EACJ,aAAa,mBACb,QAAQ,OACR,OAAO,YACP,SACA,YACA,cAAc,OACd,YAAY,IACZ,iBACE;CAGJ,MAAM,aAAa,OAAO,QAAQ;CAClC,MAAM,WAAW,uBAAkB,IAAI,KAAK,CAAC;CAC7C,MAAM,kBAAkB,OAAsB,OAAU;CACxD,MAAM,eAAe,OAAsB,OAAU;AAGrD,YAAW,UAAU;CAGrB,MAAM,iBAAiB,aAAa,UAA4B;AAC9D,MAAI,CAAC,YAAa,QAAO;AAGzB,MAAI,aAAa,YAAY,SAAS,gBAAgB,YAAY,OAChE,QAAO,gBAAgB;AAIzB,OAAK,MAAM,CAAC,aAAa,iBAAiB,SAAS,QACjD,KAAI,kBAAkB,aAAa,MAAM,EAAE;AACzC,OAAI,MACF,SAAQ,MAAM,qBAAqB,KAAK,uBAAuB;AAEjE,UAAO;;IAKV;EAAC;EAAa;EAAO;EAAK,CAAC;CAE9B,MAAM,iBAAiB,aAAa,OAAU,WAAc;AAC1D,MAAI,CAAC,YAAa;AAGlB,eAAa,UAAU;AACvB,kBAAgB,UAAU;AAG1B,WAAS,QAAQ,IAAI,OAAO,OAAO;AAGnC,MAAI,SAAS,QAAQ,OAAO,WAAW;GACrC,MAAM,WAAW,SAAS,QAAQ,MAAM,CAAC,MAAM,CAAC;AAChD,OAAI,aAAa,OACf,UAAS,QAAQ,OAAO,SAAS;;AAIrC,MAAI,MACF,SAAQ,MAAM,qBAAqB,KAAK,mBAAmB;GACzD,WAAW,SAAS,QAAQ;GAC5B;GACA;GACD,CAAC;IAEH;EAAC;EAAa;EAAW;EAAO;EAAK,CAAC;AA4DzC,QAZsB,yBACpB,OA9CsB,aAAa,UAAgB;AACnD,MAAI;GAEF,MAAM,SAAS,eAAe,MAAM;AACpC,OAAI,WAAW,OACb,QAAO;GAIT,MAAM,YAAY,QAAQ,YAAY,KAAK,GAAG;GAC9C,MAAM,SAAS,WAAW,QAAQ,MAAM;AAExC,OAAI,OAAO;IACT,MAAM,WAAW,YAAY,KAAK,GAAG;AACrC,YAAQ,MAAM,qBAAqB,KAAK,iBAAiB,SAAS,QAAQ,EAAE,CAAC,KAAK;KAChF,OAAO;KACP;KACD,CAAC;;AAIJ,kBAAe,OAAO,OAAO;AAC7B,mBAAgB,UAAU;AAE1B,UAAO;WACA,OAAO;AACd,OAAI,SAAS;AACX,YAAQ,MAAe;AAKvB,WAHsB,gBAAgB,YAAY,SAC9C,gBAAgB,UAChB;;AAIN,OAAI,MACF,SAAQ,MAAM,qBAAqB,KAAK,2BAA2B,MAAM;AAI3E,SAAM;;IAEP;EAAC;EAAgB;EAAgB;EAAO;EAAM;EAAS;EAAa,CAAC,EAMtE;EACE;EACA,UAAU;EACV;EACA,MAAM,YAAY;EAClB;EACD,CACF;;;;;ACrMH,IAAI,oBAAoB;AAExB,SAAgB,cACd,cACA,MACmC;CACnC,MAAM,WAAW,OAAwB,KAAK;AAE9C,KAAI,CAAC,SAAS,QAGZ,UAAS,UAAU,YADD,QAAQ,cAAc,EAAE,qBACA,aAAa;CAGzD,MAAM,QAAQ,SAAS;AAGvB,QAAO;EACL,OAHY,cAAc,MAAM;EAIhC,MAAM,MAAM;EACZ,YAAY,MAAM,aAAa,CAAC;EAChC;EACD"} |
+262
-34
@@ -1,25 +0,129 @@ | ||
| import { ComparisonOptions, IStore, Snapshot, Store, StoreRegistry, createStore } from "./Store--dj9U0mo.cjs"; | ||
| import { ActionContextConfig, ActionContextReturn, ActionContextType, StoreErrorBoundary, StoreErrorBoundaryProps, createActionContext } from "./ActionContext-BnM5V83y.cjs"; | ||
| import React, { ReactNode } from "react"; | ||
| import { ActionHandler, ActionPayloadMap, ActionRegister, ActionRegisterConfig, ExecutionMode, HandlerConfig, PipelineController, UnregisterFunction } from "@context-action/core"; | ||
| import { _ as StoreSetValueOptions, f as IStore, g as Snapshot, i as ComparisonOptions, m as Listener, n as Store, r as createStore, t as PatchAwareListener, y as Unsubscribe } from "./Store.cjs"; | ||
| import { a as StoreErrorBoundary, i as ActionContextType, n as ActionContextConfig, o as StoreErrorBoundaryProps, p as StoreRegistry, r as ActionContextReturn, t as createActionContext } from "./ActionContext.cjs"; | ||
| import { Patches, Patches as Patches$1, TimeTravelControls, TravelPatches } from "@context-action/mutative"; | ||
| import React$1, { ReactNode } from "react"; | ||
| import { ActionHandler, ActionHandler as ActionHandler$1, ActionPayloadMap, ActionRegister, ActionRegister as ActionRegister$1, ActionRegisterConfig, ActionSchemaMap, ActionSchemaMap as ActionSchemaMap$1, ActionValidationError, AnthropicToolDefinition, AnthropicToolDefinition as AnthropicToolDefinition$1, DefineActionOptions, DispatchOptions, ExecutionMode, ExecutionResult, HandlerConfig, HandlerConfig as HandlerConfig$1, InferActionPayloadMap, InferActionPayloadMap as InferActionPayloadMap$1, JSONSchema, JSONSchemaType, MCPToolDefinition, MCPToolDefinition as MCPToolDefinition$1, OpenAIToolDefinition, OpenAIToolDefinition as OpenAIToolDefinition$1, PipelineController, SafeParseResult, UnifiedAction, UnregisterFunction, createActionFactory, createActionSchema, defineAction, isActionValidationError, zodToJsonSchema } from "@context-action/core"; | ||
| import * as react_jsx_runtime0 from "react/jsx-runtime"; | ||
| //#region src/stores/core/TimeTravelStore.d.ts | ||
| type PatchAwareListener$1 = (patches: Patches$1 | null) => void; | ||
| interface TimeTravelStoreOptions<T> { | ||
| maxHistory?: number; | ||
| mutable?: boolean; | ||
| isEqual?: (a: T, b: T) => boolean; | ||
| notificationMode?: 'batched' | 'immediate'; | ||
| } | ||
| declare class TimeTravelStore<T = unknown> implements IStore<T> { | ||
| readonly name: string; | ||
| private timeTravel; | ||
| private listeners; | ||
| private patchAwareListeners; | ||
| private _snapshot; | ||
| private _lastPatches; | ||
| private isDisposed; | ||
| private cleanupTasks; | ||
| private customComparator?; | ||
| private cloningEnabled; | ||
| private notificationMode; | ||
| private pendingNotification; | ||
| private animationFrameId; | ||
| constructor(name: string, initialValue: T, options?: TimeTravelStoreOptions<T>); | ||
| subscribe: (listener: Listener) => Unsubscribe; | ||
| subscribeWithPatches: (listener: PatchAwareListener$1) => Unsubscribe; | ||
| getLastPatches(): Patches$1 | null; | ||
| getSnapshot: () => Snapshot<T>; | ||
| getValue(): T; | ||
| setValue(value: T, options?: StoreSetValueOptions<T>): void; | ||
| update(updater: (current: T) => T | void): void; | ||
| getListenerCount(): number; | ||
| clearListeners(): void; | ||
| dispose(): void; | ||
| registerCleanup(task: () => void): () => void; | ||
| isStoreDisposed(): boolean; | ||
| undo(steps?: number): void; | ||
| redo(steps?: number): void; | ||
| canUndo(): boolean; | ||
| canRedo(): boolean; | ||
| goTo(position: number): void; | ||
| reset(): void; | ||
| getHistory(): readonly T[]; | ||
| getPosition(): number; | ||
| getTimeTravelControls(): TimeTravelControls<T, false>; | ||
| notifyPath(path: (string | number)[]): void; | ||
| notifyPaths(paths: (string | number)[][]): void; | ||
| private _getValueAtPath; | ||
| setCloningEnabled(enabled: boolean): void; | ||
| isCloningEnabled(): boolean; | ||
| setCustomComparator(comparator: (a: T, b: T) => boolean): void; | ||
| private _createSnapshot; | ||
| private _updateSnapshot; | ||
| private _scheduleNotification; | ||
| private _executeNotification; | ||
| private _areEqual; | ||
| } | ||
| declare function createTimeTravelStore<T>(name: string, initialValue: T, options?: TimeTravelStoreOptions<T>): TimeTravelStore<T>; | ||
| declare function isTimeTravelStore<T>(store: IStore<T>): store is TimeTravelStore<T>; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreValue.d.ts | ||
| interface StoreValueOptions<R> { | ||
| equalityFn?: (a: R, b: R) => boolean; | ||
| interface StoreValueOptions<R$1> { | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| condition?: () => boolean; | ||
| debounce?: number; | ||
| throttle?: number; | ||
| initialValue?: R; | ||
| initialValue?: R$1; | ||
| debug?: boolean; | ||
| name?: string; | ||
| } | ||
| declare function useStoreValue<T>(store: Store<T>, options?: StoreValueOptions<T>): T; | ||
| declare function useStoreValue<T>(store: Store<T> | undefined | null, options?: StoreValueOptions<T>): T | undefined; | ||
| declare function useStoreValue<T, R>(store: Store<T>, selector: (value: T) => R, options?: StoreValueOptions<R>): R; | ||
| declare function useStoreValue<T, R>(store: Store<T> | undefined | null, selector: (value: T) => R, options?: StoreValueOptions<R>): R | undefined; | ||
| declare function useStoreValue<T>(store: IStore<T>, options?: StoreValueOptions<T>): T; | ||
| declare function useStoreValue<T>(store: IStore<T> | undefined | null, options?: StoreValueOptions<T>): T | undefined; | ||
| declare function useStoreValue<T, R$1>(store: IStore<T>, selector: (value: T) => R$1, options?: StoreValueOptions<R$1>): R$1; | ||
| declare function useStoreValue<T, R$1>(store: IStore<T> | undefined | null, selector: (value: T) => R$1, options?: StoreValueOptions<R$1>): R$1 | undefined; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreSelector.d.ts | ||
| declare function useStoreSelector<T, R>(store: Store<T>, selector: (value: T) => R, equalityFn?: (a: R, b: R) => boolean): R; | ||
| declare function useStoreSelector<T, R$1>(store: Store<T>, selector: (value: T) => R$1, equalityFn?: (a: R$1, b: R$1) => boolean): R$1; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStorePath.d.ts | ||
| interface PatchAwareStore<T> { | ||
| getValue(): T; | ||
| subscribe(listener: () => void): Unsubscribe; | ||
| subscribeWithPatches(listener: (patches: Patches$1 | null) => void): Unsubscribe; | ||
| } | ||
| type StorePath = (string | number)[]; | ||
| interface UseStorePathOptions<R$1> { | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useStorePath<T, R$1 = unknown>(store: PatchAwareStore<T>, path: StorePath, options?: UseStorePathOptions<R$1>): R$1; | ||
| interface UseStoreSelectorWithPathsOptions<R$1> { | ||
| dependsOn?: StorePath[]; | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useStoreSelectorWithPaths<T, R$1>(store: PatchAwareStore<T>, selector: (value: T) => R$1, options?: UseStoreSelectorWithPathsOptions<R$1>): R$1; | ||
| //#endregion | ||
| //#region src/stores/hooks/useTimeTravelControls.d.ts | ||
| interface TimeTravelState { | ||
| canUndo: boolean; | ||
| canRedo: boolean; | ||
| position: number; | ||
| historyLength: number; | ||
| } | ||
| interface TimeTravelControlsState$1 extends TimeTravelState { | ||
| undo: (steps?: number) => void; | ||
| redo: (steps?: number) => void; | ||
| goTo: (position: number) => void; | ||
| reset: () => void; | ||
| } | ||
| declare function useTimeTravelControls<T>(store: TimeTravelStore<T>): TimeTravelControlsState$1; | ||
| //#endregion | ||
| //#region src/stores/hooks/useTimeTravelPath.d.ts | ||
| type StorePath$1 = (string | number)[]; | ||
| interface UseTimeTravelPathOptions<R$1> { | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useTimeTravelPath<T, R$1 = unknown>(store: TimeTravelStore<T>, path: StorePath$1, options?: UseTimeTravelPathOptions<R$1>): R$1; | ||
| interface UseTimeTravelSelectorOptions<R$1> { | ||
| dependsOn?: StorePath$1[]; | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useTimeTravelSelector<T, R$1>(store: TimeTravelStore<T>, selector: (value: T) => R$1, options?: UseTimeTravelSelectorOptions<R$1>): R$1; | ||
| //#endregion | ||
| //#region src/stores/patterns/declarative-store-pattern-v2.d.ts | ||
@@ -44,3 +148,3 @@ interface StoreConfig<T = any> { | ||
| constructor(name: string, initialStores: InitialStores<T>); | ||
| getStore<K extends keyof T>(storeName: K): Store<T[K]>; | ||
| getStore<K$1 extends keyof T>(storeName: K$1): Store<T[K$1]>; | ||
| clear(): void; | ||
@@ -63,3 +167,3 @@ getInfo(): { | ||
| }) => react_jsx_runtime0.JSX.Element; | ||
| readonly useStore: <K extends keyof T>(storeName: K) => Store<T[K]>; | ||
| readonly useStore: <K$1 extends keyof T>(storeName: K$1) => Store<T[K$1]>; | ||
| readonly useStoreManager: () => StoreManager<T>; | ||
@@ -72,3 +176,3 @@ readonly useStoreInfo: () => { | ||
| readonly useStoreClear: () => () => void; | ||
| readonly withProvider: <P extends {}>(Component: React.ComponentType<P>, config?: WithProviderConfig) => React.FC<P>; | ||
| readonly withProvider: <P extends {}>(Component: React$1.ComponentType<P>, config?: WithProviderConfig) => React$1.FC<P>; | ||
| readonly contextName: string; | ||
@@ -84,2 +188,76 @@ readonly initialStores: InitialStores<T>; | ||
| //#endregion | ||
| //#region src/stores/patterns/time-travel-store-pattern.d.ts | ||
| interface TimeTravelStoreConfig<T = any> { | ||
| initialValue: T; | ||
| timeTravel?: boolean; | ||
| maxHistory?: number; | ||
| mutable?: boolean; | ||
| strategy?: 'reference' | 'shallow' | 'deep'; | ||
| description?: string; | ||
| debug?: boolean; | ||
| tags?: string[]; | ||
| version?: string; | ||
| comparisonOptions?: Partial<ComparisonOptions<T>>; | ||
| } | ||
| type TimeTravelInitialStores<T extends Record<string, any>> = { [K in keyof T]: TimeTravelStoreConfig<T[K]> | T[K] }; | ||
| interface TimeTravelControlsState { | ||
| canUndo: boolean; | ||
| canRedo: boolean; | ||
| position: number; | ||
| historyLength: number; | ||
| undo: (steps?: number) => void; | ||
| redo: (steps?: number) => void; | ||
| goTo: (position: number) => void; | ||
| reset: () => void; | ||
| } | ||
| type InferTimeTravelStoreTypes<T extends Record<string, any>> = { readonly [K in keyof T]: T[K] extends TimeTravelStoreConfig<infer V> ? V : T[K] extends ((...args: unknown[]) => unknown) ? never : T[K] }; | ||
| declare class TimeTravelStoreManager<T extends Record<string, any>> { | ||
| readonly name: string; | ||
| private readonly defaultMaxHistory; | ||
| readonly registry: StoreRegistry; | ||
| readonly initialStores: TimeTravelInitialStores<T>; | ||
| readonly stores: Map<keyof T, Store<any> | TimeTravelStore<any>>; | ||
| constructor(name: string, initialStores: TimeTravelInitialStores<T>, defaultMaxHistory?: number); | ||
| getStore<K$1 extends keyof T>(storeName: K$1): Store<T[K$1]> | TimeTravelStore<T[K$1]>; | ||
| hasTimeTravel<K$1 extends keyof T>(storeName: K$1): boolean; | ||
| clear(): void; | ||
| getInfo(): { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| } | ||
| declare function createTimeTravelStoreContext<T extends Record<string, any>>(contextName: string, initialStores: TimeTravelInitialStores<T>, options?: { | ||
| defaultMaxHistory?: number; | ||
| }): { | ||
| readonly Provider: ({ | ||
| children, | ||
| registryId | ||
| }: { | ||
| children: ReactNode; | ||
| registryId?: string; | ||
| }) => react_jsx_runtime0.JSX.Element; | ||
| readonly useStore: <K$1 extends keyof T>(storeName: K$1) => Store<T[K$1]> | TimeTravelStore<T[K$1]>; | ||
| readonly useTimeTravelStore: <K$1 extends keyof T>(storeName: K$1) => TimeTravelStore<T[K$1]>; | ||
| readonly useStorePath: <K$1 extends keyof T, R$1 = unknown>(storeName: K$1, path: StorePath$1) => R$1; | ||
| readonly useStoreSelector: <K$1 extends keyof T, R$1>(storeName: K$1, selector: (value: T[K$1]) => R$1, options?: { | ||
| dependsOn?: StorePath$1[]; | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| }) => R$1; | ||
| readonly useTimeTravelControls: <K$1 extends keyof T>(storeName: K$1) => TimeTravelControlsState; | ||
| readonly useStoreManager: () => TimeTravelStoreManager<T>; | ||
| readonly useStoreInfo: () => { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| readonly useStoreClear: () => () => void; | ||
| readonly withProvider: <P extends {}>(Component: React$1.ComponentType<P>, config?: { | ||
| displayName?: string; | ||
| registryId?: string; | ||
| }) => React$1.FC<P>; | ||
| readonly contextName: string; | ||
| readonly initialStores: TimeTravelInitialStores<T>; | ||
| }; | ||
| //#endregion | ||
| //#region src/refs/types.d.ts | ||
@@ -102,3 +280,3 @@ type RefTarget = any; | ||
| } | ||
| type RefOperation<T extends RefTarget, R = any> = (target: T, options?: RefOperationOptions) => R | Promise<R>; | ||
| type RefOperation<T extends RefTarget, R$1 = any> = (target: T, options?: RefOperationOptions) => R$1 | Promise<R$1>; | ||
| interface RefInitConfig<T extends RefTarget = RefTarget> { | ||
@@ -126,35 +304,35 @@ name: string; | ||
| interface RefContextReturn<T> { | ||
| Provider: React.FC<{ | ||
| Provider: React$1.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useRefHandler: <K extends keyof T>(refName: K) => { | ||
| setRef: (target: T[K] | null) => void; | ||
| target: T[K] | null; | ||
| waitForMount: () => Promise<T[K]>; | ||
| withTarget: <Result>(operation: RefOperation<T[K] & RefTarget, Result>, options?: RefOperationOptions) => Promise<RefOperationResult<Result>>; | ||
| useRefHandler: <K$1 extends keyof T>(refName: K$1) => { | ||
| setRef: (target: T[K$1] | null) => void; | ||
| target: T[K$1] | null; | ||
| waitForMount: () => Promise<T[K$1]>; | ||
| withTarget: <Result>(operation: RefOperation<T[K$1] & RefTarget, Result>, options?: RefOperationOptions) => Promise<RefOperationResult<Result>>; | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| onMount: (callback: (target: T[K]) => void) => () => void; | ||
| executeIfMounted: <Result>(operation: (target: T[K] & RefTarget) => Result) => Result | null; | ||
| onMount: (callback: (target: T[K$1]) => void) => () => void; | ||
| executeIfMounted: <Result>(operation: (target: T[K$1] & RefTarget) => Result) => Result | null; | ||
| }; | ||
| useWaitForRefs: () => { | ||
| <K extends keyof T>(...refNames: K[]): Promise<Pick<T, K>>; | ||
| <K extends keyof T>(timeout: number, ...refNames: K[]): Promise<Pick<T, K>>; | ||
| <K$1 extends keyof T>(...refNames: K$1[]): Promise<Pick<T, K$1>>; | ||
| <K$1 extends keyof T>(timeout: number, ...refNames: K$1[]): Promise<Pick<T, K$1>>; | ||
| }; | ||
| useGetAllRefs: () => () => Partial<T>; | ||
| useRefPolling: () => <K extends keyof T>(refName: K, options?: RefPollingOptions) => { | ||
| promise: Promise<T[K]>; | ||
| useRefPolling: () => <K$1 extends keyof T>(refName: K$1, options?: RefPollingOptions) => { | ||
| promise: Promise<T[K$1]>; | ||
| cancel: () => void; | ||
| isMounted: () => boolean; | ||
| }; | ||
| useRefMountState: <K extends keyof T>(refName: K) => { | ||
| useRefMountState: <K$1 extends keyof T>(refName: K$1) => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| mountedTarget: T[K] | null; | ||
| mountedTarget: T[K$1] | null; | ||
| }; | ||
| useOnMountStateChange: <K extends keyof T>(refName: K, callback: (mounted: boolean, target: T[K] | null) => void) => void; | ||
| useRefMountChecker: <K extends keyof T>(refName: K) => () => { | ||
| useOnMountStateChange: <K$1 extends keyof T>(refName: K$1, callback: (mounted: boolean, target: T[K$1] | null) => void) => void; | ||
| useRefMountChecker: <K$1 extends keyof T>(refName: K$1) => () => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| target: T[K] | null; | ||
| target: T[K$1] | null; | ||
| }; | ||
@@ -171,3 +349,53 @@ contextName: string; | ||
| //#endregion | ||
| export { type ActionContextConfig, type ActionContextReturn, type ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, type ActionRegisterConfig, type CreateRefContextOptions, type ExecutionMode, type HandlerConfig, type IStore, type InitialStores, type PipelineController, type RefContextReturn, type RefOperationOptions, type RefOperationResult, type RefTarget, type Snapshot, Store, type StoreConfig, StoreErrorBoundary, type StoreErrorBoundaryProps, StoreManager, type UnregisterFunction, type WithProviderConfig, createActionContext, createRefContext, createStore, createStoreContext, useStoreSelector, useStoreValue }; | ||
| //#region src/tools/ToolContext.types.d.ts | ||
| type ToolValidationMode = 'strict' | 'warn' | 'silent'; | ||
| interface ToolContextConfig<TSchema extends ActionSchemaMap$1> { | ||
| schema: TSchema; | ||
| validationMode?: ToolValidationMode; | ||
| validateOnDispatch?: boolean; | ||
| debug?: boolean; | ||
| } | ||
| interface ToolRegistry<TSchema extends ActionSchemaMap$1> { | ||
| readonly tools: TSchema; | ||
| getTool<K$1 extends keyof TSchema>(name: K$1): TSchema[K$1]; | ||
| hasTool(name: string): boolean; | ||
| getToolNames(): (keyof TSchema)[]; | ||
| toMCP(): MCPToolDefinition$1[]; | ||
| toOpenAI(): OpenAIToolDefinition$1[]; | ||
| toAnthropic(): AnthropicToolDefinition$1[]; | ||
| toMCPFiltered<K$1 extends keyof TSchema>(toolNames: K$1[]): MCPToolDefinition$1[]; | ||
| toOpenAIFiltered<K$1 extends keyof TSchema>(toolNames: K$1[]): OpenAIToolDefinition$1[]; | ||
| toAnthropicFiltered<K$1 extends keyof TSchema>(toolNames: K$1[]): AnthropicToolDefinition$1[]; | ||
| } | ||
| interface ToolExecutionResult<R$1 = void> extends ExecutionResult<R$1> { | ||
| validationPassed: boolean; | ||
| validationErrors?: string[]; | ||
| } | ||
| interface ToolContextType<TSchema extends ActionSchemaMap$1> { | ||
| actionRegisterRef: React.RefObject<ActionRegister$1<InferActionPayloadMap$1<TSchema>> | null>; | ||
| registry: ToolRegistry<TSchema>; | ||
| dispatch: ToolDispatchFunction<InferActionPayloadMap$1<TSchema>>; | ||
| } | ||
| type ToolDispatchFunction<TPayloadMap> = <K$1 extends keyof TPayloadMap>(toolName: K$1, payload: TPayloadMap[K$1], options?: DispatchOptions) => Promise<void>; | ||
| interface ToolDispatchWithResultReturn<TPayloadMap> { | ||
| dispatch: ToolDispatchFunction<TPayloadMap>; | ||
| dispatchWithResult: <K$1 extends keyof TPayloadMap, R$1 = void>(toolName: K$1, payload: TPayloadMap[K$1], options?: DispatchOptions) => Promise<ToolExecutionResult<R$1>>; | ||
| abortAll: () => void; | ||
| } | ||
| interface ToolContextReturn<TSchema extends ActionSchemaMap$1> { | ||
| Provider: React.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useToolDispatch: () => ToolDispatchFunction<InferActionPayloadMap$1<TSchema>>; | ||
| useToolHandler: <K$1 extends keyof TSchema>(toolName: K$1, handler: ActionHandler$1<InferActionPayloadMap$1<TSchema>[K$1]>, config?: HandlerConfig$1) => void; | ||
| useToolRegistry: () => ToolRegistry<TSchema>; | ||
| useToolDispatchWithResult: () => ToolDispatchWithResultReturn<InferActionPayloadMap$1<TSchema>>; | ||
| useActionRegister: () => ActionRegister$1<InferActionPayloadMap$1<TSchema>> | null; | ||
| context: React.Context<ToolContextType<TSchema> | null>; | ||
| } | ||
| //#endregion | ||
| //#region src/tools/ToolContext.d.ts | ||
| declare function createToolContext<TSchema extends ActionSchemaMap$1>(contextName: string, config: ToolContextConfig<TSchema>): ToolContextReturn<TSchema>; | ||
| //#endregion | ||
| export { type ActionContextConfig, type ActionContextReturn, type ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, type ActionRegisterConfig, type ActionSchemaMap, ActionValidationError, type AnthropicToolDefinition, type CreateRefContextOptions, type DefineActionOptions, type ExecutionMode, type HandlerConfig, type IStore, type InferActionPayloadMap, type InferTimeTravelStoreTypes, type InitialStores, type JSONSchema, type JSONSchemaType, type MCPToolDefinition, type OpenAIToolDefinition, type PatchAwareListener, type Patches, type PipelineController, type RefContextReturn, type RefOperationOptions, type RefOperationResult, type RefTarget, type SafeParseResult, type Snapshot, Store, type StoreConfig, StoreErrorBoundary, type StoreErrorBoundaryProps, StoreManager, type StorePath, type TimeTravelControlsState as TimeTravelContextControlsState, type TimeTravelControlsState$1 as TimeTravelControlsState, type TimeTravelInitialStores, TimeTravelStore, type TimeTravelStoreConfig, TimeTravelStoreManager, type TimeTravelStoreOptions, type ToolContextConfig, type ToolContextReturn, type ToolContextType, type ToolDispatchFunction, type ToolDispatchWithResultReturn, type ToolExecutionResult, type ToolRegistry, type ToolValidationMode, type TravelPatches, type UnifiedAction, type UnregisterFunction, type UseStorePathOptions, type UseStoreSelectorWithPathsOptions, type UseTimeTravelPathOptions, type UseTimeTravelSelectorOptions, type WithProviderConfig, createActionContext, createActionFactory, createActionSchema, createRefContext, createStore, createStoreContext, createTimeTravelStore, createTimeTravelStoreContext, createToolContext, defineAction, isActionValidationError, isTimeTravelStore, useStorePath, useStoreSelector, useStoreSelectorWithPaths, useStoreValue, useTimeTravelControls, useTimeTravelPath, useTimeTravelSelector, zodToJsonSchema }; | ||
| //# sourceMappingURL=index.d.cts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.cts","names":[],"sources":["../src/stores/hooks/useStoreValue.ts","../src/stores/hooks/useStoreSelector.ts","../src/stores/patterns/declarative-store-pattern-v2.tsx","../src/refs/types.ts","../src/refs/hooks/useRefPolling.ts","../src/refs/createRefContext.ts"],"sourcesContent":[],"mappings":"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"} | ||
| {"version":3,"file":"index.d.cts","names":[],"sources":["../src/stores/core/TimeTravelStore.ts","../src/stores/hooks/useStoreValue.ts","../src/stores/hooks/useStoreSelector.ts","../src/stores/hooks/useStorePath.ts","../src/stores/hooks/useTimeTravelControls.ts","../src/stores/hooks/useTimeTravelPath.ts","../src/stores/patterns/declarative-store-pattern-v2.tsx","../src/stores/patterns/time-travel-store-pattern.tsx","../src/refs/types.ts","../src/refs/hooks/useRefPolling.ts","../src/refs/createRefContext.ts","../src/tools/ToolContext.types.ts","../src/tools/ToolContext.tsx"],"sourcesContent":[],"mappings":"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"} |
+262
-34
@@ -1,25 +0,129 @@ | ||
| import { ComparisonOptions, IStore, Snapshot, Store, StoreRegistry, createStore } from "./Store-CoQcuZnp.js"; | ||
| import { ActionContextConfig, ActionContextReturn, ActionContextType, StoreErrorBoundary, StoreErrorBoundaryProps, createActionContext } from "./ActionContext-Cq5LNd0Y.js"; | ||
| import React, { ReactNode } from "react"; | ||
| import { _ as StoreSetValueOptions, f as IStore, g as Snapshot, i as ComparisonOptions, m as Listener, n as Store, r as createStore, t as PatchAwareListener, y as Unsubscribe } from "./Store.js"; | ||
| import { a as StoreErrorBoundary, i as ActionContextType, n as ActionContextConfig, o as StoreErrorBoundaryProps, p as StoreRegistry, r as ActionContextReturn, t as createActionContext } from "./ActionContext.js"; | ||
| import React$1, { ReactNode } from "react"; | ||
| import { Patches, Patches as Patches$1, TimeTravelControls, TravelPatches } from "@context-action/mutative"; | ||
| import * as react_jsx_runtime0 from "react/jsx-runtime"; | ||
| import { ActionHandler, ActionPayloadMap, ActionRegister, ActionRegisterConfig, ExecutionMode, HandlerConfig, PipelineController, UnregisterFunction } from "@context-action/core"; | ||
| import { ActionHandler, ActionHandler as ActionHandler$1, ActionPayloadMap, ActionRegister, ActionRegister as ActionRegister$1, ActionRegisterConfig, ActionSchemaMap, ActionSchemaMap as ActionSchemaMap$1, ActionValidationError, AnthropicToolDefinition, AnthropicToolDefinition as AnthropicToolDefinition$1, DefineActionOptions, DispatchOptions, ExecutionMode, ExecutionResult, HandlerConfig, HandlerConfig as HandlerConfig$1, InferActionPayloadMap, InferActionPayloadMap as InferActionPayloadMap$1, JSONSchema, JSONSchemaType, MCPToolDefinition, MCPToolDefinition as MCPToolDefinition$1, OpenAIToolDefinition, OpenAIToolDefinition as OpenAIToolDefinition$1, PipelineController, SafeParseResult, UnifiedAction, UnregisterFunction, createActionFactory, createActionSchema, defineAction, isActionValidationError, zodToJsonSchema } from "@context-action/core"; | ||
| //#region src/stores/core/TimeTravelStore.d.ts | ||
| type PatchAwareListener$1 = (patches: Patches$1 | null) => void; | ||
| interface TimeTravelStoreOptions<T> { | ||
| maxHistory?: number; | ||
| mutable?: boolean; | ||
| isEqual?: (a: T, b: T) => boolean; | ||
| notificationMode?: 'batched' | 'immediate'; | ||
| } | ||
| declare class TimeTravelStore<T = unknown> implements IStore<T> { | ||
| readonly name: string; | ||
| private timeTravel; | ||
| private listeners; | ||
| private patchAwareListeners; | ||
| private _snapshot; | ||
| private _lastPatches; | ||
| private isDisposed; | ||
| private cleanupTasks; | ||
| private customComparator?; | ||
| private cloningEnabled; | ||
| private notificationMode; | ||
| private pendingNotification; | ||
| private animationFrameId; | ||
| constructor(name: string, initialValue: T, options?: TimeTravelStoreOptions<T>); | ||
| subscribe: (listener: Listener) => Unsubscribe; | ||
| subscribeWithPatches: (listener: PatchAwareListener$1) => Unsubscribe; | ||
| getLastPatches(): Patches$1 | null; | ||
| getSnapshot: () => Snapshot<T>; | ||
| getValue(): T; | ||
| setValue(value: T, options?: StoreSetValueOptions<T>): void; | ||
| update(updater: (current: T) => T | void): void; | ||
| getListenerCount(): number; | ||
| clearListeners(): void; | ||
| dispose(): void; | ||
| registerCleanup(task: () => void): () => void; | ||
| isStoreDisposed(): boolean; | ||
| undo(steps?: number): void; | ||
| redo(steps?: number): void; | ||
| canUndo(): boolean; | ||
| canRedo(): boolean; | ||
| goTo(position: number): void; | ||
| reset(): void; | ||
| getHistory(): readonly T[]; | ||
| getPosition(): number; | ||
| getTimeTravelControls(): TimeTravelControls<T, false>; | ||
| notifyPath(path: (string | number)[]): void; | ||
| notifyPaths(paths: (string | number)[][]): void; | ||
| private _getValueAtPath; | ||
| setCloningEnabled(enabled: boolean): void; | ||
| isCloningEnabled(): boolean; | ||
| setCustomComparator(comparator: (a: T, b: T) => boolean): void; | ||
| private _createSnapshot; | ||
| private _updateSnapshot; | ||
| private _scheduleNotification; | ||
| private _executeNotification; | ||
| private _areEqual; | ||
| } | ||
| declare function createTimeTravelStore<T>(name: string, initialValue: T, options?: TimeTravelStoreOptions<T>): TimeTravelStore<T>; | ||
| declare function isTimeTravelStore<T>(store: IStore<T>): store is TimeTravelStore<T>; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreValue.d.ts | ||
| interface StoreValueOptions<R> { | ||
| equalityFn?: (a: R, b: R) => boolean; | ||
| interface StoreValueOptions<R$1> { | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| condition?: () => boolean; | ||
| debounce?: number; | ||
| throttle?: number; | ||
| initialValue?: R; | ||
| initialValue?: R$1; | ||
| debug?: boolean; | ||
| name?: string; | ||
| } | ||
| declare function useStoreValue<T>(store: Store<T>, options?: StoreValueOptions<T>): T; | ||
| declare function useStoreValue<T>(store: Store<T> | undefined | null, options?: StoreValueOptions<T>): T | undefined; | ||
| declare function useStoreValue<T, R>(store: Store<T>, selector: (value: T) => R, options?: StoreValueOptions<R>): R; | ||
| declare function useStoreValue<T, R>(store: Store<T> | undefined | null, selector: (value: T) => R, options?: StoreValueOptions<R>): R | undefined; | ||
| declare function useStoreValue<T>(store: IStore<T>, options?: StoreValueOptions<T>): T; | ||
| declare function useStoreValue<T>(store: IStore<T> | undefined | null, options?: StoreValueOptions<T>): T | undefined; | ||
| declare function useStoreValue<T, R$1>(store: IStore<T>, selector: (value: T) => R$1, options?: StoreValueOptions<R$1>): R$1; | ||
| declare function useStoreValue<T, R$1>(store: IStore<T> | undefined | null, selector: (value: T) => R$1, options?: StoreValueOptions<R$1>): R$1 | undefined; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreSelector.d.ts | ||
| declare function useStoreSelector<T, R>(store: Store<T>, selector: (value: T) => R, equalityFn?: (a: R, b: R) => boolean): R; | ||
| declare function useStoreSelector<T, R$1>(store: Store<T>, selector: (value: T) => R$1, equalityFn?: (a: R$1, b: R$1) => boolean): R$1; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStorePath.d.ts | ||
| interface PatchAwareStore<T> { | ||
| getValue(): T; | ||
| subscribe(listener: () => void): Unsubscribe; | ||
| subscribeWithPatches(listener: (patches: Patches$1 | null) => void): Unsubscribe; | ||
| } | ||
| type StorePath = (string | number)[]; | ||
| interface UseStorePathOptions<R$1> { | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useStorePath<T, R$1 = unknown>(store: PatchAwareStore<T>, path: StorePath, options?: UseStorePathOptions<R$1>): R$1; | ||
| interface UseStoreSelectorWithPathsOptions<R$1> { | ||
| dependsOn?: StorePath[]; | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useStoreSelectorWithPaths<T, R$1>(store: PatchAwareStore<T>, selector: (value: T) => R$1, options?: UseStoreSelectorWithPathsOptions<R$1>): R$1; | ||
| //#endregion | ||
| //#region src/stores/hooks/useTimeTravelControls.d.ts | ||
| interface TimeTravelState { | ||
| canUndo: boolean; | ||
| canRedo: boolean; | ||
| position: number; | ||
| historyLength: number; | ||
| } | ||
| interface TimeTravelControlsState$1 extends TimeTravelState { | ||
| undo: (steps?: number) => void; | ||
| redo: (steps?: number) => void; | ||
| goTo: (position: number) => void; | ||
| reset: () => void; | ||
| } | ||
| declare function useTimeTravelControls<T>(store: TimeTravelStore<T>): TimeTravelControlsState$1; | ||
| //#endregion | ||
| //#region src/stores/hooks/useTimeTravelPath.d.ts | ||
| type StorePath$1 = (string | number)[]; | ||
| interface UseTimeTravelPathOptions<R$1> { | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useTimeTravelPath<T, R$1 = unknown>(store: TimeTravelStore<T>, path: StorePath$1, options?: UseTimeTravelPathOptions<R$1>): R$1; | ||
| interface UseTimeTravelSelectorOptions<R$1> { | ||
| dependsOn?: StorePath$1[]; | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| } | ||
| declare function useTimeTravelSelector<T, R$1>(store: TimeTravelStore<T>, selector: (value: T) => R$1, options?: UseTimeTravelSelectorOptions<R$1>): R$1; | ||
| //#endregion | ||
| //#region src/stores/patterns/declarative-store-pattern-v2.d.ts | ||
@@ -44,3 +148,3 @@ interface StoreConfig<T = any> { | ||
| constructor(name: string, initialStores: InitialStores<T>); | ||
| getStore<K extends keyof T>(storeName: K): Store<T[K]>; | ||
| getStore<K$1 extends keyof T>(storeName: K$1): Store<T[K$1]>; | ||
| clear(): void; | ||
@@ -63,3 +167,3 @@ getInfo(): { | ||
| }) => react_jsx_runtime0.JSX.Element; | ||
| readonly useStore: <K extends keyof T>(storeName: K) => Store<T[K]>; | ||
| readonly useStore: <K$1 extends keyof T>(storeName: K$1) => Store<T[K$1]>; | ||
| readonly useStoreManager: () => StoreManager<T>; | ||
@@ -72,3 +176,3 @@ readonly useStoreInfo: () => { | ||
| readonly useStoreClear: () => () => void; | ||
| readonly withProvider: <P extends {}>(Component: React.ComponentType<P>, config?: WithProviderConfig) => React.FC<P>; | ||
| readonly withProvider: <P extends {}>(Component: React$1.ComponentType<P>, config?: WithProviderConfig) => React$1.FC<P>; | ||
| readonly contextName: string; | ||
@@ -84,2 +188,76 @@ readonly initialStores: InitialStores<T>; | ||
| //#endregion | ||
| //#region src/stores/patterns/time-travel-store-pattern.d.ts | ||
| interface TimeTravelStoreConfig<T = any> { | ||
| initialValue: T; | ||
| timeTravel?: boolean; | ||
| maxHistory?: number; | ||
| mutable?: boolean; | ||
| strategy?: 'reference' | 'shallow' | 'deep'; | ||
| description?: string; | ||
| debug?: boolean; | ||
| tags?: string[]; | ||
| version?: string; | ||
| comparisonOptions?: Partial<ComparisonOptions<T>>; | ||
| } | ||
| type TimeTravelInitialStores<T extends Record<string, any>> = { [K in keyof T]: TimeTravelStoreConfig<T[K]> | T[K] }; | ||
| interface TimeTravelControlsState { | ||
| canUndo: boolean; | ||
| canRedo: boolean; | ||
| position: number; | ||
| historyLength: number; | ||
| undo: (steps?: number) => void; | ||
| redo: (steps?: number) => void; | ||
| goTo: (position: number) => void; | ||
| reset: () => void; | ||
| } | ||
| type InferTimeTravelStoreTypes<T extends Record<string, any>> = { readonly [K in keyof T]: T[K] extends TimeTravelStoreConfig<infer V> ? V : T[K] extends ((...args: unknown[]) => unknown) ? never : T[K] }; | ||
| declare class TimeTravelStoreManager<T extends Record<string, any>> { | ||
| readonly name: string; | ||
| private readonly defaultMaxHistory; | ||
| readonly registry: StoreRegistry; | ||
| readonly initialStores: TimeTravelInitialStores<T>; | ||
| readonly stores: Map<keyof T, Store<any> | TimeTravelStore<any>>; | ||
| constructor(name: string, initialStores: TimeTravelInitialStores<T>, defaultMaxHistory?: number); | ||
| getStore<K$1 extends keyof T>(storeName: K$1): Store<T[K$1]> | TimeTravelStore<T[K$1]>; | ||
| hasTimeTravel<K$1 extends keyof T>(storeName: K$1): boolean; | ||
| clear(): void; | ||
| getInfo(): { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| } | ||
| declare function createTimeTravelStoreContext<T extends Record<string, any>>(contextName: string, initialStores: TimeTravelInitialStores<T>, options?: { | ||
| defaultMaxHistory?: number; | ||
| }): { | ||
| readonly Provider: ({ | ||
| children, | ||
| registryId | ||
| }: { | ||
| children: ReactNode; | ||
| registryId?: string; | ||
| }) => react_jsx_runtime0.JSX.Element; | ||
| readonly useStore: <K$1 extends keyof T>(storeName: K$1) => Store<T[K$1]> | TimeTravelStore<T[K$1]>; | ||
| readonly useTimeTravelStore: <K$1 extends keyof T>(storeName: K$1) => TimeTravelStore<T[K$1]>; | ||
| readonly useStorePath: <K$1 extends keyof T, R$1 = unknown>(storeName: K$1, path: StorePath$1) => R$1; | ||
| readonly useStoreSelector: <K$1 extends keyof T, R$1>(storeName: K$1, selector: (value: T[K$1]) => R$1, options?: { | ||
| dependsOn?: StorePath$1[]; | ||
| equalityFn?: (a: R$1, b: R$1) => boolean; | ||
| }) => R$1; | ||
| readonly useTimeTravelControls: <K$1 extends keyof T>(storeName: K$1) => TimeTravelControlsState; | ||
| readonly useStoreManager: () => TimeTravelStoreManager<T>; | ||
| readonly useStoreInfo: () => { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| readonly useStoreClear: () => () => void; | ||
| readonly withProvider: <P extends {}>(Component: React$1.ComponentType<P>, config?: { | ||
| displayName?: string; | ||
| registryId?: string; | ||
| }) => React$1.FC<P>; | ||
| readonly contextName: string; | ||
| readonly initialStores: TimeTravelInitialStores<T>; | ||
| }; | ||
| //#endregion | ||
| //#region src/refs/types.d.ts | ||
@@ -102,3 +280,3 @@ type RefTarget = any; | ||
| } | ||
| type RefOperation<T extends RefTarget, R = any> = (target: T, options?: RefOperationOptions) => R | Promise<R>; | ||
| type RefOperation<T extends RefTarget, R$1 = any> = (target: T, options?: RefOperationOptions) => R$1 | Promise<R$1>; | ||
| interface RefInitConfig<T extends RefTarget = RefTarget> { | ||
@@ -126,35 +304,35 @@ name: string; | ||
| interface RefContextReturn<T> { | ||
| Provider: React.FC<{ | ||
| Provider: React$1.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useRefHandler: <K extends keyof T>(refName: K) => { | ||
| setRef: (target: T[K] | null) => void; | ||
| target: T[K] | null; | ||
| waitForMount: () => Promise<T[K]>; | ||
| withTarget: <Result>(operation: RefOperation<T[K] & RefTarget, Result>, options?: RefOperationOptions) => Promise<RefOperationResult<Result>>; | ||
| useRefHandler: <K$1 extends keyof T>(refName: K$1) => { | ||
| setRef: (target: T[K$1] | null) => void; | ||
| target: T[K$1] | null; | ||
| waitForMount: () => Promise<T[K$1]>; | ||
| withTarget: <Result>(operation: RefOperation<T[K$1] & RefTarget, Result>, options?: RefOperationOptions) => Promise<RefOperationResult<Result>>; | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| onMount: (callback: (target: T[K]) => void) => () => void; | ||
| executeIfMounted: <Result>(operation: (target: T[K] & RefTarget) => Result) => Result | null; | ||
| onMount: (callback: (target: T[K$1]) => void) => () => void; | ||
| executeIfMounted: <Result>(operation: (target: T[K$1] & RefTarget) => Result) => Result | null; | ||
| }; | ||
| useWaitForRefs: () => { | ||
| <K extends keyof T>(...refNames: K[]): Promise<Pick<T, K>>; | ||
| <K extends keyof T>(timeout: number, ...refNames: K[]): Promise<Pick<T, K>>; | ||
| <K$1 extends keyof T>(...refNames: K$1[]): Promise<Pick<T, K$1>>; | ||
| <K$1 extends keyof T>(timeout: number, ...refNames: K$1[]): Promise<Pick<T, K$1>>; | ||
| }; | ||
| useGetAllRefs: () => () => Partial<T>; | ||
| useRefPolling: () => <K extends keyof T>(refName: K, options?: RefPollingOptions) => { | ||
| promise: Promise<T[K]>; | ||
| useRefPolling: () => <K$1 extends keyof T>(refName: K$1, options?: RefPollingOptions) => { | ||
| promise: Promise<T[K$1]>; | ||
| cancel: () => void; | ||
| isMounted: () => boolean; | ||
| }; | ||
| useRefMountState: <K extends keyof T>(refName: K) => { | ||
| useRefMountState: <K$1 extends keyof T>(refName: K$1) => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| mountedTarget: T[K] | null; | ||
| mountedTarget: T[K$1] | null; | ||
| }; | ||
| useOnMountStateChange: <K extends keyof T>(refName: K, callback: (mounted: boolean, target: T[K] | null) => void) => void; | ||
| useRefMountChecker: <K extends keyof T>(refName: K) => () => { | ||
| useOnMountStateChange: <K$1 extends keyof T>(refName: K$1, callback: (mounted: boolean, target: T[K$1] | null) => void) => void; | ||
| useRefMountChecker: <K$1 extends keyof T>(refName: K$1) => () => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| target: T[K] | null; | ||
| target: T[K$1] | null; | ||
| }; | ||
@@ -171,3 +349,53 @@ contextName: string; | ||
| //#endregion | ||
| export { type ActionContextConfig, type ActionContextReturn, type ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, type ActionRegisterConfig, type CreateRefContextOptions, type ExecutionMode, type HandlerConfig, type IStore, type InitialStores, type PipelineController, type RefContextReturn, type RefOperationOptions, type RefOperationResult, type RefTarget, type Snapshot, Store, type StoreConfig, StoreErrorBoundary, type StoreErrorBoundaryProps, StoreManager, type UnregisterFunction, type WithProviderConfig, createActionContext, createRefContext, createStore, createStoreContext, useStoreSelector, useStoreValue }; | ||
| //#region src/tools/ToolContext.types.d.ts | ||
| type ToolValidationMode = 'strict' | 'warn' | 'silent'; | ||
| interface ToolContextConfig<TSchema extends ActionSchemaMap$1> { | ||
| schema: TSchema; | ||
| validationMode?: ToolValidationMode; | ||
| validateOnDispatch?: boolean; | ||
| debug?: boolean; | ||
| } | ||
| interface ToolRegistry<TSchema extends ActionSchemaMap$1> { | ||
| readonly tools: TSchema; | ||
| getTool<K$1 extends keyof TSchema>(name: K$1): TSchema[K$1]; | ||
| hasTool(name: string): boolean; | ||
| getToolNames(): (keyof TSchema)[]; | ||
| toMCP(): MCPToolDefinition$1[]; | ||
| toOpenAI(): OpenAIToolDefinition$1[]; | ||
| toAnthropic(): AnthropicToolDefinition$1[]; | ||
| toMCPFiltered<K$1 extends keyof TSchema>(toolNames: K$1[]): MCPToolDefinition$1[]; | ||
| toOpenAIFiltered<K$1 extends keyof TSchema>(toolNames: K$1[]): OpenAIToolDefinition$1[]; | ||
| toAnthropicFiltered<K$1 extends keyof TSchema>(toolNames: K$1[]): AnthropicToolDefinition$1[]; | ||
| } | ||
| interface ToolExecutionResult<R$1 = void> extends ExecutionResult<R$1> { | ||
| validationPassed: boolean; | ||
| validationErrors?: string[]; | ||
| } | ||
| interface ToolContextType<TSchema extends ActionSchemaMap$1> { | ||
| actionRegisterRef: React.RefObject<ActionRegister$1<InferActionPayloadMap$1<TSchema>> | null>; | ||
| registry: ToolRegistry<TSchema>; | ||
| dispatch: ToolDispatchFunction<InferActionPayloadMap$1<TSchema>>; | ||
| } | ||
| type ToolDispatchFunction<TPayloadMap> = <K$1 extends keyof TPayloadMap>(toolName: K$1, payload: TPayloadMap[K$1], options?: DispatchOptions) => Promise<void>; | ||
| interface ToolDispatchWithResultReturn<TPayloadMap> { | ||
| dispatch: ToolDispatchFunction<TPayloadMap>; | ||
| dispatchWithResult: <K$1 extends keyof TPayloadMap, R$1 = void>(toolName: K$1, payload: TPayloadMap[K$1], options?: DispatchOptions) => Promise<ToolExecutionResult<R$1>>; | ||
| abortAll: () => void; | ||
| } | ||
| interface ToolContextReturn<TSchema extends ActionSchemaMap$1> { | ||
| Provider: React.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useToolDispatch: () => ToolDispatchFunction<InferActionPayloadMap$1<TSchema>>; | ||
| useToolHandler: <K$1 extends keyof TSchema>(toolName: K$1, handler: ActionHandler$1<InferActionPayloadMap$1<TSchema>[K$1]>, config?: HandlerConfig$1) => void; | ||
| useToolRegistry: () => ToolRegistry<TSchema>; | ||
| useToolDispatchWithResult: () => ToolDispatchWithResultReturn<InferActionPayloadMap$1<TSchema>>; | ||
| useActionRegister: () => ActionRegister$1<InferActionPayloadMap$1<TSchema>> | null; | ||
| context: React.Context<ToolContextType<TSchema> | null>; | ||
| } | ||
| //#endregion | ||
| //#region src/tools/ToolContext.d.ts | ||
| declare function createToolContext<TSchema extends ActionSchemaMap$1>(contextName: string, config: ToolContextConfig<TSchema>): ToolContextReturn<TSchema>; | ||
| //#endregion | ||
| export { type ActionContextConfig, type ActionContextReturn, type ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, type ActionRegisterConfig, type ActionSchemaMap, ActionValidationError, type AnthropicToolDefinition, type CreateRefContextOptions, type DefineActionOptions, type ExecutionMode, type HandlerConfig, type IStore, type InferActionPayloadMap, type InferTimeTravelStoreTypes, type InitialStores, type JSONSchema, type JSONSchemaType, type MCPToolDefinition, type OpenAIToolDefinition, type PatchAwareListener, type Patches, type PipelineController, type RefContextReturn, type RefOperationOptions, type RefOperationResult, type RefTarget, type SafeParseResult, type Snapshot, Store, type StoreConfig, StoreErrorBoundary, type StoreErrorBoundaryProps, StoreManager, type StorePath, type TimeTravelControlsState as TimeTravelContextControlsState, type TimeTravelControlsState$1 as TimeTravelControlsState, type TimeTravelInitialStores, TimeTravelStore, type TimeTravelStoreConfig, TimeTravelStoreManager, type TimeTravelStoreOptions, type ToolContextConfig, type ToolContextReturn, type ToolContextType, type ToolDispatchFunction, type ToolDispatchWithResultReturn, type ToolExecutionResult, type ToolRegistry, type ToolValidationMode, type TravelPatches, type UnifiedAction, type UnregisterFunction, type UseStorePathOptions, type UseStoreSelectorWithPathsOptions, type UseTimeTravelPathOptions, type UseTimeTravelSelectorOptions, type WithProviderConfig, createActionContext, createActionFactory, createActionSchema, createRefContext, createStore, createStoreContext, createTimeTravelStore, createTimeTravelStoreContext, createToolContext, defineAction, isActionValidationError, isTimeTravelStore, useStorePath, useStoreSelector, useStoreSelectorWithPaths, useStoreValue, useTimeTravelControls, useTimeTravelPath, useTimeTravelSelector, zodToJsonSchema }; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","names":[],"sources":["../src/stores/hooks/useStoreValue.ts","../src/stores/hooks/useStoreSelector.ts","../src/stores/patterns/declarative-store-pattern-v2.tsx","../src/refs/types.ts","../src/refs/hooks/useRefPolling.ts","../src/refs/createRefContext.ts"],"sourcesContent":[],"mappings":"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"} | ||
| {"version":3,"file":"index.d.ts","names":[],"sources":["../src/stores/core/TimeTravelStore.ts","../src/stores/hooks/useStoreValue.ts","../src/stores/hooks/useStoreSelector.ts","../src/stores/hooks/useStorePath.ts","../src/stores/hooks/useTimeTravelControls.ts","../src/stores/hooks/useTimeTravelPath.ts","../src/stores/patterns/declarative-store-pattern-v2.tsx","../src/stores/patterns/time-travel-store-pattern.tsx","../src/refs/types.ts","../src/refs/hooks/useRefPolling.ts","../src/refs/createRefContext.ts","../src/tools/ToolContext.types.ts","../src/tools/ToolContext.tsx"],"sourcesContent":[],"mappings":"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"} |
+36
-21
@@ -1,23 +0,38 @@ | ||
| const require_error_handling = require('./error-handling-ibCwx4ki.cjs'); | ||
| const require_utils = require('./utils-ZdkTBqFK.cjs'); | ||
| const require_comparison = require('./comparison.cjs'); | ||
| const require_utils = require('./utils2.cjs'); | ||
| let _context_action_mutative = require("@context-action/mutative"); | ||
| exports.ImmerUtils = require_error_handling.ImmerUtils; | ||
| exports.SubscriptionManager = require_utils.SubscriptionManager; | ||
| exports.TypeUtils = require_utils.TypeUtils; | ||
| exports.compareValues = require_error_handling.compareValues; | ||
| Object.defineProperty(exports, 'MutativeUtils', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.MutativeUtils; | ||
| } | ||
| }); | ||
| exports.compareValues = require_comparison.compareValues; | ||
| exports.composeProviders = require_utils.composeProviders; | ||
| exports.createSafeEqualityFn = require_utils.createSafeEqualityFn; | ||
| exports.createStoreConfig = require_utils.createStoreConfig; | ||
| exports.deepClone = require_error_handling.deepClone; | ||
| exports.deepCloneWithImmer = require_error_handling.deepCloneWithImmer; | ||
| exports.extractStoreValue = require_utils.extractStoreValue; | ||
| exports.extractStoreValues = require_utils.extractStoreValues; | ||
| exports.getGlobalComparisonOptions = require_error_handling.getGlobalComparisonOptions; | ||
| exports.isStore = require_utils.isStore; | ||
| exports.isValidStoreValue = require_utils.isValidStoreValue; | ||
| exports.preloadImmer = require_error_handling.preloadImmer; | ||
| exports.produce = require_error_handling.produce; | ||
| exports.safeGet = require_error_handling.safeGet; | ||
| exports.safeSet = require_error_handling.safeSet; | ||
| exports.setGlobalComparisonOptions = require_error_handling.setGlobalComparisonOptions; | ||
| exports.useSubscriptionManager = require_utils.useSubscriptionManager; | ||
| Object.defineProperty(exports, 'deepClone', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.deepClone; | ||
| } | ||
| }); | ||
| exports.getGlobalComparisonOptions = require_comparison.getGlobalComparisonOptions; | ||
| Object.defineProperty(exports, 'produce', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.produce; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'safeGet', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.safeGet; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'safeSet', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return _context_action_mutative.safeSet; | ||
| } | ||
| }); | ||
| exports.setGlobalComparisonOptions = require_comparison.setGlobalComparisonOptions; |
+3
-3
@@ -1,3 +0,3 @@ | ||
| import { ComparisonOptions, ComparisonStrategy, CustomComparator, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store--dj9U0mo.cjs"; | ||
| import { DeepReadonly, EqualityFunction, ImmerUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, useSubscriptionManager } from "./utils-Cq-l1Kd1.cjs"; | ||
| export { ComparisonOptions, ComparisonStrategy, CustomComparator, DeepReadonly, EqualityFunction, ImmerUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, compareValues, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useSubscriptionManager }; | ||
| import { a as ComparisonStrategy, c as getGlobalComparisonOptions, i as ComparisonOptions, l as setGlobalComparisonOptions, o as CustomComparator, s as compareValues } from "./Store.cjs"; | ||
| import { _ as StoreValue, a as safeSet, c as DeepReadonly, d as RequiredBy, f as StoreInitConfig, g as StoreUpdater, h as StoreSelector, i as safeGet, l as EqualityFunction, m as StoreRecordValues, n as deepClone, o as ProviderComponent, p as StoreListener, r as produce, s as composeProviders, t as MutativeUtils, u as PartialBy, v as StoresValues } from "./utils2.cjs"; | ||
| export { ComparisonOptions, ComparisonStrategy, CustomComparator, DeepReadonly, EqualityFunction, MutativeUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, compareValues, composeProviders, deepClone, getGlobalComparisonOptions, produce, safeGet, safeSet, setGlobalComparisonOptions }; |
+3
-3
@@ -1,3 +0,3 @@ | ||
| import { ComparisonOptions, ComparisonStrategy, CustomComparator, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store-CoQcuZnp.js"; | ||
| import { DeepReadonly, EqualityFunction, ImmerUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, useSubscriptionManager } from "./utils-DGg-aIzZ.js"; | ||
| export { ComparisonOptions, ComparisonStrategy, CustomComparator, DeepReadonly, EqualityFunction, ImmerUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, SubscriptionEntry, SubscriptionManager, SubscriptionStats, TypeUtils, compareValues, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useSubscriptionManager }; | ||
| import { a as ComparisonStrategy, c as getGlobalComparisonOptions, i as ComparisonOptions, l as setGlobalComparisonOptions, o as CustomComparator, s as compareValues } from "./Store.js"; | ||
| import { _ as StoreValue, a as safeSet, c as DeepReadonly, d as RequiredBy, f as StoreInitConfig, g as StoreUpdater, h as StoreSelector, i as safeGet, l as EqualityFunction, m as StoreRecordValues, n as deepClone, o as ProviderComponent, p as StoreListener, r as produce, s as composeProviders, t as MutativeUtils, u as PartialBy, v as StoresValues } from "./utils2.js"; | ||
| export { ComparisonOptions, ComparisonStrategy, CustomComparator, DeepReadonly, EqualityFunction, MutativeUtils, PartialBy, ProviderComponent, RequiredBy, StoreInitConfig, StoreListener, StoreRecordValues, StoreSelector, StoreUpdater, StoreValue, StoresValues, compareValues, composeProviders, deepClone, getGlobalComparisonOptions, produce, safeGet, safeSet, setGlobalComparisonOptions }; |
+3
-3
@@ -1,4 +0,4 @@ | ||
| import { ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getGlobalComparisonOptions, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions } from "./error-handling-CkdfKCZ0.js"; | ||
| import { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager } from "./utils-B_r1_2dw.js"; | ||
| import { a as setGlobalComparisonOptions, r as getGlobalComparisonOptions, t as compareValues } from "./comparison.js"; | ||
| import { a as safeSet, i as safeGet, n as deepClone, o as composeProviders, r as produce, t as MutativeUtils } from "./utils2.js"; | ||
| export { ImmerUtils, SubscriptionManager, TypeUtils, compareValues, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useSubscriptionManager }; | ||
| export { MutativeUtils, compareValues, composeProviders, deepClone, getGlobalComparisonOptions, produce, safeGet, safeSet, setGlobalComparisonOptions }; |
+42
-35
| { | ||
| "name": "@context-action/react", | ||
| "version": "0.8.4", | ||
| "version": "0.8.6", | ||
| "type": "module", | ||
@@ -48,2 +48,21 @@ "description": "React integration for @context-action/core - Context and hooks for type-safe action management", | ||
| ], | ||
| "scripts": { | ||
| "build": "tsdown", | ||
| "build:prod": "NODE_ENV=production tsdown", | ||
| "build:dev": "NODE_ENV=development tsdown", | ||
| "build:watch": "tsdown --watch", | ||
| "test": "jest", | ||
| "test:canonical-example": "jest --runInBand __tests__/patterns/implementation-playbook.integration.test.tsx", | ||
| "test:watch": "jest --watch", | ||
| "lint": "eslint src --ext .ts,.tsx", | ||
| "lint:fix": "eslint src --ext .ts,.tsx --fix", | ||
| "type-check": "tsc --noEmit", | ||
| "clean": "rimraf dist", | ||
| "security:audit": "pnpm audit --audit-level high", | ||
| "analyze": "NODE_ENV=production tsdown --analyze", | ||
| "bundle-report": "NODE_ENV=production tsdown --report", | ||
| "security:outdated": "pnpm outdated", | ||
| "security:check": "pnpm security:audit && pnpm security:outdated", | ||
| "prepublishOnly": "pnpm run build:prod" | ||
| }, | ||
| "keywords": [ | ||
@@ -69,2 +88,5 @@ "typescript", | ||
| "homepage": "https://github.com/mineclover/context-action#readme", | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "peerDependencies": { | ||
@@ -74,4 +96,4 @@ "react": "^17.0.0 || ^18.0.0 || ^19.0.0" | ||
| "dependencies": { | ||
| "@context-action/core": "^0.8.4", | ||
| "immer": "^10.1.3", | ||
| "@context-action/core": "^0.8.6", | ||
| "@context-action/mutative": "^0.8.6", | ||
| "react-compiler-runtime": "1.0.0" | ||
@@ -81,22 +103,23 @@ }, | ||
| "@eslint/js": "^9.36.0", | ||
| "@testing-library/jest-dom": "6.8.0", | ||
| "@testing-library/react": "16.3.0", | ||
| "@testing-library/jest-dom": "6.9.1", | ||
| "@testing-library/react": "16.3.2", | ||
| "@testing-library/user-event": "14.6.1", | ||
| "@types/jest": "^30.0.0", | ||
| "@types/node": "^24.5.2", | ||
| "@types/three": "^0.180.0", | ||
| "@typescript-eslint/eslint-plugin": "^8.44.1", | ||
| "@typescript-eslint/parser": "^8.44.1", | ||
| "@types/node": "^25.5.0", | ||
| "@types/three": "^0.183.1", | ||
| "@typescript-eslint/eslint-plugin": "^8.57.2", | ||
| "@typescript-eslint/parser": "^8.57.2", | ||
| "eslint": "^9.36.0", | ||
| "eslint-plugin-react-hooks": "^5.2.0", | ||
| "jest": "^30.1.3", | ||
| "jest-environment-jsdom": "^30.1.2", | ||
| "react": "^19.1.1", | ||
| "react-dom": "^19.1.1", | ||
| "rimraf": "^6.0.1", | ||
| "rollup-plugin-visualizer": "6.0.3", | ||
| "ts-jest": "^29.4.4", | ||
| "jest": "^30.3.0", | ||
| "jest-environment-jsdom": "^30.3.0", | ||
| "react": "^19.2.4", | ||
| "react-dom": "^19.2.4", | ||
| "rimraf": "^6.1.3", | ||
| "rollup-plugin-visualizer": "7.0.1", | ||
| "ts-jest": "^29.4.6", | ||
| "tsdown": "^0.15.4", | ||
| "tslib": "^2.8.1", | ||
| "typescript": "^5.9.2" | ||
| "typescript": "^5.9.2", | ||
| "zod": "^4.3.6" | ||
| }, | ||
@@ -120,19 +143,3 @@ "engines": { | ||
| ], | ||
| "scripts": { | ||
| "build": "tsdown", | ||
| "build:prod": "NODE_ENV=production tsdown", | ||
| "build:dev": "NODE_ENV=development tsdown", | ||
| "build:watch": "tsdown --watch", | ||
| "test": "jest", | ||
| "test:watch": "jest --watch", | ||
| "lint": "eslint src --ext .ts,.tsx", | ||
| "lint:fix": "eslint src --ext .ts,.tsx --fix", | ||
| "type-check": "tsc --noEmit", | ||
| "clean": "rimraf dist", | ||
| "security:audit": "pnpm audit --audit-level high", | ||
| "analyze": "NODE_ENV=production tsdown --analyze", | ||
| "bundle-report": "NODE_ENV=production tsdown --report", | ||
| "security:outdated": "pnpm outdated", | ||
| "security:check": "pnpm security:audit && pnpm security:outdated" | ||
| } | ||
| } | ||
| "gitHead": "f43e1503a6a71d94f6dd1e49734f46fb0d51a606" | ||
| } |
| const require_error_handling = require('./error-handling-ibCwx4ki.cjs'); | ||
| let react = require("react"); | ||
| react = require_error_handling.__toESM(react); | ||
| let react_jsx_runtime = require("react/jsx-runtime"); | ||
| react_jsx_runtime = require_error_handling.__toESM(react_jsx_runtime); | ||
| let __context_action_core = require("@context-action/core"); | ||
| __context_action_core = require_error_handling.__toESM(__context_action_core); | ||
| //#region src/stores/core/StoreRegistry.ts | ||
| /** | ||
| * Centralized store registry for managing multiple Store instances | ||
| */ | ||
| var StoreRegistry = class { | ||
| constructor(name = "default") { | ||
| this.stores = /* @__PURE__ */ new Map(); | ||
| this.metadata = /* @__PURE__ */ new WeakMap(); | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this._snapshot = []; | ||
| this.name = name; | ||
| } | ||
| /** | ||
| * Subscribe to registry changes for reactive updates | ||
| */ | ||
| subscribe(listener) { | ||
| this.listeners.add(listener); | ||
| return () => { | ||
| this.listeners.delete(listener); | ||
| }; | ||
| } | ||
| /** | ||
| * Register a new store in the registry | ||
| */ | ||
| register(name, store, metadata) { | ||
| if (this.stores.has(name)) { | ||
| if (this.stores.get(name)) {} | ||
| } | ||
| this.stores.set(name, store); | ||
| if (metadata) this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name, | ||
| ...metadata | ||
| }); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Unregister a store from the registry | ||
| */ | ||
| unregister(name) { | ||
| if (!this.stores.get(name)) return false; | ||
| this.stores.delete(name); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get a store by name | ||
| */ | ||
| getStore(name) { | ||
| return this.stores.get(name); | ||
| } | ||
| /** | ||
| * Check if a store exists | ||
| */ | ||
| hasStore(name) { | ||
| return this.stores.has(name); | ||
| } | ||
| /** | ||
| * Get all registered store names | ||
| */ | ||
| getStoreNames() { | ||
| return Array.from(this.stores.keys()); | ||
| } | ||
| /** | ||
| * Get all stores as entries | ||
| */ | ||
| getAllStores() { | ||
| return new Map(this.stores); | ||
| } | ||
| /** | ||
| * Get store metadata | ||
| */ | ||
| getStoreMetadata(nameOrStore) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| return store ? this.metadata.get(store) : void 0; | ||
| } | ||
| /** | ||
| * Update store metadata | ||
| */ | ||
| updateStoreMetadata(nameOrStore, metadata) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| if (!store) return false; | ||
| const currentMetadata = this.metadata.get(store); | ||
| this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown", | ||
| ...currentMetadata, | ||
| ...metadata | ||
| }); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get registry snapshot for React integration | ||
| */ | ||
| getSnapshot() { | ||
| return this._snapshot; | ||
| } | ||
| /** | ||
| * Clear all stores from registry | ||
| */ | ||
| clear() { | ||
| this.stores.clear(); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Dispose registry and cleanup resources | ||
| */ | ||
| dispose() { | ||
| this.clear(); | ||
| this.listeners.clear(); | ||
| } | ||
| /** | ||
| * Get count of registered stores | ||
| */ | ||
| getStoreCount() { | ||
| return this.stores.size; | ||
| } | ||
| /** | ||
| * Iterate over all stores | ||
| */ | ||
| forEach(callback) { | ||
| this.stores.forEach((store, name) => { | ||
| callback(store, name); | ||
| }); | ||
| } | ||
| /** | ||
| * Get registry statistics | ||
| */ | ||
| getStats() { | ||
| return { | ||
| totalStores: this.stores.size, | ||
| storeNames: this.getStoreNames(), | ||
| registryName: this.name | ||
| }; | ||
| } | ||
| /** | ||
| * Update internal snapshot | ||
| */ | ||
| _updateSnapshot() { | ||
| this._snapshot = Array.from(this.stores.entries()); | ||
| } | ||
| /** | ||
| * Notify all listeners of registry changes | ||
| */ | ||
| _notifyListeners() { | ||
| this.listeners.forEach((listener) => { | ||
| try { | ||
| listener(); | ||
| } catch (error) { | ||
| console.error("Error in registry listener:", error); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Global default registry instance | ||
| */ | ||
| const globalStoreRegistry = new StoreRegistry("global"); | ||
| //#endregion | ||
| //#region src/stores/utils/type-guards.ts | ||
| function isRefState(value) { | ||
| return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean"; | ||
| } | ||
| /** | ||
| * DOM Event 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMEvent(value) { | ||
| return value instanceof Event; | ||
| } | ||
| /** | ||
| * Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체) | ||
| */ | ||
| function isEventLike(value) { | ||
| return typeof value === "object" && value !== null && typeof value.preventDefault === "function"; | ||
| } | ||
| /** | ||
| * target 프로퍼티를 가진 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function hasTargetProperty(value) { | ||
| return typeof value === "object" && value !== null && "target" in value; | ||
| } | ||
| /** | ||
| * DOM Element인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMElement(value) { | ||
| return value instanceof Element; | ||
| } | ||
| /** | ||
| * 객체인지 확인하는 타입 가드 (null 제외) | ||
| */ | ||
| function isObject(value) { | ||
| return typeof value === "object" && value !== null && !Array.isArray(value); | ||
| } | ||
| /** | ||
| * 복합 타입 가드: Event 객체로 의심되는 객체인지 확인 | ||
| * RefState가 아니면서 Event 관련 속성을 가진 객체를 감지 | ||
| */ | ||
| function isSuspiciousEventObject(value, checkNested = true) { | ||
| if (!isObject(value) || isRefState(value)) return false; | ||
| if (isEventLikeObject(value)) return true; | ||
| if (checkNested) { | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const nestedValue = value[key]; | ||
| if (isEventLikeObject(nestedValue)) return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * 단일 객체가 이벤트와 같은지 확인 | ||
| */ | ||
| function isEventLikeObject(value) { | ||
| if (!isObject(value)) return false; | ||
| const hasEventTarget = hasTargetProperty(value); | ||
| const hasPreventDefault = isEventLike(value); | ||
| const isEvent = isDOMEvent(value); | ||
| const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault); | ||
| const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value; | ||
| const constructorName = value?.constructor?.name; | ||
| const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false; | ||
| return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor; | ||
| } | ||
| /** | ||
| * 문제가 될 수 있는 속성들을 찾아내는 함수 | ||
| */ | ||
| function findProblematicProperties(value) { | ||
| if (!isObject(value)) return []; | ||
| const problematicKeys = []; | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const prop = value[key]; | ||
| if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key); | ||
| } | ||
| return problematicKeys; | ||
| } | ||
| /** | ||
| * 통합 타입 가드 객체 | ||
| * 모든 타입 가드 함수들을 하나의 객체로 export | ||
| */ | ||
| const TypeGuards = { | ||
| isRefState, | ||
| isDOMEvent, | ||
| isEventLike, | ||
| hasTargetProperty, | ||
| isDOMElement, | ||
| isObject, | ||
| isSuspiciousEventObject, | ||
| findProblematicProperties | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/core/Store.ts | ||
| /** | ||
| * Core Store class for centralized state management with memory leak prevention | ||
| * | ||
| * Provides reactive state management with subscription capabilities, optimized for | ||
| * React integration through useSyncExternalStore. Features advanced cleanup mechanisms, | ||
| * automatic resource management, and comprehensive memory leak prevention. | ||
| * | ||
| * Key Features: | ||
| * - Automatic cleanup task registration and execution | ||
| * - Memory leak prevention with disposal patterns | ||
| * - Race condition protection for async operations | ||
| * - Advanced error recovery with exponential backoff | ||
| * - Resource monitoring and threshold management | ||
| * | ||
| * @template T - The type of value stored in this store | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const userStore = createStore('user', { name: '', age: 0 }); | ||
| * | ||
| * // Register cleanup tasks | ||
| * const unregister = userStore.registerCleanup(() => { | ||
| * console.log('Cleaning up user store resources'); | ||
| * }); | ||
| * | ||
| * // Automatic cleanup on disposal | ||
| * userStore.dispose(); | ||
| * ``` | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * @public | ||
| */ | ||
| var Store = class { | ||
| constructor(name, initialValue) { | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this._lastClonedValue = null; | ||
| this._lastClonedVersion = 0; | ||
| this._version = 0; | ||
| this.isUpdating = false; | ||
| this.updateQueue = []; | ||
| this.notificationMode = "batched"; | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| this.pendingUpdatesCount = 0; | ||
| this.cleanupTasks = /* @__PURE__ */ new Set(); | ||
| this.isDisposed = false; | ||
| this.errorCount = 0; | ||
| this.lastErrorTime = 0; | ||
| this.MAX_ERROR_COUNT = 5; | ||
| this.ERROR_RESET_TIME = 6e4; | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.cloningEnabled = true; | ||
| this.subscribe = (listener) => { | ||
| if (this.isDisposed) { | ||
| console.warn(`Cannot subscribe to disposed store "${this.name}"`); | ||
| return () => {}; | ||
| } | ||
| const enhancedListener = () => { | ||
| if (this.isDisposed) return; | ||
| try { | ||
| listener(); | ||
| if (this.errorCount > 0) this.errorCount = 0; | ||
| } catch (error) { | ||
| this._handleListenerError(error, listener); | ||
| } | ||
| }; | ||
| this.subscriptionRegistry.set(listener, { | ||
| subscribedAt: Date.now(), | ||
| errorCount: 0, | ||
| enhancedListener | ||
| }); | ||
| this.listeners.add(enhancedListener); | ||
| return () => { | ||
| this.listeners.delete(enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| }; | ||
| }; | ||
| this.getSnapshot = () => { | ||
| return this._snapshot; | ||
| }; | ||
| this.name = name; | ||
| this._value = initialValue; | ||
| this._snapshot = this._createSnapshot(); | ||
| } | ||
| /** | ||
| * 현재 값 직접 가져오기 (액션 핸들러용) | ||
| * 핵심 로직: 불변성을 보장하는 깊은 복사본 반환 | ||
| * | ||
| * @implements lazy-evaluation | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 사용 시나리오: Action handler에서 최신 상태 읽기 | ||
| * 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨 | ||
| */ | ||
| getValue() { | ||
| if (typeof this._value !== "object" || this._value === null) return this._value; | ||
| if (this.cloningEnabled) { | ||
| if (this._lastClonedVersion === this._version && this._lastClonedValue !== null) return this._lastClonedValue; | ||
| this._lastClonedValue = require_error_handling.safeGet(this._value, this.cloningEnabled); | ||
| this._lastClonedVersion = this._version; | ||
| return this._lastClonedValue; | ||
| } | ||
| return this._value; | ||
| } | ||
| /** | ||
| * Store 값 설정 및 구독자 알림 | ||
| * 핵심 로직: | ||
| * 1. 입력값의 불변성 보장을 위한 깊은 복사 (선택적 skip 가능) | ||
| * 2. 강화된 값 비교 시스템으로 불필요한 리렌더링 방지 | ||
| * 3. Structural sharing을 통한 성능 최적화 | ||
| * 4. 값 변경 시에만 스냅샷 재생성 및 알림 | ||
| * | ||
| * @implements unidirectional-data-flow | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 보안 강화: 입력값을 복사하여 Store 내부 상태가 외부 참조에 의해 변경되지 않도록 보호 | ||
| * 성능 강화: 다층 비교 시스템으로 정확한 변경 감지 및 렌더링 최적화 | ||
| */ | ||
| setValue(value, options) { | ||
| if (TypeGuards.isObject(value)) { | ||
| if (!TypeGuards.isRefState(value) && TypeGuards.isSuspiciousEventObject(value)) { | ||
| const eventHandling = options?.eventHandling || "block"; | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(value); | ||
| const hasPreventDefault = TypeGuards.isEventLike(value); | ||
| const isEvent = TypeGuards.isDOMEvent(value); | ||
| switch (eventHandling) { | ||
| case "allow": break; | ||
| case "transform": | ||
| if (options?.eventTransform) try { | ||
| value = options.eventTransform(value); | ||
| } catch (error) { | ||
| require_error_handling.ErrorHandlers.store("Event transformation failed in Store.setValue", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| error: error instanceof Error ? error.message : String(error) | ||
| }); | ||
| return; | ||
| } | ||
| else { | ||
| require_error_handling.ErrorHandlers.store("Event transformation requested but no transform function provided", { | ||
| storeName: this.name, | ||
| valueType: typeof value | ||
| }); | ||
| return; | ||
| } | ||
| break; | ||
| case "block": | ||
| default: | ||
| require_error_handling.ErrorHandlers.store("Event object detected in Store.setValue - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| constructorName: value?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(value) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| const safeValue = options?.skipClone ? value : require_error_handling.safeSet(value, this.cloningEnabled); | ||
| let hasChanged = true; | ||
| if (!options?.skipComparison) hasChanged = this._compareValues(this._value, safeValue); | ||
| if (hasChanged) { | ||
| this._value = safeValue; | ||
| this._version++; | ||
| this._snapshot = this._createSnapshot(); | ||
| this._scheduleNotification(); | ||
| } | ||
| } | ||
| /** | ||
| * Update value using updater function with Immer integration | ||
| * 핵심 로직: | ||
| * 1. Immer produce를 사용하여 draft 객체 제공 | ||
| * 2. updater 결과를 불변성을 보장하며 설정 | ||
| * | ||
| * @implements store-immutability | ||
| * 보안 강화: Immer draft를 통한 안전한 상태 수정 | ||
| */ | ||
| update(updater) { | ||
| if (this.isUpdating) { | ||
| this.updateQueue.push(() => this.update(updater)); | ||
| return; | ||
| } | ||
| try { | ||
| this.isUpdating = true; | ||
| let updatedValue; | ||
| try { | ||
| updatedValue = require_error_handling.produce(this._value, (draft) => { | ||
| const result = updater(draft); | ||
| return result !== void 0 ? result : draft; | ||
| }); | ||
| } catch (immerError) { | ||
| if (process.env.NODE_ENV === "development") console.warn("[Store] Immer update failed, falling back to safe copy method", immerError); | ||
| const safeCurrentValue = require_error_handling.safeGet(this._value, this.cloningEnabled); | ||
| try { | ||
| updatedValue = require_error_handling.produce(safeCurrentValue, (draft) => { | ||
| const result = updater(draft); | ||
| return result !== void 0 ? result : draft; | ||
| }); | ||
| } catch (secondImmerError) { | ||
| if (process.env.NODE_ENV === "development") console.warn("[Store] Immer completely failed, using direct update (immutability not guaranteed)", secondImmerError); | ||
| updatedValue = updater(safeCurrentValue); | ||
| } | ||
| } | ||
| if (TypeGuards.isObject(updatedValue)) { | ||
| if (!TypeGuards.isRefState(updatedValue) && TypeGuards.isSuspiciousEventObject(updatedValue)) { | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(updatedValue); | ||
| const hasPreventDefault = TypeGuards.isEventLike(updatedValue); | ||
| const isEvent = TypeGuards.isDOMEvent(updatedValue); | ||
| require_error_handling.ErrorHandlers.store("Event object detected in Store.update result - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| updatedValueType: typeof updatedValue, | ||
| constructorName: updatedValue?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(updatedValue) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| this.setValue(updatedValue); | ||
| } finally { | ||
| this.isUpdating = false; | ||
| if (this.updateQueue.length > 0) { | ||
| const nextUpdate = this.updateQueue.shift(); | ||
| if (nextUpdate) Promise.resolve().then(nextUpdate); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Get number of active listeners | ||
| */ | ||
| getListenerCount() { | ||
| return this.listeners.size; | ||
| } | ||
| /** | ||
| * Clear all listeners | ||
| */ | ||
| clearListeners() { | ||
| this.listeners.clear(); | ||
| } | ||
| /** | ||
| * Register cleanup task for automatic execution on disposal | ||
| * | ||
| * Registers a cleanup function that will be automatically called when the store | ||
| * is disposed. This prevents memory leaks and ensures proper resource cleanup. | ||
| * | ||
| * @param task - Cleanup function to register | ||
| * @returns Unregister function to remove the cleanup task | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const timer = setInterval(() => {}, 1000); | ||
| * const unregister = store.registerCleanup(() => clearInterval(timer)); | ||
| * | ||
| * // Later, remove the cleanup task if needed | ||
| * unregister(); | ||
| * ``` | ||
| */ | ||
| registerCleanup(task) { | ||
| if (this.isDisposed) { | ||
| console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`); | ||
| return () => {}; | ||
| } | ||
| this.cleanupTasks.add(task); | ||
| return () => this.cleanupTasks.delete(task); | ||
| } | ||
| /** | ||
| * Enhanced Store disposal with comprehensive cleanup | ||
| * | ||
| * Performs complete cleanup of all store resources including listeners, | ||
| * timers, cleanup tasks, and internal state. Prevents memory leaks and | ||
| * ensures proper resource disposal. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Manual disposal | ||
| * store.dispose(); | ||
| * | ||
| * // Auto-disposal with useEffect | ||
| * useEffect(() => { | ||
| * return () => store.dispose(); | ||
| * }, [store]); | ||
| * ``` | ||
| */ | ||
| dispose() { | ||
| if (this.isDisposed) return; | ||
| this.isDisposed = true; | ||
| try { | ||
| this.cleanupTasks.forEach((task) => { | ||
| try { | ||
| task(); | ||
| } catch (error) { | ||
| require_error_handling.ErrorHandlers.store("Error during cleanup task execution", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| }); | ||
| this.cleanupTasks.clear(); | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.clearListeners(); | ||
| if (this.animationFrameId !== null) { | ||
| cancelAnimationFrame(this.animationFrameId); | ||
| this.animationFrameId = null; | ||
| } | ||
| this.pendingNotification = false; | ||
| this.updateQueue.length = 0; | ||
| } catch (error) { | ||
| require_error_handling.ErrorHandlers.store("Critical error during store disposal", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| } | ||
| /** | ||
| * Check if store is disposed | ||
| * @returns true if store has been disposed | ||
| */ | ||
| isStoreDisposed() { | ||
| return this.isDisposed; | ||
| } | ||
| /** | ||
| * Store별 커스텀 비교 함수 설정 | ||
| * 이 Store에만 적용되는 특별한 비교 로직 설정 | ||
| * | ||
| * @param comparator - 커스텀 비교 함수 (oldValue, newValue) => boolean | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setCustomComparator(comparator) { | ||
| this.customComparator = comparator; | ||
| } | ||
| /** | ||
| * Store별 비교 옵션 설정 | ||
| * 이 Store에만 적용되는 비교 전략 설정 | ||
| * | ||
| * @param options - 비교 옵션 | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setComparisonOptions(options) { | ||
| this.comparisonOptions = options; | ||
| } | ||
| /** | ||
| * 성능 최적화: Store별 복사 동작 제어 | ||
| * | ||
| * @param enabled - true: 복사 활성화 (안전), false: 복사 비활성화 (성능 우선) | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/performance | ||
| */ | ||
| setCloningEnabled(enabled) { | ||
| this.cloningEnabled = enabled; | ||
| } | ||
| /** | ||
| * 현재 복사 설정 조회 | ||
| */ | ||
| isCloningEnabled() { | ||
| return this.cloningEnabled; | ||
| } | ||
| /** | ||
| * 강화된 값 비교 시스템 | ||
| * 1. 커스텀 비교 함수 우선 사용 | ||
| * 2. Store별 비교 옵션 적용 | ||
| * 3. 성능 최적화된 빠른 비교 fallback | ||
| * 4. 전역 비교 설정 사용 | ||
| * | ||
| * @param oldValue - 이전 값 | ||
| * @param newValue - 새로운 값 | ||
| * @returns true if values are different (change detected), false if same | ||
| * @protected | ||
| */ | ||
| _compareValues(oldValue, newValue) { | ||
| let result; | ||
| try { | ||
| if (this.customComparator) result = !this.customComparator(oldValue, newValue); | ||
| else if (this.comparisonOptions) result = !require_error_handling.compareValues(oldValue, newValue, this.comparisonOptions); | ||
| else result = !require_error_handling.compareValues(oldValue, newValue, { strategy: "reference" }); | ||
| } catch (error) { | ||
| require_error_handling.ErrorHandlers.store("Error during value comparison, falling back to reference comparison", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| result = !Object.is(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| _createSnapshot() { | ||
| return { | ||
| value: require_error_handling.safeGet(this._value, this.cloningEnabled), | ||
| name: this.name, | ||
| lastUpdate: Date.now() | ||
| }; | ||
| } | ||
| /** | ||
| * requestAnimationFrame 기반 알림 스케줄링 | ||
| * 브라우저의 다음 프레임에서 리스너 알림 실행 | ||
| */ | ||
| _scheduleNotification() { | ||
| if (this.notificationMode === "immediate") this._notifyListeners(); | ||
| else this._scheduleWithRAF(); | ||
| } | ||
| /** | ||
| * requestAnimationFrame을 사용한 알림 스케줄링 | ||
| * 누적 가능한 배치 시스템으로 개선 | ||
| */ | ||
| _scheduleWithRAF() { | ||
| this.pendingUpdatesCount++; | ||
| if (!this.pendingNotification) { | ||
| this.pendingNotification = true; | ||
| this.animationFrameId = requestAnimationFrame(() => { | ||
| this._executeNotification(); | ||
| }); | ||
| } | ||
| } | ||
| /** | ||
| * 스케줄된 알림 실행 | ||
| */ | ||
| _executeNotification() { | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| const batchedUpdates = this.pendingUpdatesCount; | ||
| this.pendingUpdatesCount = 0; | ||
| this._notifyListeners(); | ||
| if (process.env.NODE_ENV === "development" && batchedUpdates > 1) console.debug(`[Store:${this.name}] Batched ${batchedUpdates} updates in single frame`); | ||
| } | ||
| /** | ||
| * Handle listener execution errors with recovery strategies | ||
| */ | ||
| _handleListenerError(error, listener) { | ||
| const now = Date.now(); | ||
| if (now - this.lastErrorTime > this.ERROR_RESET_TIME) this.errorCount = 0; | ||
| this.errorCount++; | ||
| this.lastErrorTime = now; | ||
| const metadata = this.subscriptionRegistry.get(listener); | ||
| if (metadata) metadata.errorCount++; | ||
| require_error_handling.ErrorHandlers.store("Error in store listener execution", { | ||
| storeName: this.name, | ||
| listenerCount: this.listeners.size, | ||
| errorCount: this.errorCount, | ||
| subscriptionAge: metadata ? now - metadata.subscribedAt : "unknown" | ||
| }, error instanceof Error ? error : void 0); | ||
| if (metadata && metadata.errorCount >= 3) { | ||
| console.warn(`Removing problematic listener from store "${this.name}" after ${metadata.errorCount} errors`); | ||
| this.listeners.delete(metadata.enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| } | ||
| if (this.errorCount >= this.MAX_ERROR_COUNT) { | ||
| console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`); | ||
| this.clearListeners(); | ||
| } | ||
| } | ||
| _notifyListeners() { | ||
| if (this.isDisposed) return; | ||
| this.listeners.forEach((listener) => { | ||
| if (this.isDisposed) return; | ||
| listener(); | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Factory function for creating type-safe Store instances | ||
| * | ||
| * Creates a new Store instance with the specified name and initial value. | ||
| * Provides type safety and integrates seamlessly with React hooks and | ||
| * the Context-Action framework patterns. | ||
| * | ||
| * @template T - The type of values stored in this store | ||
| * | ||
| * @param name - Unique identifier for the store (used for debugging) | ||
| * @param initialValue - Initial value to store | ||
| * | ||
| * @returns Configured Store instance ready for use | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function createStore(name, initialValue) { | ||
| return new Store(name, initialValue); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/sync-external-store-utils.ts | ||
| /** | ||
| * 향상된 구독 함수 생성 (내부 사용) | ||
| * 디바운싱, 스로틀링, 조건부 구독 기능 제공 | ||
| */ | ||
| function createEnhancedSubscriber(store, options = {}) { | ||
| const { debounce, throttle, condition, debug, name = "unknown" } = options; | ||
| return (callback) => { | ||
| if (!store) return () => {}; | ||
| let debounceTimer = null; | ||
| let throttleTimer = null; | ||
| let lastThrottleTime = 0; | ||
| const enhancedCallback = () => { | ||
| if (condition && !condition()) { | ||
| if (debug) console.debug(`[${name}] Subscription suspended due to condition`); | ||
| return; | ||
| } | ||
| const now = performance.now(); | ||
| if (throttle && throttle > 0) { | ||
| if (now - lastThrottleTime < throttle) { | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| throttleTimer = setTimeout(() => { | ||
| lastThrottleTime = performance.now(); | ||
| callback(); | ||
| }, throttle - (now - lastThrottleTime)); | ||
| return; | ||
| } | ||
| lastThrottleTime = now; | ||
| } | ||
| if (debounce && debounce > 0) { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| debounceTimer = setTimeout(() => { | ||
| callback(); | ||
| if (debug) console.debug(`[${name}] Debounced callback executed after ${debounce}ms`); | ||
| }, debounce); | ||
| return; | ||
| } | ||
| callback(); | ||
| }; | ||
| const unsubscribe = store.subscribe(enhancedCallback); | ||
| return () => { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| unsubscribe(); | ||
| }; | ||
| }; | ||
| } | ||
| /** | ||
| * Null-safe Store 구독 훅 | ||
| * useSyncExternalStore를 기반으로 한 안전한 구독 | ||
| */ | ||
| function useSafeStoreSubscription(store, selector, options = {}) { | ||
| const { initialValue, equalityFn, debounce, throttle, condition, debug, name } = options; | ||
| const stableSubscriptionOptions = (0, react.useMemo)(() => ({ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| }), [ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| ]); | ||
| const needsEnhancedSubscription = Boolean(debounce || throttle || condition); | ||
| const subscribe = (0, react.useCallback)((callback) => { | ||
| if (!store) return () => {}; | ||
| if (needsEnhancedSubscription) return createEnhancedSubscriber(store, stableSubscriptionOptions)(callback); | ||
| return store.subscribe(callback); | ||
| }, [ | ||
| store, | ||
| needsEnhancedSubscription, | ||
| stableSubscriptionOptions | ||
| ]); | ||
| const getSnapshot = (0, react.useCallback)(() => { | ||
| if (!store) return initialValue; | ||
| const snapshot = store.getSnapshot(); | ||
| return selector ? selector(snapshot.value) : snapshot.value; | ||
| }, [ | ||
| store, | ||
| selector, | ||
| initialValue | ||
| ]); | ||
| const cachedSnapshotRef = (0, react.useRef)(); | ||
| const stableGetSnapshot = (0, react.useCallback)(() => { | ||
| const currentSnapshot = getSnapshot(); | ||
| if (equalityFn && cachedSnapshotRef.current !== void 0) { | ||
| if (equalityFn(cachedSnapshotRef.current, currentSnapshot)) return cachedSnapshotRef.current; | ||
| } | ||
| cachedSnapshotRef.current = currentSnapshot; | ||
| return currentSnapshot; | ||
| }, [getSnapshot, equalityFn]); | ||
| const getServerSnapshot = (0, react.useCallback)(() => { | ||
| return initialValue; | ||
| }, [initialValue]); | ||
| return (0, react.useSyncExternalStore)(subscribe, equalityFn ? stableGetSnapshot : getSnapshot, getServerSnapshot); | ||
| } | ||
| /** | ||
| * 기본 동등성 비교 함수들 | ||
| */ | ||
| const equalityFunctions = { | ||
| reference: (a, b) => Object.is(a, b), | ||
| shallow: (a, b) => { | ||
| if (Object.is(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| const keysA = Object.keys(a); | ||
| const keysB = Object.keys(b); | ||
| if (keysA.length !== keysB.length) return false; | ||
| for (const key of keysA) if (!Object.prototype.hasOwnProperty.call(b, key) || !Object.is(a[key], b[key])) return false; | ||
| return true; | ||
| }, | ||
| deep: (a, b) => { | ||
| if (Object.is(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| if (Array.isArray(a) !== Array.isArray(b)) return false; | ||
| const keysA = Object.keys(a); | ||
| const keysB = Object.keys(b); | ||
| if (keysA.length !== keysB.length) return false; | ||
| for (const key of keysA) { | ||
| if (!Object.prototype.hasOwnProperty.call(b, key)) return false; | ||
| if (!equalityFunctions.deep(a[key], b[key])) return false; | ||
| } | ||
| return true; | ||
| }, | ||
| smart: (a, b) => { | ||
| if (Object.is(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| return a.every((item, index) => { | ||
| const bItem = b[index]; | ||
| if (typeof item === "object" && item !== null && typeof bItem === "object" && bItem !== null) return equalityFunctions.shallow(item, bItem); | ||
| return Object.is(item, bItem); | ||
| }); | ||
| } | ||
| return equalityFunctions.shallow(a, b); | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreSelector.ts | ||
| const defaultEqualityFn = equalityFunctions.smart; | ||
| const shallowEqual = equalityFunctions.shallow; | ||
| const deepEqual = equalityFunctions.deep; | ||
| const smartEqual = equalityFunctions.smart; | ||
| /** | ||
| * Hook for selective store subscription with performance optimization | ||
| * | ||
| * Subscribes to specific parts of store data using a selector function, | ||
| * triggering re-renders only when the selected value actually changes. | ||
| * Essential for preventing unnecessary re-renders in complex applications. | ||
| * | ||
| * @template T - Type of the store value | ||
| * @template R - Type of the value returned by the selector | ||
| * | ||
| * @param store - Store instance to subscribe to | ||
| * @param selector - Function to extract needed data from store value | ||
| * @param equalityFn - Function to compare previous and new values (default: Object.is) | ||
| * | ||
| * @returns The value returned by the selector function | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usestoreselector-advanced-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function useStoreSelector(store, selector, equalityFn = defaultEqualityFn) { | ||
| "use memo"; | ||
| const stableSelector = (0, react.useCallback)(selector, [selector]); | ||
| const stableEqualityFn = (0, react.useCallback)(equalityFn, [equalityFn]); | ||
| const selectorWarningShownRef = (0, react.useRef)(false); | ||
| if (process.env.NODE_ENV === "development") { | ||
| if (selector !== stableSelector && !selectorWarningShownRef.current) { | ||
| console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name); | ||
| selectorWarningShownRef.current = true; | ||
| } | ||
| } | ||
| const previousValueRef = (0, react.useRef)(); | ||
| const subscribe = (0, react.useCallback)((callback) => { | ||
| return store.subscribe(callback); | ||
| }, [store]); | ||
| const getSnapshot = (0, react.useCallback)(() => { | ||
| try { | ||
| const selectedValue = stableSelector(store.getValue()); | ||
| if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current; | ||
| previousValueRef.current = selectedValue; | ||
| return selectedValue; | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") console.error("useStoreSelector: Error in selector function:", error); | ||
| throw error; | ||
| } | ||
| }, [ | ||
| store, | ||
| stableSelector, | ||
| stableEqualityFn | ||
| ]); | ||
| return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.tsx | ||
| /** | ||
| * Store 시스템을 위한 에러 경계 컴포넌트 | ||
| * | ||
| * Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다. | ||
| * 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는 | ||
| * 사용자 친화적인 메시지를 보여줍니다. | ||
| */ | ||
| var StoreErrorBoundary = class extends react.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.resetTimeoutId = null; | ||
| this.resetErrorBoundary = () => { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| this.setState({ | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }); | ||
| }; | ||
| this.state = { | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }; | ||
| } | ||
| static getDerivedStateFromError(error) { | ||
| return { | ||
| hasError: true, | ||
| error: error instanceof Error && error.name === "ContextActionError" ? error : null, | ||
| errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` | ||
| }; | ||
| } | ||
| componentDidCatch(error, errorInfo) { | ||
| if (error.name === "ContextActionError") { | ||
| const contextActionError = error; | ||
| this.setState({ errorInfo }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } else { | ||
| const contextActionError = require_error_handling.ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, { | ||
| component: "StoreErrorBoundary", | ||
| stack: error.stack, | ||
| componentStack: errorInfo.componentStack | ||
| }, error); | ||
| this.setState({ | ||
| error: contextActionError, | ||
| errorInfo | ||
| }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } | ||
| } | ||
| componentDidUpdate(prevProps) { | ||
| const { hasError } = this.state; | ||
| const { resetOnPropsChange, resetKeys } = this.props; | ||
| if (hasError && resetOnPropsChange) { | ||
| if (resetKeys) { | ||
| if (resetKeys.some((key) => { | ||
| return prevProps[key] !== this.props[key]; | ||
| })) this.resetErrorBoundary(); | ||
| } else if (prevProps !== this.props) this.resetErrorBoundary(); | ||
| } | ||
| } | ||
| componentWillUnmount() { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| } | ||
| render() { | ||
| const { hasError, error, errorInfo } = this.state; | ||
| const { children, fallback } = this.props; | ||
| if (hasError) { | ||
| if (fallback) { | ||
| if (typeof fallback === "function") return fallback(error, errorInfo); | ||
| return fallback; | ||
| } | ||
| return this.renderDefaultFallback(); | ||
| } | ||
| return children; | ||
| } | ||
| renderDefaultFallback() { | ||
| if (process.env.NODE_ENV === "development") return this.renderDevelopmentFallback(); | ||
| else return this.renderProductionFallback(); | ||
| } | ||
| renderDevelopmentFallback() { | ||
| const { error, errorInfo, errorId } = this.state; | ||
| const stats = require_error_handling.getErrorStatistics(); | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { | ||
| padding: "20px", | ||
| margin: "20px", | ||
| border: "2px solid #ff6b6b", | ||
| borderRadius: "8px", | ||
| backgroundColor: "#ffe0e0", | ||
| fontFamily: "monospace" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { | ||
| style: { | ||
| color: "#d63031", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "🚨 Store Error Boundary" | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error ID:" }), | ||
| " ", | ||
| errorId | ||
| ] | ||
| }), | ||
| error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Type:" }), | ||
| " ", | ||
| error.type, | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Message:" }), | ||
| " ", | ||
| error.message, | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Timestamp:" }), | ||
| " ", | ||
| new Date(error.timestamp).toISOString() | ||
| ] | ||
| }), | ||
| error?.context && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Context:" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "12px" | ||
| }, | ||
| children: JSON.stringify(error.context, null, 2) | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Statistics:" }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| "Total Errors: ", | ||
| stats.totalErrors, | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), | ||
| "Recent Errors: ", | ||
| stats.recentErrors.length | ||
| ] | ||
| }), | ||
| errorInfo && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { | ||
| style: { | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Component Stack" | ||
| }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "11px", | ||
| whiteSpace: "pre-wrap" | ||
| }, | ||
| children: errorInfo.componentStack | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#00b894", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| renderProductionFallback() { | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { | ||
| style: { | ||
| padding: "20px", | ||
| textAlign: "center", | ||
| backgroundColor: "#f8f9fa", | ||
| border: "1px solid #dee2e6", | ||
| borderRadius: "8px", | ||
| margin: "20px 0" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "Something went wrong" | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 15px 0" | ||
| }, | ||
| children: "We're sorry, but something unexpected happened. Please try again." | ||
| }), | ||
| /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#007bff", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Enhanced HOC for automatic Store Error Boundary wrapping with security | ||
| * | ||
| * @template P - Component props type | ||
| * @param WrappedComponent - Component to wrap with error boundary | ||
| * @param errorBoundaryProps - Error boundary configuration | ||
| * @returns Enhanced component with comprehensive error handling | ||
| */ | ||
| function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) { | ||
| const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, { | ||
| ...errorBoundaryProps, | ||
| children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WrappedComponent, { ...props }) | ||
| }); | ||
| WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`; | ||
| return WithStoreErrorBoundaryComponent; | ||
| } | ||
| /** | ||
| * 특정 Store와 연결된 에러 경계 생성 헬퍼 | ||
| */ | ||
| function createStoreErrorBoundary(storeName, customFallback) { | ||
| return ({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, { | ||
| fallback: customFallback, | ||
| onError: (error, errorInfo) => { | ||
| console.group(`Store Error in ${storeName}`); | ||
| console.error("Error:", error); | ||
| console.error("Component Stack:", errorInfo.componentStack); | ||
| console.groupEnd(); | ||
| }, | ||
| resetKeys: [storeName], | ||
| children | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.tsx | ||
| function createActionContext(contextNameOrConfig = {}, config) { | ||
| let effectiveConfig; | ||
| let contextName; | ||
| if (typeof contextNameOrConfig === "string") { | ||
| contextName = contextNameOrConfig; | ||
| effectiveConfig = { | ||
| ...config, | ||
| name: config?.name || contextName | ||
| }; | ||
| } else { | ||
| effectiveConfig = contextNameOrConfig; | ||
| contextName = effectiveConfig.name || "ActionContext"; | ||
| } | ||
| const FactoryActionContext = (0, react.createContext)(null); | ||
| const Provider = ({ children }) => { | ||
| const actionRegisterRef = (0, react.useRef)(new __context_action_core.ActionRegister(effectiveConfig)); | ||
| const contextValue = (0, react.useMemo)(() => ({ actionRegisterRef }), []); | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FactoryActionContext.Provider, { | ||
| value: contextValue, | ||
| children | ||
| }); | ||
| }; | ||
| const useFactoryActionContext = () => { | ||
| const context = (0, react.useContext)(FactoryActionContext); | ||
| if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider"); | ||
| return context; | ||
| }; | ||
| /** | ||
| * Optimized hook to get stable dispatch functions | ||
| * | ||
| * Returns stable dispatch functions that prevent re-renders and maintain | ||
| * reference equality across component renders. | ||
| * | ||
| * @returns Object with dispatch and dispatchWithResult functions | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useActionDispatcher = () => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| return { | ||
| dispatch: (0, react.useCallback)((action, payload, options) => { | ||
| if (process.env.NODE_ENV === "development") console.log(`React dispatch called for '${String(action)}':`, { | ||
| hasPayload: payload !== void 0, | ||
| hasOptions: options !== void 0, | ||
| timestamp: (/* @__PURE__ */ new Date()).toISOString() | ||
| }); | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]), | ||
| dispatchWithResult: (0, react.useCallback)((action, payload, options) => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]) | ||
| }; | ||
| }; | ||
| const useAction = () => { | ||
| const { dispatch } = useActionDispatcher(); | ||
| return dispatch; | ||
| }; | ||
| const useActionHandler = (action, handler, config$1) => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| const actionId = (0, react.useId)(); | ||
| const handlerRef = (0, react.useRef)(handler); | ||
| handlerRef.current = handler; | ||
| const priority = config$1?.priority ?? 0; | ||
| const id = config$1?.id || `react_${String(action)}_${actionId}`; | ||
| const blocking = config$1?.blocking ?? false; | ||
| const once = config$1?.once ?? false; | ||
| const debounce = config$1?.debounce; | ||
| const throttle = config$1?.throttle; | ||
| const stableConfig = (0, react.useMemo)(() => ({ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| replaceExisting: true, | ||
| ...debounce !== void 0 && { debounce }, | ||
| ...throttle !== void 0 && { throttle } | ||
| }), [ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| debounce, | ||
| throttle | ||
| ]); | ||
| (0, react.useEffect)(() => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) return; | ||
| const wrapperHandler = (payload, controller) => { | ||
| return handlerRef.current(payload, controller); | ||
| }; | ||
| if (process.env.NODE_ENV === "development") console.log(`Registering handler for '${String(action)}'`); | ||
| return register.register(action, wrapperHandler, stableConfig); | ||
| }, [ | ||
| action, | ||
| actionRegisterRef, | ||
| stableConfig | ||
| ]); | ||
| }; | ||
| /** | ||
| * Hook that provides direct access to the ActionRegister instance | ||
| * | ||
| * This hook is useful when you need to: | ||
| * - Register multiple handlers dynamically | ||
| * - Access other ActionRegister methods like clearAction, getHandlers, etc. | ||
| * - Implement complex handler registration logic | ||
| * - Have more control over the registration lifecycle | ||
| * | ||
| * @returns ActionRegister instance or null if not initialized | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useFactoryActionRegister = () => { | ||
| return useFactoryActionContext().actionRegisterRef.current; | ||
| }; | ||
| /** | ||
| * Hook that provides access to the dispatchWithResult function | ||
| * | ||
| * This hook returns a function that dispatches actions and returns detailed | ||
| * execution results including collected handler results, execution metadata, | ||
| * and error information. | ||
| * | ||
| * @returns dispatchWithResult function with full type safety | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result | ||
| */ | ||
| const useFactoryActionDispatchWithResult = () => { | ||
| const context = useFactoryActionContext(); | ||
| const activeControllersRef = (0, react.useRef)(/* @__PURE__ */ new Set()); | ||
| const dispatch = (0, react.useCallback)((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const dispatchWithResult = (0, react.useCallback)((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const abortAll = (0, react.useCallback)(() => { | ||
| activeControllersRef.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| activeControllersRef.current.clear(); | ||
| }, []); | ||
| const resetAbortScope = (0, react.useCallback)(() => { | ||
| abortAll(); | ||
| }, [abortAll]); | ||
| (0, react.useEffect)(() => { | ||
| const controllers = activeControllersRef; | ||
| return () => { | ||
| controllers.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| controllers.current.clear(); | ||
| }; | ||
| }, []); | ||
| return { | ||
| dispatch, | ||
| dispatchWithResult, | ||
| abortAll, | ||
| resetAbortScope | ||
| }; | ||
| }; | ||
| return { | ||
| Provider, | ||
| useActionContext: useFactoryActionContext, | ||
| useActionDispatch: useAction, | ||
| useActionHandler, | ||
| useActionRegister: useFactoryActionRegister, | ||
| useActionDispatchWithResult: useFactoryActionDispatchWithResult, | ||
| context: FactoryActionContext | ||
| }; | ||
| } | ||
| //#endregion | ||
| Object.defineProperty(exports, 'Store', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return Store; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'StoreErrorBoundary', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return StoreErrorBoundary; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'StoreRegistry', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return StoreRegistry; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createActionContext', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createActionContext; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createStore', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createStore; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createStoreErrorBoundary', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createStoreErrorBoundary; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'defaultEqualityFn', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return defaultEqualityFn; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'useSafeStoreSubscription', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return useSafeStoreSubscription; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'useStoreSelector', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return useStoreSelector; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'withStoreErrorBoundary', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return withStoreErrorBoundary; | ||
| } | ||
| }); |
| import { ErrorHandlers, compareValues, getErrorStatistics, produce, safeGet, safeSet } from "./error-handling-CkdfKCZ0.js"; | ||
| import React, { Component, createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useSyncExternalStore } from "react"; | ||
| import { jsx, jsxs } from "react/jsx-runtime"; | ||
| import { ActionRegister } from "@context-action/core"; | ||
| //#region src/stores/core/StoreRegistry.ts | ||
| /** | ||
| * Centralized store registry for managing multiple Store instances | ||
| */ | ||
| var StoreRegistry = class { | ||
| constructor(name = "default") { | ||
| this.stores = /* @__PURE__ */ new Map(); | ||
| this.metadata = /* @__PURE__ */ new WeakMap(); | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this._snapshot = []; | ||
| this.name = name; | ||
| } | ||
| /** | ||
| * Subscribe to registry changes for reactive updates | ||
| */ | ||
| subscribe(listener) { | ||
| this.listeners.add(listener); | ||
| return () => { | ||
| this.listeners.delete(listener); | ||
| }; | ||
| } | ||
| /** | ||
| * Register a new store in the registry | ||
| */ | ||
| register(name, store, metadata) { | ||
| if (this.stores.has(name)) { | ||
| if (this.stores.get(name)) {} | ||
| } | ||
| this.stores.set(name, store); | ||
| if (metadata) this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name, | ||
| ...metadata | ||
| }); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Unregister a store from the registry | ||
| */ | ||
| unregister(name) { | ||
| if (!this.stores.get(name)) return false; | ||
| this.stores.delete(name); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get a store by name | ||
| */ | ||
| getStore(name) { | ||
| return this.stores.get(name); | ||
| } | ||
| /** | ||
| * Check if a store exists | ||
| */ | ||
| hasStore(name) { | ||
| return this.stores.has(name); | ||
| } | ||
| /** | ||
| * Get all registered store names | ||
| */ | ||
| getStoreNames() { | ||
| return Array.from(this.stores.keys()); | ||
| } | ||
| /** | ||
| * Get all stores as entries | ||
| */ | ||
| getAllStores() { | ||
| return new Map(this.stores); | ||
| } | ||
| /** | ||
| * Get store metadata | ||
| */ | ||
| getStoreMetadata(nameOrStore) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| return store ? this.metadata.get(store) : void 0; | ||
| } | ||
| /** | ||
| * Update store metadata | ||
| */ | ||
| updateStoreMetadata(nameOrStore, metadata) { | ||
| const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore; | ||
| if (!store) return false; | ||
| const currentMetadata = this.metadata.get(store); | ||
| this.metadata.set(store, { | ||
| registeredAt: Date.now(), | ||
| name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown", | ||
| ...currentMetadata, | ||
| ...metadata | ||
| }); | ||
| return true; | ||
| } | ||
| /** | ||
| * Get registry snapshot for React integration | ||
| */ | ||
| getSnapshot() { | ||
| return this._snapshot; | ||
| } | ||
| /** | ||
| * Clear all stores from registry | ||
| */ | ||
| clear() { | ||
| this.stores.clear(); | ||
| this._updateSnapshot(); | ||
| this._notifyListeners(); | ||
| } | ||
| /** | ||
| * Dispose registry and cleanup resources | ||
| */ | ||
| dispose() { | ||
| this.clear(); | ||
| this.listeners.clear(); | ||
| } | ||
| /** | ||
| * Get count of registered stores | ||
| */ | ||
| getStoreCount() { | ||
| return this.stores.size; | ||
| } | ||
| /** | ||
| * Iterate over all stores | ||
| */ | ||
| forEach(callback) { | ||
| this.stores.forEach((store, name) => { | ||
| callback(store, name); | ||
| }); | ||
| } | ||
| /** | ||
| * Get registry statistics | ||
| */ | ||
| getStats() { | ||
| return { | ||
| totalStores: this.stores.size, | ||
| storeNames: this.getStoreNames(), | ||
| registryName: this.name | ||
| }; | ||
| } | ||
| /** | ||
| * Update internal snapshot | ||
| */ | ||
| _updateSnapshot() { | ||
| this._snapshot = Array.from(this.stores.entries()); | ||
| } | ||
| /** | ||
| * Notify all listeners of registry changes | ||
| */ | ||
| _notifyListeners() { | ||
| this.listeners.forEach((listener) => { | ||
| try { | ||
| listener(); | ||
| } catch (error) { | ||
| console.error("Error in registry listener:", error); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Global default registry instance | ||
| */ | ||
| const globalStoreRegistry = new StoreRegistry("global"); | ||
| //#endregion | ||
| //#region src/stores/utils/type-guards.ts | ||
| function isRefState(value) { | ||
| return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean"; | ||
| } | ||
| /** | ||
| * DOM Event 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMEvent(value) { | ||
| return value instanceof Event; | ||
| } | ||
| /** | ||
| * Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체) | ||
| */ | ||
| function isEventLike(value) { | ||
| return typeof value === "object" && value !== null && typeof value.preventDefault === "function"; | ||
| } | ||
| /** | ||
| * target 프로퍼티를 가진 객체인지 확인하는 타입 가드 | ||
| */ | ||
| function hasTargetProperty(value) { | ||
| return typeof value === "object" && value !== null && "target" in value; | ||
| } | ||
| /** | ||
| * DOM Element인지 확인하는 타입 가드 | ||
| */ | ||
| function isDOMElement(value) { | ||
| return value instanceof Element; | ||
| } | ||
| /** | ||
| * 객체인지 확인하는 타입 가드 (null 제외) | ||
| */ | ||
| function isObject(value) { | ||
| return typeof value === "object" && value !== null && !Array.isArray(value); | ||
| } | ||
| /** | ||
| * 복합 타입 가드: Event 객체로 의심되는 객체인지 확인 | ||
| * RefState가 아니면서 Event 관련 속성을 가진 객체를 감지 | ||
| */ | ||
| function isSuspiciousEventObject(value, checkNested = true) { | ||
| if (!isObject(value) || isRefState(value)) return false; | ||
| if (isEventLikeObject(value)) return true; | ||
| if (checkNested) { | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const nestedValue = value[key]; | ||
| if (isEventLikeObject(nestedValue)) return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * 단일 객체가 이벤트와 같은지 확인 | ||
| */ | ||
| function isEventLikeObject(value) { | ||
| if (!isObject(value)) return false; | ||
| const hasEventTarget = hasTargetProperty(value); | ||
| const hasPreventDefault = isEventLike(value); | ||
| const isEvent = isDOMEvent(value); | ||
| const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault); | ||
| const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value; | ||
| const constructorName = value?.constructor?.name; | ||
| const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false; | ||
| return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor; | ||
| } | ||
| /** | ||
| * 문제가 될 수 있는 속성들을 찾아내는 함수 | ||
| */ | ||
| function findProblematicProperties(value) { | ||
| if (!isObject(value)) return []; | ||
| const problematicKeys = []; | ||
| for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) { | ||
| const prop = value[key]; | ||
| if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key); | ||
| } | ||
| return problematicKeys; | ||
| } | ||
| /** | ||
| * 통합 타입 가드 객체 | ||
| * 모든 타입 가드 함수들을 하나의 객체로 export | ||
| */ | ||
| const TypeGuards = { | ||
| isRefState, | ||
| isDOMEvent, | ||
| isEventLike, | ||
| hasTargetProperty, | ||
| isDOMElement, | ||
| isObject, | ||
| isSuspiciousEventObject, | ||
| findProblematicProperties | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/core/Store.ts | ||
| /** | ||
| * Core Store class for centralized state management with memory leak prevention | ||
| * | ||
| * Provides reactive state management with subscription capabilities, optimized for | ||
| * React integration through useSyncExternalStore. Features advanced cleanup mechanisms, | ||
| * automatic resource management, and comprehensive memory leak prevention. | ||
| * | ||
| * Key Features: | ||
| * - Automatic cleanup task registration and execution | ||
| * - Memory leak prevention with disposal patterns | ||
| * - Race condition protection for async operations | ||
| * - Advanced error recovery with exponential backoff | ||
| * - Resource monitoring and threshold management | ||
| * | ||
| * @template T - The type of value stored in this store | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const userStore = createStore('user', { name: '', age: 0 }); | ||
| * | ||
| * // Register cleanup tasks | ||
| * const unregister = userStore.registerCleanup(() => { | ||
| * console.log('Cleaning up user store resources'); | ||
| * }); | ||
| * | ||
| * // Automatic cleanup on disposal | ||
| * userStore.dispose(); | ||
| * ``` | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * @public | ||
| */ | ||
| var Store = class { | ||
| constructor(name, initialValue) { | ||
| this.listeners = /* @__PURE__ */ new Set(); | ||
| this._lastClonedValue = null; | ||
| this._lastClonedVersion = 0; | ||
| this._version = 0; | ||
| this.isUpdating = false; | ||
| this.updateQueue = []; | ||
| this.notificationMode = "batched"; | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| this.pendingUpdatesCount = 0; | ||
| this.cleanupTasks = /* @__PURE__ */ new Set(); | ||
| this.isDisposed = false; | ||
| this.errorCount = 0; | ||
| this.lastErrorTime = 0; | ||
| this.MAX_ERROR_COUNT = 5; | ||
| this.ERROR_RESET_TIME = 6e4; | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.cloningEnabled = true; | ||
| this.subscribe = (listener) => { | ||
| if (this.isDisposed) { | ||
| console.warn(`Cannot subscribe to disposed store "${this.name}"`); | ||
| return () => {}; | ||
| } | ||
| const enhancedListener = () => { | ||
| if (this.isDisposed) return; | ||
| try { | ||
| listener(); | ||
| if (this.errorCount > 0) this.errorCount = 0; | ||
| } catch (error) { | ||
| this._handleListenerError(error, listener); | ||
| } | ||
| }; | ||
| this.subscriptionRegistry.set(listener, { | ||
| subscribedAt: Date.now(), | ||
| errorCount: 0, | ||
| enhancedListener | ||
| }); | ||
| this.listeners.add(enhancedListener); | ||
| return () => { | ||
| this.listeners.delete(enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| }; | ||
| }; | ||
| this.getSnapshot = () => { | ||
| return this._snapshot; | ||
| }; | ||
| this.name = name; | ||
| this._value = initialValue; | ||
| this._snapshot = this._createSnapshot(); | ||
| } | ||
| /** | ||
| * 현재 값 직접 가져오기 (액션 핸들러용) | ||
| * 핵심 로직: 불변성을 보장하는 깊은 복사본 반환 | ||
| * | ||
| * @implements lazy-evaluation | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 사용 시나리오: Action handler에서 최신 상태 읽기 | ||
| * 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨 | ||
| */ | ||
| getValue() { | ||
| if (typeof this._value !== "object" || this._value === null) return this._value; | ||
| if (this.cloningEnabled) { | ||
| if (this._lastClonedVersion === this._version && this._lastClonedValue !== null) return this._lastClonedValue; | ||
| this._lastClonedValue = safeGet(this._value, this.cloningEnabled); | ||
| this._lastClonedVersion = this._version; | ||
| return this._lastClonedValue; | ||
| } | ||
| return this._value; | ||
| } | ||
| /** | ||
| * Store 값 설정 및 구독자 알림 | ||
| * 핵심 로직: | ||
| * 1. 입력값의 불변성 보장을 위한 깊은 복사 (선택적 skip 가능) | ||
| * 2. 강화된 값 비교 시스템으로 불필요한 리렌더링 방지 | ||
| * 3. Structural sharing을 통한 성능 최적화 | ||
| * 4. 값 변경 시에만 스냅샷 재생성 및 알림 | ||
| * | ||
| * @implements unidirectional-data-flow | ||
| * @implements store-immutability | ||
| * @memberof architecture-terms | ||
| * | ||
| * 보안 강화: 입력값을 복사하여 Store 내부 상태가 외부 참조에 의해 변경되지 않도록 보호 | ||
| * 성능 강화: 다층 비교 시스템으로 정확한 변경 감지 및 렌더링 최적화 | ||
| */ | ||
| setValue(value, options) { | ||
| if (TypeGuards.isObject(value)) { | ||
| if (!TypeGuards.isRefState(value) && TypeGuards.isSuspiciousEventObject(value)) { | ||
| const eventHandling = options?.eventHandling || "block"; | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(value); | ||
| const hasPreventDefault = TypeGuards.isEventLike(value); | ||
| const isEvent = TypeGuards.isDOMEvent(value); | ||
| switch (eventHandling) { | ||
| case "allow": break; | ||
| case "transform": | ||
| if (options?.eventTransform) try { | ||
| value = options.eventTransform(value); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Event transformation failed in Store.setValue", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| error: error instanceof Error ? error.message : String(error) | ||
| }); | ||
| return; | ||
| } | ||
| else { | ||
| ErrorHandlers.store("Event transformation requested but no transform function provided", { | ||
| storeName: this.name, | ||
| valueType: typeof value | ||
| }); | ||
| return; | ||
| } | ||
| break; | ||
| case "block": | ||
| default: | ||
| ErrorHandlers.store("Event object detected in Store.setValue - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| valueType: typeof value, | ||
| constructorName: value?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(value) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| const safeValue = options?.skipClone ? value : safeSet(value, this.cloningEnabled); | ||
| let hasChanged = true; | ||
| if (!options?.skipComparison) hasChanged = this._compareValues(this._value, safeValue); | ||
| if (hasChanged) { | ||
| this._value = safeValue; | ||
| this._version++; | ||
| this._snapshot = this._createSnapshot(); | ||
| this._scheduleNotification(); | ||
| } | ||
| } | ||
| /** | ||
| * Update value using updater function with Immer integration | ||
| * 핵심 로직: | ||
| * 1. Immer produce를 사용하여 draft 객체 제공 | ||
| * 2. updater 결과를 불변성을 보장하며 설정 | ||
| * | ||
| * @implements store-immutability | ||
| * 보안 강화: Immer draft를 통한 안전한 상태 수정 | ||
| */ | ||
| update(updater) { | ||
| if (this.isUpdating) { | ||
| this.updateQueue.push(() => this.update(updater)); | ||
| return; | ||
| } | ||
| try { | ||
| this.isUpdating = true; | ||
| let updatedValue; | ||
| try { | ||
| updatedValue = produce(this._value, (draft) => { | ||
| const result = updater(draft); | ||
| return result !== void 0 ? result : draft; | ||
| }); | ||
| } catch (immerError) { | ||
| console.warn("[Store] Immer update failed, falling back to safe copy method", immerError); | ||
| const safeCurrentValue = safeGet(this._value, this.cloningEnabled); | ||
| try { | ||
| updatedValue = produce(safeCurrentValue, (draft) => { | ||
| const result = updater(draft); | ||
| return result !== void 0 ? result : draft; | ||
| }); | ||
| } catch (secondImmerError) { | ||
| console.warn("[Store] Immer completely failed, using direct update (immutability not guaranteed)", secondImmerError); | ||
| updatedValue = updater(safeCurrentValue); | ||
| } | ||
| } | ||
| if (TypeGuards.isObject(updatedValue)) { | ||
| if (!TypeGuards.isRefState(updatedValue) && TypeGuards.isSuspiciousEventObject(updatedValue)) { | ||
| const hasEventTarget = TypeGuards.hasTargetProperty(updatedValue); | ||
| const hasPreventDefault = TypeGuards.isEventLike(updatedValue); | ||
| const isEvent = TypeGuards.isDOMEvent(updatedValue); | ||
| ErrorHandlers.store("Event object detected in Store.update result - this may cause memory leaks", { | ||
| storeName: this.name, | ||
| updatedValueType: typeof updatedValue, | ||
| constructorName: updatedValue?.constructor?.name, | ||
| isEvent, | ||
| hasTargetProperty: hasEventTarget, | ||
| hasPreventDefault, | ||
| problematicProperties: TypeGuards.findProblematicProperties(updatedValue) | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| this.setValue(updatedValue); | ||
| } finally { | ||
| this.isUpdating = false; | ||
| if (this.updateQueue.length > 0) { | ||
| const nextUpdate = this.updateQueue.shift(); | ||
| if (nextUpdate) Promise.resolve().then(nextUpdate); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Get number of active listeners | ||
| */ | ||
| getListenerCount() { | ||
| return this.listeners.size; | ||
| } | ||
| /** | ||
| * Clear all listeners | ||
| */ | ||
| clearListeners() { | ||
| this.listeners.clear(); | ||
| } | ||
| /** | ||
| * Register cleanup task for automatic execution on disposal | ||
| * | ||
| * Registers a cleanup function that will be automatically called when the store | ||
| * is disposed. This prevents memory leaks and ensures proper resource cleanup. | ||
| * | ||
| * @param task - Cleanup function to register | ||
| * @returns Unregister function to remove the cleanup task | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const timer = setInterval(() => {}, 1000); | ||
| * const unregister = store.registerCleanup(() => clearInterval(timer)); | ||
| * | ||
| * // Later, remove the cleanup task if needed | ||
| * unregister(); | ||
| * ``` | ||
| */ | ||
| registerCleanup(task) { | ||
| if (this.isDisposed) { | ||
| console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`); | ||
| return () => {}; | ||
| } | ||
| this.cleanupTasks.add(task); | ||
| return () => this.cleanupTasks.delete(task); | ||
| } | ||
| /** | ||
| * Enhanced Store disposal with comprehensive cleanup | ||
| * | ||
| * Performs complete cleanup of all store resources including listeners, | ||
| * timers, cleanup tasks, and internal state. Prevents memory leaks and | ||
| * ensures proper resource disposal. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Manual disposal | ||
| * store.dispose(); | ||
| * | ||
| * // Auto-disposal with useEffect | ||
| * useEffect(() => { | ||
| * return () => store.dispose(); | ||
| * }, [store]); | ||
| * ``` | ||
| */ | ||
| dispose() { | ||
| if (this.isDisposed) return; | ||
| this.isDisposed = true; | ||
| try { | ||
| this.cleanupTasks.forEach((task) => { | ||
| try { | ||
| task(); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error during cleanup task execution", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| }); | ||
| this.cleanupTasks.clear(); | ||
| this.subscriptionRegistry = /* @__PURE__ */ new WeakMap(); | ||
| this.clearListeners(); | ||
| if (this.animationFrameId !== null) { | ||
| cancelAnimationFrame(this.animationFrameId); | ||
| this.animationFrameId = null; | ||
| } | ||
| this.pendingNotification = false; | ||
| this.updateQueue.length = 0; | ||
| } catch (error) { | ||
| ErrorHandlers.store("Critical error during store disposal", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| } | ||
| } | ||
| /** | ||
| * Check if store is disposed | ||
| * @returns true if store has been disposed | ||
| */ | ||
| isStoreDisposed() { | ||
| return this.isDisposed; | ||
| } | ||
| /** | ||
| * Store별 커스텀 비교 함수 설정 | ||
| * 이 Store에만 적용되는 특별한 비교 로직 설정 | ||
| * | ||
| * @param comparator - 커스텀 비교 함수 (oldValue, newValue) => boolean | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setCustomComparator(comparator) { | ||
| this.customComparator = comparator; | ||
| } | ||
| /** | ||
| * Store별 비교 옵션 설정 | ||
| * 이 Store에만 적용되는 비교 전략 설정 | ||
| * | ||
| * @param options - 비교 옵션 | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config | ||
| */ | ||
| setComparisonOptions(options) { | ||
| this.comparisonOptions = options; | ||
| } | ||
| /** | ||
| * 성능 최적화: Store별 복사 동작 제어 | ||
| * | ||
| * @param enabled - true: 복사 활성화 (안전), false: 복사 비활성화 (성능 우선) | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/performance | ||
| */ | ||
| setCloningEnabled(enabled) { | ||
| this.cloningEnabled = enabled; | ||
| } | ||
| /** | ||
| * 현재 복사 설정 조회 | ||
| */ | ||
| isCloningEnabled() { | ||
| return this.cloningEnabled; | ||
| } | ||
| /** | ||
| * 강화된 값 비교 시스템 | ||
| * 1. 커스텀 비교 함수 우선 사용 | ||
| * 2. Store별 비교 옵션 적용 | ||
| * 3. 성능 최적화된 빠른 비교 fallback | ||
| * 4. 전역 비교 설정 사용 | ||
| * | ||
| * @param oldValue - 이전 값 | ||
| * @param newValue - 새로운 값 | ||
| * @returns true if values are different (change detected), false if same | ||
| * @protected | ||
| */ | ||
| _compareValues(oldValue, newValue) { | ||
| let result; | ||
| try { | ||
| if (this.customComparator) result = !this.customComparator(oldValue, newValue); | ||
| else if (this.comparisonOptions) result = !compareValues(oldValue, newValue, this.comparisonOptions); | ||
| else result = !compareValues(oldValue, newValue, { strategy: "reference" }); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error during value comparison, falling back to reference comparison", { storeName: this.name }, error instanceof Error ? error : void 0); | ||
| result = !Object.is(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| _createSnapshot() { | ||
| return { | ||
| value: safeGet(this._value, this.cloningEnabled), | ||
| name: this.name, | ||
| lastUpdate: Date.now() | ||
| }; | ||
| } | ||
| /** | ||
| * requestAnimationFrame 기반 알림 스케줄링 | ||
| * 브라우저의 다음 프레임에서 리스너 알림 실행 | ||
| */ | ||
| _scheduleNotification() { | ||
| if (this.notificationMode === "immediate") this._notifyListeners(); | ||
| else this._scheduleWithRAF(); | ||
| } | ||
| /** | ||
| * requestAnimationFrame을 사용한 알림 스케줄링 | ||
| * 누적 가능한 배치 시스템으로 개선 | ||
| */ | ||
| _scheduleWithRAF() { | ||
| this.pendingUpdatesCount++; | ||
| if (!this.pendingNotification) { | ||
| this.pendingNotification = true; | ||
| this.animationFrameId = requestAnimationFrame(() => { | ||
| this._executeNotification(); | ||
| }); | ||
| } | ||
| } | ||
| /** | ||
| * 스케줄된 알림 실행 | ||
| */ | ||
| _executeNotification() { | ||
| this.pendingNotification = false; | ||
| this.animationFrameId = null; | ||
| const batchedUpdates = this.pendingUpdatesCount; | ||
| this.pendingUpdatesCount = 0; | ||
| this._notifyListeners(); | ||
| if (batchedUpdates > 1) console.debug(`[Store:${this.name}] Batched ${batchedUpdates} updates in single frame`); | ||
| } | ||
| /** | ||
| * Handle listener execution errors with recovery strategies | ||
| */ | ||
| _handleListenerError(error, listener) { | ||
| const now = Date.now(); | ||
| if (now - this.lastErrorTime > this.ERROR_RESET_TIME) this.errorCount = 0; | ||
| this.errorCount++; | ||
| this.lastErrorTime = now; | ||
| const metadata = this.subscriptionRegistry.get(listener); | ||
| if (metadata) metadata.errorCount++; | ||
| ErrorHandlers.store("Error in store listener execution", { | ||
| storeName: this.name, | ||
| listenerCount: this.listeners.size, | ||
| errorCount: this.errorCount, | ||
| subscriptionAge: metadata ? now - metadata.subscribedAt : "unknown" | ||
| }, error instanceof Error ? error : void 0); | ||
| if (metadata && metadata.errorCount >= 3) { | ||
| console.warn(`Removing problematic listener from store "${this.name}" after ${metadata.errorCount} errors`); | ||
| this.listeners.delete(metadata.enhancedListener); | ||
| this.subscriptionRegistry.delete(listener); | ||
| } | ||
| if (this.errorCount >= this.MAX_ERROR_COUNT) { | ||
| console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`); | ||
| this.clearListeners(); | ||
| } | ||
| } | ||
| _notifyListeners() { | ||
| if (this.isDisposed) return; | ||
| this.listeners.forEach((listener) => { | ||
| if (this.isDisposed) return; | ||
| listener(); | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Factory function for creating type-safe Store instances | ||
| * | ||
| * Creates a new Store instance with the specified name and initial value. | ||
| * Provides type safety and integrates seamlessly with React hooks and | ||
| * the Context-Action framework patterns. | ||
| * | ||
| * @template T - The type of values stored in this store | ||
| * | ||
| * @param name - Unique identifier for the store (used for debugging) | ||
| * @param initialValue - Initial value to store | ||
| * | ||
| * @returns Configured Store instance ready for use | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function createStore(name, initialValue) { | ||
| return new Store(name, initialValue); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/sync-external-store-utils.ts | ||
| /** | ||
| * 향상된 구독 함수 생성 (내부 사용) | ||
| * 디바운싱, 스로틀링, 조건부 구독 기능 제공 | ||
| */ | ||
| function createEnhancedSubscriber(store, options = {}) { | ||
| const { debounce, throttle, condition, debug, name = "unknown" } = options; | ||
| return (callback) => { | ||
| if (!store) return () => {}; | ||
| let debounceTimer = null; | ||
| let throttleTimer = null; | ||
| let lastThrottleTime = 0; | ||
| const enhancedCallback = () => { | ||
| if (condition && !condition()) { | ||
| if (debug) console.debug(`[${name}] Subscription suspended due to condition`); | ||
| return; | ||
| } | ||
| const now = performance.now(); | ||
| if (throttle && throttle > 0) { | ||
| if (now - lastThrottleTime < throttle) { | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| throttleTimer = setTimeout(() => { | ||
| lastThrottleTime = performance.now(); | ||
| callback(); | ||
| }, throttle - (now - lastThrottleTime)); | ||
| return; | ||
| } | ||
| lastThrottleTime = now; | ||
| } | ||
| if (debounce && debounce > 0) { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| debounceTimer = setTimeout(() => { | ||
| callback(); | ||
| if (debug) console.debug(`[${name}] Debounced callback executed after ${debounce}ms`); | ||
| }, debounce); | ||
| return; | ||
| } | ||
| callback(); | ||
| }; | ||
| const unsubscribe = store.subscribe(enhancedCallback); | ||
| return () => { | ||
| if (debounceTimer) clearTimeout(debounceTimer); | ||
| if (throttleTimer) clearTimeout(throttleTimer); | ||
| unsubscribe(); | ||
| }; | ||
| }; | ||
| } | ||
| /** | ||
| * Null-safe Store 구독 훅 | ||
| * useSyncExternalStore를 기반으로 한 안전한 구독 | ||
| */ | ||
| function useSafeStoreSubscription(store, selector, options = {}) { | ||
| const { initialValue, equalityFn, debounce, throttle, condition, debug, name } = options; | ||
| const stableSubscriptionOptions = useMemo(() => ({ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| }), [ | ||
| debounce, | ||
| throttle, | ||
| condition, | ||
| debug, | ||
| name | ||
| ]); | ||
| const needsEnhancedSubscription = Boolean(debounce || throttle || condition); | ||
| const subscribe = useCallback((callback) => { | ||
| if (!store) return () => {}; | ||
| if (needsEnhancedSubscription) return createEnhancedSubscriber(store, stableSubscriptionOptions)(callback); | ||
| return store.subscribe(callback); | ||
| }, [ | ||
| store, | ||
| needsEnhancedSubscription, | ||
| stableSubscriptionOptions | ||
| ]); | ||
| const getSnapshot = useCallback(() => { | ||
| if (!store) return initialValue; | ||
| const snapshot = store.getSnapshot(); | ||
| return selector ? selector(snapshot.value) : snapshot.value; | ||
| }, [ | ||
| store, | ||
| selector, | ||
| initialValue | ||
| ]); | ||
| const cachedSnapshotRef = useRef(); | ||
| const stableGetSnapshot = useCallback(() => { | ||
| const currentSnapshot = getSnapshot(); | ||
| if (equalityFn && cachedSnapshotRef.current !== void 0) { | ||
| if (equalityFn(cachedSnapshotRef.current, currentSnapshot)) return cachedSnapshotRef.current; | ||
| } | ||
| cachedSnapshotRef.current = currentSnapshot; | ||
| return currentSnapshot; | ||
| }, [getSnapshot, equalityFn]); | ||
| const getServerSnapshot = useCallback(() => { | ||
| return initialValue; | ||
| }, [initialValue]); | ||
| return useSyncExternalStore(subscribe, equalityFn ? stableGetSnapshot : getSnapshot, getServerSnapshot); | ||
| } | ||
| /** | ||
| * 기본 동등성 비교 함수들 | ||
| */ | ||
| const equalityFunctions = { | ||
| reference: (a, b) => Object.is(a, b), | ||
| shallow: (a, b) => { | ||
| if (Object.is(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| const keysA = Object.keys(a); | ||
| const keysB = Object.keys(b); | ||
| if (keysA.length !== keysB.length) return false; | ||
| for (const key of keysA) if (!Object.prototype.hasOwnProperty.call(b, key) || !Object.is(a[key], b[key])) return false; | ||
| return true; | ||
| }, | ||
| deep: (a, b) => { | ||
| if (Object.is(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| if (Array.isArray(a) !== Array.isArray(b)) return false; | ||
| const keysA = Object.keys(a); | ||
| const keysB = Object.keys(b); | ||
| if (keysA.length !== keysB.length) return false; | ||
| for (const key of keysA) { | ||
| if (!Object.prototype.hasOwnProperty.call(b, key)) return false; | ||
| if (!equalityFunctions.deep(a[key], b[key])) return false; | ||
| } | ||
| return true; | ||
| }, | ||
| smart: (a, b) => { | ||
| if (Object.is(a, b)) return true; | ||
| if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false; | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| return a.every((item, index) => { | ||
| const bItem = b[index]; | ||
| if (typeof item === "object" && item !== null && typeof bItem === "object" && bItem !== null) return equalityFunctions.shallow(item, bItem); | ||
| return Object.is(item, bItem); | ||
| }); | ||
| } | ||
| return equalityFunctions.shallow(a, b); | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/hooks/useStoreSelector.ts | ||
| const defaultEqualityFn = equalityFunctions.smart; | ||
| const shallowEqual = equalityFunctions.shallow; | ||
| const deepEqual = equalityFunctions.deep; | ||
| const smartEqual = equalityFunctions.smart; | ||
| /** | ||
| * Hook for selective store subscription with performance optimization | ||
| * | ||
| * Subscribes to specific parts of store data using a selector function, | ||
| * triggering re-renders only when the selected value actually changes. | ||
| * Essential for preventing unnecessary re-renders in complex applications. | ||
| * | ||
| * @template T - Type of the store value | ||
| * @template R - Type of the value returned by the selector | ||
| * | ||
| * @param store - Store instance to subscribe to | ||
| * @param selector - Function to extract needed data from store value | ||
| * @param equalityFn - Function to compare previous and new values (default: Object.is) | ||
| * | ||
| * @returns The value returned by the selector function | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usestoreselector-advanced-usage | ||
| * | ||
| * @public | ||
| */ | ||
| function useStoreSelector(store, selector, equalityFn = defaultEqualityFn) { | ||
| "use memo"; | ||
| const stableSelector = useCallback(selector, [selector]); | ||
| const stableEqualityFn = useCallback(equalityFn, [equalityFn]); | ||
| const selectorWarningShownRef = useRef(false); | ||
| if (selector !== stableSelector && !selectorWarningShownRef.current) { | ||
| console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name); | ||
| selectorWarningShownRef.current = true; | ||
| } | ||
| const previousValueRef = useRef(); | ||
| const subscribe = useCallback((callback) => { | ||
| return store.subscribe(callback); | ||
| }, [store]); | ||
| const getSnapshot = useCallback(() => { | ||
| try { | ||
| const selectedValue = stableSelector(store.getValue()); | ||
| if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current; | ||
| previousValueRef.current = selectedValue; | ||
| return selectedValue; | ||
| } catch (error) { | ||
| console.error("useStoreSelector: Error in selector function:", error); | ||
| throw error; | ||
| } | ||
| }, [ | ||
| store, | ||
| stableSelector, | ||
| stableEqualityFn | ||
| ]); | ||
| return useSyncExternalStore(subscribe, getSnapshot, getSnapshot); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.tsx | ||
| /** | ||
| * Store 시스템을 위한 에러 경계 컴포넌트 | ||
| * | ||
| * Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다. | ||
| * 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는 | ||
| * 사용자 친화적인 메시지를 보여줍니다. | ||
| */ | ||
| var StoreErrorBoundary = class extends Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.resetTimeoutId = null; | ||
| this.resetErrorBoundary = () => { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| this.setState({ | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }); | ||
| }; | ||
| this.state = { | ||
| hasError: false, | ||
| error: null, | ||
| errorInfo: null, | ||
| errorId: null | ||
| }; | ||
| } | ||
| static getDerivedStateFromError(error) { | ||
| return { | ||
| hasError: true, | ||
| error: error instanceof Error && error.name === "ContextActionError" ? error : null, | ||
| errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` | ||
| }; | ||
| } | ||
| componentDidCatch(error, errorInfo) { | ||
| if (error.name === "ContextActionError") { | ||
| const contextActionError = error; | ||
| this.setState({ errorInfo }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } else { | ||
| const contextActionError = ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, { | ||
| component: "StoreErrorBoundary", | ||
| stack: error.stack, | ||
| componentStack: errorInfo.componentStack | ||
| }, error); | ||
| this.setState({ | ||
| error: contextActionError, | ||
| errorInfo | ||
| }); | ||
| this.props.onError?.(contextActionError, errorInfo); | ||
| } | ||
| } | ||
| componentDidUpdate(prevProps) { | ||
| const { hasError } = this.state; | ||
| const { resetOnPropsChange, resetKeys } = this.props; | ||
| if (hasError && resetOnPropsChange) { | ||
| if (resetKeys) { | ||
| if (resetKeys.some((key) => { | ||
| return prevProps[key] !== this.props[key]; | ||
| })) this.resetErrorBoundary(); | ||
| } else if (prevProps !== this.props) this.resetErrorBoundary(); | ||
| } | ||
| } | ||
| componentWillUnmount() { | ||
| if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId); | ||
| } | ||
| render() { | ||
| const { hasError, error, errorInfo } = this.state; | ||
| const { children, fallback } = this.props; | ||
| if (hasError) { | ||
| if (fallback) { | ||
| if (typeof fallback === "function") return fallback(error, errorInfo); | ||
| return fallback; | ||
| } | ||
| return this.renderDefaultFallback(); | ||
| } | ||
| return children; | ||
| } | ||
| renderDefaultFallback() { | ||
| return this.renderDevelopmentFallback(); | ||
| } | ||
| renderDevelopmentFallback() { | ||
| const { error, errorInfo, errorId } = this.state; | ||
| const stats = getErrorStatistics(); | ||
| return /* @__PURE__ */ jsxs("div", { | ||
| style: { | ||
| padding: "20px", | ||
| margin: "20px", | ||
| border: "2px solid #ff6b6b", | ||
| borderRadius: "8px", | ||
| backgroundColor: "#ffe0e0", | ||
| fontFamily: "monospace" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("h2", { | ||
| style: { | ||
| color: "#d63031", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "🚨 Store Error Boundary" | ||
| }), | ||
| /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("strong", { children: "Error ID:" }), | ||
| " ", | ||
| errorId | ||
| ] | ||
| }), | ||
| error && /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("strong", { children: "Error Type:" }), | ||
| " ", | ||
| error.type, | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| /* @__PURE__ */ jsx("strong", { children: "Message:" }), | ||
| " ", | ||
| error.message, | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| /* @__PURE__ */ jsx("strong", { children: "Timestamp:" }), | ||
| " ", | ||
| new Date(error.timestamp).toISOString() | ||
| ] | ||
| }), | ||
| error?.context && /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ jsx("strong", { children: "Context:" }), /* @__PURE__ */ jsx("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "12px" | ||
| }, | ||
| children: JSON.stringify(error.context, null, 2) | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ jsxs("div", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("strong", { children: "Error Statistics:" }), | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| "Total Errors: ", | ||
| stats.totalErrors, | ||
| /* @__PURE__ */ jsx("br", {}), | ||
| "Recent Errors: ", | ||
| stats.recentErrors.length | ||
| ] | ||
| }), | ||
| errorInfo && /* @__PURE__ */ jsxs("details", { | ||
| style: { marginBottom: "15px" }, | ||
| children: [/* @__PURE__ */ jsx("summary", { | ||
| style: { | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Component Stack" | ||
| }), /* @__PURE__ */ jsx("pre", { | ||
| style: { | ||
| background: "#f8f9fa", | ||
| padding: "10px", | ||
| borderRadius: "4px", | ||
| overflow: "auto", | ||
| fontSize: "11px", | ||
| whiteSpace: "pre-wrap" | ||
| }, | ||
| children: errorInfo.componentStack | ||
| })] | ||
| }), | ||
| /* @__PURE__ */ jsx("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#00b894", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer", | ||
| fontWeight: "bold" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| renderProductionFallback() { | ||
| return /* @__PURE__ */ jsxs("div", { | ||
| style: { | ||
| padding: "20px", | ||
| textAlign: "center", | ||
| backgroundColor: "#f8f9fa", | ||
| border: "1px solid #dee2e6", | ||
| borderRadius: "8px", | ||
| margin: "20px 0" | ||
| }, | ||
| children: [ | ||
| /* @__PURE__ */ jsx("h3", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 10px 0" | ||
| }, | ||
| children: "Something went wrong" | ||
| }), | ||
| /* @__PURE__ */ jsx("p", { | ||
| style: { | ||
| color: "#6c757d", | ||
| margin: "0 0 15px 0" | ||
| }, | ||
| children: "We're sorry, but something unexpected happened. Please try again." | ||
| }), | ||
| /* @__PURE__ */ jsx("button", { | ||
| onClick: this.resetErrorBoundary, | ||
| style: { | ||
| padding: "8px 16px", | ||
| backgroundColor: "#007bff", | ||
| color: "white", | ||
| border: "none", | ||
| borderRadius: "4px", | ||
| cursor: "pointer" | ||
| }, | ||
| children: "Try Again" | ||
| }) | ||
| ] | ||
| }); | ||
| } | ||
| }; | ||
| /** | ||
| * Enhanced HOC for automatic Store Error Boundary wrapping with security | ||
| * | ||
| * @template P - Component props type | ||
| * @param WrappedComponent - Component to wrap with error boundary | ||
| * @param errorBoundaryProps - Error boundary configuration | ||
| * @returns Enhanced component with comprehensive error handling | ||
| */ | ||
| function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) { | ||
| const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ jsx(StoreErrorBoundary, { | ||
| ...errorBoundaryProps, | ||
| children: /* @__PURE__ */ jsx(WrappedComponent, { ...props }) | ||
| }); | ||
| WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`; | ||
| return WithStoreErrorBoundaryComponent; | ||
| } | ||
| /** | ||
| * 특정 Store와 연결된 에러 경계 생성 헬퍼 | ||
| */ | ||
| function createStoreErrorBoundary(storeName, customFallback) { | ||
| return ({ children }) => /* @__PURE__ */ jsx(StoreErrorBoundary, { | ||
| fallback: customFallback, | ||
| onError: (error, errorInfo) => { | ||
| console.group(`Store Error in ${storeName}`); | ||
| console.error("Error:", error); | ||
| console.error("Component Stack:", errorInfo.componentStack); | ||
| console.groupEnd(); | ||
| }, | ||
| resetKeys: [storeName], | ||
| children | ||
| }); | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.tsx | ||
| function createActionContext(contextNameOrConfig = {}, config) { | ||
| let effectiveConfig; | ||
| let contextName; | ||
| if (typeof contextNameOrConfig === "string") { | ||
| contextName = contextNameOrConfig; | ||
| effectiveConfig = { | ||
| ...config, | ||
| name: config?.name || contextName | ||
| }; | ||
| } else { | ||
| effectiveConfig = contextNameOrConfig; | ||
| contextName = effectiveConfig.name || "ActionContext"; | ||
| } | ||
| const FactoryActionContext = createContext(null); | ||
| const Provider = ({ children }) => { | ||
| const actionRegisterRef = useRef(new ActionRegister(effectiveConfig)); | ||
| const contextValue = useMemo(() => ({ actionRegisterRef }), []); | ||
| return /* @__PURE__ */ jsx(FactoryActionContext.Provider, { | ||
| value: contextValue, | ||
| children | ||
| }); | ||
| }; | ||
| const useFactoryActionContext = () => { | ||
| const context = useContext(FactoryActionContext); | ||
| if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider"); | ||
| return context; | ||
| }; | ||
| /** | ||
| * Optimized hook to get stable dispatch functions | ||
| * | ||
| * Returns stable dispatch functions that prevent re-renders and maintain | ||
| * reference equality across component renders. | ||
| * | ||
| * @returns Object with dispatch and dispatchWithResult functions | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useActionDispatcher = () => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| return { | ||
| dispatch: useCallback((action, payload, options) => { | ||
| console.log(`React dispatch called for '${String(action)}':`, { | ||
| hasPayload: payload !== void 0, | ||
| hasOptions: options !== void 0, | ||
| timestamp: (/* @__PURE__ */ new Date()).toISOString() | ||
| }); | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]), | ||
| dispatchWithResult: useCallback((action, payload, options) => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions); | ||
| }, [actionRegisterRef]) | ||
| }; | ||
| }; | ||
| const useAction = () => { | ||
| const { dispatch } = useActionDispatcher(); | ||
| return dispatch; | ||
| }; | ||
| const useActionHandler = (action, handler, config$1) => { | ||
| const { actionRegisterRef } = useFactoryActionContext(); | ||
| const actionId = useId(); | ||
| const handlerRef = useRef(handler); | ||
| handlerRef.current = handler; | ||
| const priority = config$1?.priority ?? 0; | ||
| const id = config$1?.id || `react_${String(action)}_${actionId}`; | ||
| const blocking = config$1?.blocking ?? false; | ||
| const once = config$1?.once ?? false; | ||
| const debounce = config$1?.debounce; | ||
| const throttle = config$1?.throttle; | ||
| const stableConfig = useMemo(() => ({ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| replaceExisting: true, | ||
| ...debounce !== void 0 && { debounce }, | ||
| ...throttle !== void 0 && { throttle } | ||
| }), [ | ||
| priority, | ||
| id, | ||
| blocking, | ||
| once, | ||
| debounce, | ||
| throttle | ||
| ]); | ||
| useEffect(() => { | ||
| const register = actionRegisterRef.current; | ||
| if (!register) return; | ||
| const wrapperHandler = (payload, controller) => { | ||
| return handlerRef.current(payload, controller); | ||
| }; | ||
| console.log(`Registering handler for '${String(action)}'`); | ||
| return register.register(action, wrapperHandler, stableConfig); | ||
| }, [ | ||
| action, | ||
| actionRegisterRef, | ||
| stableConfig | ||
| ]); | ||
| }; | ||
| /** | ||
| * Hook that provides direct access to the ActionRegister instance | ||
| * | ||
| * This hook is useful when you need to: | ||
| * - Register multiple handlers dynamically | ||
| * - Access other ActionRegister methods like clearAction, getHandlers, etc. | ||
| * - Implement complex handler registration logic | ||
| * - Have more control over the registration lifecycle | ||
| * | ||
| * @returns ActionRegister instance or null if not initialized | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access | ||
| */ | ||
| const useFactoryActionRegister = () => { | ||
| return useFactoryActionContext().actionRegisterRef.current; | ||
| }; | ||
| /** | ||
| * Hook that provides access to the dispatchWithResult function | ||
| * | ||
| * This hook returns a function that dispatches actions and returns detailed | ||
| * execution results including collected handler results, execution metadata, | ||
| * and error information. | ||
| * | ||
| * @returns dispatchWithResult function with full type safety | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result | ||
| */ | ||
| const useFactoryActionDispatchWithResult = () => { | ||
| const context = useFactoryActionContext(); | ||
| const activeControllersRef = useRef(/* @__PURE__ */ new Set()); | ||
| const dispatch = useCallback((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const dispatchWithResult = useCallback((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| let createdController; | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| createdController = controller; | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions).finally(() => { | ||
| if (createdController) activeControllersRef.current.delete(createdController); | ||
| }); | ||
| }, [context.actionRegisterRef]); | ||
| const abortAll = useCallback(() => { | ||
| activeControllersRef.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| activeControllersRef.current.clear(); | ||
| }, []); | ||
| const resetAbortScope = useCallback(() => { | ||
| abortAll(); | ||
| }, [abortAll]); | ||
| useEffect(() => { | ||
| const controllers = activeControllersRef; | ||
| return () => { | ||
| controllers.current.forEach((controller) => { | ||
| if (!controller.signal.aborted) controller.abort(); | ||
| }); | ||
| controllers.current.clear(); | ||
| }; | ||
| }, []); | ||
| return { | ||
| dispatch, | ||
| dispatchWithResult, | ||
| abortAll, | ||
| resetAbortScope | ||
| }; | ||
| }; | ||
| return { | ||
| Provider, | ||
| useActionContext: useFactoryActionContext, | ||
| useActionDispatch: useAction, | ||
| useActionHandler, | ||
| useActionRegister: useFactoryActionRegister, | ||
| useActionDispatchWithResult: useFactoryActionDispatchWithResult, | ||
| context: FactoryActionContext | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { Store, StoreErrorBoundary, StoreRegistry, createActionContext, createStore, createStoreErrorBoundary, defaultEqualityFn, useSafeStoreSubscription, useStoreSelector, withStoreErrorBoundary }; | ||
| //# sourceMappingURL=ActionContext-BIIFgZEq.js.map |
Sorry, the diff of this file is too big to display
| import React$1, { Component, ErrorInfo, ReactNode } from "react"; | ||
| import { ActionHandler, ActionRegister, ActionRegisterConfig, DispatchOptions, ExecutionResult, HandlerConfig } from "@context-action/core"; | ||
| //#region src/stores/utils/error-handling.d.ts | ||
| declare enum ContextActionErrorType { | ||
| STORE_ERROR = "STORE_ERROR", | ||
| ACTION_ERROR = "ACTION_ERROR", | ||
| REF_ERROR = "REF_ERROR", | ||
| VALIDATION_ERROR = "VALIDATION_ERROR", | ||
| INITIALIZATION_ERROR = "INITIALIZATION_ERROR", | ||
| TIMEOUT_ERROR = "TIMEOUT_ERROR", | ||
| CIRCULAR_REFERENCE_ERROR = "CIRCULAR_REFERENCE_ERROR", | ||
| } | ||
| declare class ContextActionError extends Error { | ||
| readonly type: ContextActionErrorType; | ||
| readonly context: Record<string, unknown> | undefined; | ||
| readonly timestamp: number; | ||
| constructor(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error); | ||
| } | ||
| declare function handleError(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error): ContextActionError; | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.d.ts | ||
| interface StoreErrorBoundaryProps { | ||
| children: ReactNode; | ||
| fallback?: ReactNode | ((error: ContextActionError, errorInfo: ErrorInfo) => ReactNode); | ||
| onError?: (error: ContextActionError, errorInfo: ErrorInfo) => void; | ||
| resetOnPropsChange?: boolean; | ||
| resetKeys?: Array<string | number>; | ||
| } | ||
| interface StoreErrorBoundaryState { | ||
| hasError: boolean; | ||
| error: ContextActionError | null; | ||
| errorInfo: ErrorInfo | null; | ||
| errorId: string | null; | ||
| } | ||
| declare class StoreErrorBoundary extends Component<StoreErrorBoundaryProps, StoreErrorBoundaryState> { | ||
| private resetTimeoutId; | ||
| constructor(props: StoreErrorBoundaryProps); | ||
| static getDerivedStateFromError(error: Error): Partial<StoreErrorBoundaryState>; | ||
| componentDidCatch(error: Error, errorInfo: ErrorInfo): void; | ||
| componentDidUpdate(prevProps: StoreErrorBoundaryProps): void; | ||
| componentWillUnmount(): void; | ||
| resetErrorBoundary: () => void; | ||
| render(): React$1.ReactNode; | ||
| private renderDefaultFallback; | ||
| private renderDevelopmentFallback; | ||
| private renderProductionFallback; | ||
| } | ||
| declare function withStoreErrorBoundary<P extends object>(WrappedComponent: React$1.ComponentType<P>, errorBoundaryProps?: Omit<StoreErrorBoundaryProps, 'children'>): React$1.ComponentType<P>; | ||
| declare function createStoreErrorBoundary(storeName: string, customFallback?: ReactNode): React$1.ComponentType<{ | ||
| children: ReactNode; | ||
| }>; | ||
| //#endregion | ||
| //#region src/actions/ActionContext.types.d.ts | ||
| interface ActionContextConfig extends ActionRegisterConfig { | ||
| name?: string; | ||
| } | ||
| interface ActionContextType<T extends {}> { | ||
| actionRegisterRef: React.RefObject<ActionRegister<T>>; | ||
| } | ||
| interface ActionContextReturn<T extends {}> { | ||
| Provider: React.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useActionContext: () => ActionContextType<T>; | ||
| useActionDispatch: () => ActionRegister<T>['dispatch']; | ||
| useActionHandler: <K extends keyof T>(action: K, handler: ActionHandler<T[K]>, config?: HandlerConfig) => void; | ||
| useActionRegister: () => ActionRegister<T> | null; | ||
| useActionDispatchWithResult: () => { | ||
| dispatch: <K extends keyof T>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<void>; | ||
| dispatchWithResult: <K extends keyof T, R = void>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<ExecutionResult<R>>; | ||
| abortAll: () => void; | ||
| resetAbortScope: () => void; | ||
| }; | ||
| context: React.Context<ActionContextType<T> | null>; | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.d.ts | ||
| declare function createActionContext<T extends {}>(contextName: string, config?: ActionContextConfig): ActionContextReturn<T>; | ||
| declare function createActionContext<T extends {}>(config: ActionContextConfig): ActionContextReturn<T>; | ||
| //#endregion | ||
| export { ActionContextConfig, ActionContextReturn, ActionContextType, ContextActionError, ContextActionErrorType, StoreErrorBoundary, StoreErrorBoundaryProps, StoreErrorBoundaryState, createActionContext, createStoreErrorBoundary, handleError, withStoreErrorBoundary }; | ||
| //# sourceMappingURL=ActionContext-BnM5V83y.d.cts.map |
| {"version":3,"file":"ActionContext-BnM5V83y.d.cts","names":[],"sources":["../src/stores/utils/error-handling.ts","../src/stores/components/StoreErrorBoundary.tsx","../src/actions/ActionContext.types.ts","../src/actions/ActionContext.tsx"],"sourcesContent":[],"mappings":"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"} |
| import React$1, { Component, ErrorInfo, ReactNode } from "react"; | ||
| import { ActionHandler, ActionRegister, ActionRegisterConfig, DispatchOptions, ExecutionResult, HandlerConfig } from "@context-action/core"; | ||
| //#region src/stores/utils/error-handling.d.ts | ||
| declare enum ContextActionErrorType { | ||
| STORE_ERROR = "STORE_ERROR", | ||
| ACTION_ERROR = "ACTION_ERROR", | ||
| REF_ERROR = "REF_ERROR", | ||
| VALIDATION_ERROR = "VALIDATION_ERROR", | ||
| INITIALIZATION_ERROR = "INITIALIZATION_ERROR", | ||
| TIMEOUT_ERROR = "TIMEOUT_ERROR", | ||
| CIRCULAR_REFERENCE_ERROR = "CIRCULAR_REFERENCE_ERROR", | ||
| } | ||
| declare class ContextActionError extends Error { | ||
| readonly type: ContextActionErrorType; | ||
| readonly context: Record<string, unknown> | undefined; | ||
| readonly timestamp: number; | ||
| constructor(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error); | ||
| } | ||
| declare function handleError(type: ContextActionErrorType, message: string, context?: Record<string, unknown>, originalError?: Error): ContextActionError; | ||
| //#endregion | ||
| //#region src/stores/components/StoreErrorBoundary.d.ts | ||
| interface StoreErrorBoundaryProps { | ||
| children: ReactNode; | ||
| fallback?: ReactNode | ((error: ContextActionError, errorInfo: ErrorInfo) => ReactNode); | ||
| onError?: (error: ContextActionError, errorInfo: ErrorInfo) => void; | ||
| resetOnPropsChange?: boolean; | ||
| resetKeys?: Array<string | number>; | ||
| } | ||
| interface StoreErrorBoundaryState { | ||
| hasError: boolean; | ||
| error: ContextActionError | null; | ||
| errorInfo: ErrorInfo | null; | ||
| errorId: string | null; | ||
| } | ||
| declare class StoreErrorBoundary extends Component<StoreErrorBoundaryProps, StoreErrorBoundaryState> { | ||
| private resetTimeoutId; | ||
| constructor(props: StoreErrorBoundaryProps); | ||
| static getDerivedStateFromError(error: Error): Partial<StoreErrorBoundaryState>; | ||
| componentDidCatch(error: Error, errorInfo: ErrorInfo): void; | ||
| componentDidUpdate(prevProps: StoreErrorBoundaryProps): void; | ||
| componentWillUnmount(): void; | ||
| resetErrorBoundary: () => void; | ||
| render(): React$1.ReactNode; | ||
| private renderDefaultFallback; | ||
| private renderDevelopmentFallback; | ||
| private renderProductionFallback; | ||
| } | ||
| declare function withStoreErrorBoundary<P extends object>(WrappedComponent: React$1.ComponentType<P>, errorBoundaryProps?: Omit<StoreErrorBoundaryProps, 'children'>): React$1.ComponentType<P>; | ||
| declare function createStoreErrorBoundary(storeName: string, customFallback?: ReactNode): React$1.ComponentType<{ | ||
| children: ReactNode; | ||
| }>; | ||
| //#endregion | ||
| //#region src/actions/ActionContext.types.d.ts | ||
| interface ActionContextConfig extends ActionRegisterConfig { | ||
| name?: string; | ||
| } | ||
| interface ActionContextType<T extends {}> { | ||
| actionRegisterRef: React.RefObject<ActionRegister<T>>; | ||
| } | ||
| interface ActionContextReturn<T extends {}> { | ||
| Provider: React.FC<{ | ||
| children: ReactNode; | ||
| }>; | ||
| useActionContext: () => ActionContextType<T>; | ||
| useActionDispatch: () => ActionRegister<T>['dispatch']; | ||
| useActionHandler: <K extends keyof T>(action: K, handler: ActionHandler<T[K]>, config?: HandlerConfig) => void; | ||
| useActionRegister: () => ActionRegister<T> | null; | ||
| useActionDispatchWithResult: () => { | ||
| dispatch: <K extends keyof T>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<void>; | ||
| dispatchWithResult: <K extends keyof T, R = void>(action: K, payload?: T[K], options?: DispatchOptions) => Promise<ExecutionResult<R>>; | ||
| abortAll: () => void; | ||
| resetAbortScope: () => void; | ||
| }; | ||
| context: React.Context<ActionContextType<T> | null>; | ||
| } | ||
| //#endregion | ||
| //#region src/actions/ActionContext.d.ts | ||
| declare function createActionContext<T extends {}>(contextName: string, config?: ActionContextConfig): ActionContextReturn<T>; | ||
| declare function createActionContext<T extends {}>(config: ActionContextConfig): ActionContextReturn<T>; | ||
| //#endregion | ||
| export { ActionContextConfig, ActionContextReturn, ActionContextType, ContextActionError, ContextActionErrorType, StoreErrorBoundary, StoreErrorBoundaryProps, StoreErrorBoundaryState, createActionContext, createStoreErrorBoundary, handleError, withStoreErrorBoundary }; | ||
| //# sourceMappingURL=ActionContext-Cq5LNd0Y.d.ts.map |
| {"version":3,"file":"ActionContext-Cq5LNd0Y.d.ts","names":[],"sources":["../src/stores/utils/error-handling.ts","../src/stores/components/StoreErrorBoundary.tsx","../src/actions/ActionContext.types.ts","../src/actions/ActionContext.tsx"],"sourcesContent":[],"mappings":"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"} |
| import { current, enableMapSet, isDraft, original, produce } from "immer"; | ||
| //#region src/stores/utils/immutable.ts | ||
| enableMapSet(); | ||
| /** | ||
| * Check if value is a primitive type | ||
| */ | ||
| function isPrimitive(value) { | ||
| return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "symbol"; | ||
| } | ||
| /** | ||
| * Check if value is a complex object that needs Immer | ||
| */ | ||
| function isComplexObject(value) { | ||
| if (!value || typeof value !== "object") return false; | ||
| if (Array.isArray(value)) return true; | ||
| if (value.constructor === Object) { | ||
| const obj = value; | ||
| return Object.values(obj).some((val) => typeof val === "object" && val !== null); | ||
| } | ||
| return value.constructor !== Object; | ||
| } | ||
| const logger = { | ||
| warn: (message, ...args) => console.warn(`[Context-Action] ${message}`, ...args), | ||
| trace: (message, ...args) => console.trace(`[Context-Action] ${message}`, ...args), | ||
| error: (message, ...args) => console.error(`[Context-Action] ${message}`, ...args), | ||
| debug: (message, ...args) => console.debug(`[Context-Action] ${message}`, ...args) | ||
| }; | ||
| /** | ||
| * 전역 불변성 설정 | ||
| */ | ||
| let globalImmutabilityOptions = { | ||
| enableCloning: true, | ||
| enableVerification: true, | ||
| warnOnFallback: true | ||
| }; | ||
| /** | ||
| * 복사하지 않아야 할 특별한 객체 타입들을 확인 | ||
| */ | ||
| function isNonCloneableType(value) { | ||
| if (!value || typeof value !== "object") return false; | ||
| if (typeof Element !== "undefined" && value instanceof Element) return true; | ||
| if (typeof Node !== "undefined" && value instanceof Node) return true; | ||
| if (typeof HTMLElement !== "undefined" && value instanceof HTMLElement) return true; | ||
| const record = value; | ||
| if (typeof record.nodeType === "number" && record.nodeType > 0) return true; | ||
| if (typeof record.nodeName === "string") return true; | ||
| if (typeof record.tagName === "string") return true; | ||
| if (record._owner !== void 0 || record.stateNode !== void 0) return true; | ||
| if (typeof value === "function") return true; | ||
| if (value instanceof Promise) return true; | ||
| if (typeof record.then === "function" && typeof record.catch === "function") return true; | ||
| if (value instanceof WeakMap || value instanceof WeakSet) return true; | ||
| return false; | ||
| } | ||
| /** | ||
| * 최적화된 Immer 기반 깊은 복사 | ||
| * Tree-shaking과 성능을 고려한 구현 | ||
| * | ||
| * @template T 복사할 값의 타입 | ||
| * @param value 복사할 값 | ||
| * @param options 복사 옵션 | ||
| * @returns 불변성이 보장된 복사본 | ||
| */ | ||
| function deepClone(value, _options) { | ||
| if (isPrimitive(value)) return value; | ||
| if (typeof value === "function") { | ||
| logger.warn("Functions cannot be deep cloned, returning original reference"); | ||
| return value; | ||
| } | ||
| if (isNonCloneableType(value)) return value; | ||
| if (typeof value === "object" && value !== null && "__contextActionRefState" in value && value.__contextActionRefState === true) return value; | ||
| try { | ||
| return produce(value, (_draft) => {}); | ||
| } catch (error) { | ||
| logger.warn("Immer produce failed, falling back to native methods", error); | ||
| } | ||
| if (typeof structuredClone !== "undefined") try { | ||
| return structuredClone(value); | ||
| } catch {} | ||
| if (!isComplexObject(value)) return simpleClone(value); | ||
| return fallbackClone(value); | ||
| } | ||
| /** | ||
| * Synchronous version with Immer - same as deepClone but with explicit Immer focus | ||
| */ | ||
| function deepCloneWithImmer(value) { | ||
| if (isPrimitive(value)) return value; | ||
| if (isNonCloneableType(value) || typeof value === "function") return value; | ||
| try { | ||
| return produce(value, (_draft) => {}); | ||
| } catch (error) { | ||
| logger.warn("Immer produce failed, falling back to simple clone", error); | ||
| return fallbackClone(value); | ||
| } | ||
| } | ||
| /** | ||
| * 간단한 객체인지 확인 | ||
| */ | ||
| function isSimpleObject(value) { | ||
| return typeof value === "object" && value !== null && value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype; | ||
| } | ||
| /** | ||
| * 성능 최적화된 간단한 객체 복사 | ||
| */ | ||
| function simpleClone(value, visited = /* @__PURE__ */ new WeakSet()) { | ||
| if (typeof value === "object" && value !== null && visited.has(value)) return "[Circular]"; | ||
| if (Array.isArray(value)) { | ||
| visited.add(value); | ||
| return value.map((item) => { | ||
| if (typeof item === "object" && item !== null) if ("__contextActionRefState" in item && item.__contextActionRefState === true) return item; | ||
| else return simpleClone(item, visited); | ||
| return item; | ||
| }); | ||
| } | ||
| if (isSimpleObject(value)) { | ||
| visited.add(value); | ||
| const cloned = {}; | ||
| for (const [key, val] of Object.entries(value)) if (typeof val === "object" && val !== null) if ("__contextActionRefState" in val && val.__contextActionRefState === true) cloned[key] = val; | ||
| else cloned[key] = simpleClone(val, visited); | ||
| else cloned[key] = val; | ||
| return cloned; | ||
| } | ||
| return value; | ||
| } | ||
| /** | ||
| * 폴백 복사 함수 (Immer가 실패한 경우) | ||
| */ | ||
| function fallbackClone(value) { | ||
| try { | ||
| const visited = /* @__PURE__ */ new WeakSet(); | ||
| const refStateObjects = /* @__PURE__ */ new Map(); | ||
| let refStateId = 0; | ||
| const collectRefStates = (obj) => { | ||
| if (typeof obj !== "object" || obj === null || visited.has(obj)) return; | ||
| visited.add(obj); | ||
| if ("__contextActionRefState" in obj && obj.__contextActionRefState === true) { | ||
| const id = `refstate_${refStateId++}`; | ||
| refStateObjects.set(id, obj); | ||
| } | ||
| try { | ||
| if (Array.isArray(obj)) obj.forEach(collectRefStates); | ||
| else for (const val of Object.values(obj)) collectRefStates(val); | ||
| } catch {} | ||
| }; | ||
| try { | ||
| collectRefStates(value); | ||
| } catch {} | ||
| const circularSafeStringify = (obj) => { | ||
| const jsonVisited = /* @__PURE__ */ new WeakSet(); | ||
| return JSON.stringify(obj, function(key, val) { | ||
| if (val !== null && typeof val === "object") { | ||
| if (jsonVisited.has(val)) return "[Circular]"; | ||
| jsonVisited.add(val); | ||
| if ("__contextActionRefState" in val && val.__contextActionRefState === true) { | ||
| const entries = Array.from(refStateObjects.entries()); | ||
| for (let i = 0; i < entries.length; i++) { | ||
| const entry = entries[i]; | ||
| if (entry && entry[1] === val) return { __REFSTATE_PLACEHOLDER__: entry[0] }; | ||
| } | ||
| } | ||
| } | ||
| return val; | ||
| }); | ||
| }; | ||
| const jsonString = circularSafeStringify(value); | ||
| const parsed = JSON.parse(jsonString); | ||
| const restoreRefStates = (obj) => { | ||
| if (typeof obj !== "object" || obj === null) return obj; | ||
| if (obj.__REFSTATE_PLACEHOLDER__ && refStateObjects.has(obj.__REFSTATE_PLACEHOLDER__)) return refStateObjects.get(obj.__REFSTATE_PLACEHOLDER__); | ||
| if (Array.isArray(obj)) return obj.map(restoreRefStates); | ||
| const result = {}; | ||
| for (const [key, val] of Object.entries(obj)) result[key] = restoreRefStates(val); | ||
| return result; | ||
| }; | ||
| return restoreRefStates(parsed); | ||
| } catch (jsonError) { | ||
| logger.error("All cloning methods failed, returning original reference", jsonError); | ||
| return value; | ||
| } | ||
| } | ||
| /** | ||
| * 불변성 검증 함수 - 복사본이 원본과 독립적인지 확인 | ||
| * | ||
| * @param original 원본 값 | ||
| * @param cloned 복사된 값 | ||
| * @returns 불변성이 보장되면 true, 아니면 false | ||
| */ | ||
| function verifyImmutability(original$1, cloned) { | ||
| if (original$1 === null || original$1 === void 0 || typeof original$1 === "string" || typeof original$1 === "number" || typeof original$1 === "boolean" || typeof original$1 === "bigint" || typeof original$1 === "symbol") return original$1 === cloned; | ||
| if (isNonCloneableType(original$1)) return original$1 === cloned; | ||
| if (typeof original$1 === "function") return original$1 === cloned; | ||
| if (typeof original$1 === "object" && original$1 !== null) return true; | ||
| return false; | ||
| } | ||
| /** | ||
| * 안전한 getter - 불변성을 보장하는 값 반환 | ||
| * | ||
| * @template T 값의 타입 | ||
| * @param value 반환할 값 | ||
| * @param enableCloning 복사 활성화 여부 (기본: true) | ||
| * @returns 불변성이 보장된 값 | ||
| */ | ||
| function safeGet(value, enableCloning = true) { | ||
| if (!enableCloning) return value; | ||
| if (isPrimitive(value)) return value; | ||
| if (isNonCloneableType(value)) return value; | ||
| if (typeof value === "object" && value !== null && "__contextActionRefState" in value && value.__contextActionRefState === true) return value; | ||
| const cloned = deepClone(value); | ||
| if (globalImmutabilityOptions.enableVerification) { | ||
| if (!isNonCloneableType(value)) { | ||
| if (!verifyImmutability(value, cloned) && typeof value === "object" && value !== null) { | ||
| if (Math.random() < .01) logger.debug("Immer optimization: same reference returned for unchanged object", { | ||
| type: typeof value, | ||
| constructor: value?.constructor?.name, | ||
| isArray: Array.isArray(value) | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| return cloned; | ||
| } | ||
| /** | ||
| * 안전한 setter - 입력값의 불변성을 보장하는 값 설정 | ||
| * | ||
| * @template T 값의 타입 | ||
| * @param value 설정할 값 | ||
| * @param enableCloning 복사 활성화 여부 (기본: true) | ||
| * @returns 불변성이 보장된 값 | ||
| */ | ||
| function safeSet(value, enableCloning = true) { | ||
| if (!enableCloning) { | ||
| logger.trace("Cloning disabled for setter, returning original reference"); | ||
| return value; | ||
| } | ||
| return deepClone(value); | ||
| } | ||
| /** | ||
| * Immer utilities using static imports | ||
| * Provides the same API as the dynamic version but with immediate availability | ||
| */ | ||
| const ImmerUtils = { | ||
| isDraft(value) { | ||
| return isDraft(value); | ||
| }, | ||
| original(value) { | ||
| return original(value); | ||
| }, | ||
| current(value) { | ||
| return current(value); | ||
| }, | ||
| produce(baseState, producer) { | ||
| return produce(baseState, producer); | ||
| } | ||
| }; | ||
| function preloadImmer() {} | ||
| /** | ||
| * Synchronous produce using static Immer import | ||
| * Direct wrapper around Immer's produce function | ||
| */ | ||
| function produce$1(baseState, producer) { | ||
| try { | ||
| return produce(baseState, producer); | ||
| } catch (error) { | ||
| logger.warn("Immer produce failed, falling back to deep clone simulation", error); | ||
| try { | ||
| const draft = deepClone(baseState); | ||
| const result = producer(draft); | ||
| return result !== void 0 ? result : draft; | ||
| } catch (fallbackError) { | ||
| logger.error("Produce fallback failed, returning original state", fallbackError); | ||
| return baseState; | ||
| } | ||
| } | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/comparison.ts | ||
| const DEFAULT_COMPARISON_OPTIONS = { | ||
| strategy: "reference", | ||
| maxDepth: 5, | ||
| enableCircularCheck: true | ||
| }; | ||
| let globalComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS }; | ||
| function setGlobalComparisonOptions(options) { | ||
| globalComparisonOptions = { | ||
| ...DEFAULT_COMPARISON_OPTIONS, | ||
| ...options | ||
| }; | ||
| } | ||
| function getGlobalComparisonOptions() { | ||
| return { ...globalComparisonOptions }; | ||
| } | ||
| function referenceEquals(oldValue, newValue) { | ||
| return Object.is(oldValue, newValue); | ||
| } | ||
| function shallowEquals(oldValue, newValue, ignoreKeys = []) { | ||
| if (Object.is(oldValue, newValue)) return true; | ||
| if (oldValue == null || newValue == null) return oldValue === newValue; | ||
| if (typeof oldValue !== "object" || typeof newValue !== "object") return oldValue === newValue; | ||
| if (Array.isArray(oldValue) && Array.isArray(newValue)) { | ||
| if (oldValue.length !== newValue.length) return false; | ||
| for (let i = 0; i < oldValue.length; i++) if (!Object.is(oldValue[i], newValue[i])) return false; | ||
| return true; | ||
| } | ||
| const oldKeys = Object.keys(oldValue).filter((key) => !ignoreKeys.includes(key)); | ||
| const newKeys = Object.keys(newValue).filter((key) => !ignoreKeys.includes(key)); | ||
| if (oldKeys.length !== newKeys.length) return false; | ||
| for (const key of oldKeys) { | ||
| if (!newKeys.includes(key)) return false; | ||
| if (!Object.is(oldValue[key], newValue[key])) return false; | ||
| } | ||
| return true; | ||
| } | ||
| function deepEquals(oldValue, newValue, options = {}) { | ||
| const { maxDepth = 5, ignoreKeys = [], enableCircularCheck = true } = options; | ||
| const visitedPairs = enableCircularCheck ? /* @__PURE__ */ new WeakMap() : null; | ||
| function deepCompare(a, b, depth, path = "") { | ||
| if (depth > maxDepth) return Object.is(a, b); | ||
| if (Object.is(a, b)) return true; | ||
| if (a == null || b == null) return a === b; | ||
| if (typeof a !== typeof b) return false; | ||
| if (typeof a !== "object") return a === b; | ||
| if (visitedPairs && typeof a === "object" && typeof b === "object" && a !== null && b !== null) { | ||
| if (visitedPairs.has(a)) { | ||
| if (visitedPairs.get(a).has(b)) return Object.is(a, b); | ||
| } | ||
| if (!visitedPairs.has(a)) visitedPairs.set(a, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(a).add(b); | ||
| if (!visitedPairs.has(b)) visitedPairs.set(b, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(b).add(a); | ||
| } | ||
| if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); | ||
| if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString(); | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| for (let i = 0; i < a.length; i++) if (!deepCompare(a[i], b[i], depth + 1, `${path}[${i}]`)) return false; | ||
| return true; | ||
| } | ||
| if (Array.isArray(a) || Array.isArray(b)) return false; | ||
| const aKeys = Object.keys(a).filter((key) => !ignoreKeys.includes(key)); | ||
| const bKeys = Object.keys(b).filter((key) => !ignoreKeys.includes(key)); | ||
| if (aKeys.length !== bKeys.length) return false; | ||
| for (const key of aKeys) { | ||
| if (!bKeys.includes(key)) return false; | ||
| if (!deepCompare(a[key], b[key], depth + 1, `${path}.${key}`)) return false; | ||
| } | ||
| return true; | ||
| } | ||
| return deepCompare(oldValue, newValue, 0); | ||
| } | ||
| function compareValues(oldValue, newValue, options = {}) { | ||
| const { strategy, customComparator, maxDepth, ignoreKeys, enableCircularCheck } = { | ||
| ...globalComparisonOptions, | ||
| ...options | ||
| }; | ||
| let result; | ||
| try { | ||
| if (strategy !== "reference" && strategy !== "custom" && typeof oldValue === "object" && typeof newValue === "object") try { | ||
| const oldStr = JSON.stringify(oldValue); | ||
| const newStr = JSON.stringify(newValue); | ||
| if (oldStr.length < 1e3 && newStr.length < 1e3) { | ||
| result = oldStr === newStr; | ||
| return result; | ||
| } | ||
| } catch (error) { | ||
| console.debug("[ComparisonOptimization] JSON serialization failed, falling back to original strategy:", error); | ||
| } | ||
| switch (strategy) { | ||
| case "reference": | ||
| result = referenceEquals(oldValue, newValue); | ||
| break; | ||
| case "shallow": | ||
| result = shallowEquals(oldValue, newValue, ignoreKeys); | ||
| break; | ||
| case "deep": | ||
| result = deepEquals(oldValue, newValue, { | ||
| ...maxDepth !== void 0 && { maxDepth }, | ||
| ...ignoreKeys !== void 0 && { ignoreKeys }, | ||
| ...enableCircularCheck !== void 0 && { enableCircularCheck } | ||
| }); | ||
| break; | ||
| case "custom": | ||
| if (!customComparator) result = referenceEquals(oldValue, newValue); | ||
| else result = customComparator(oldValue, newValue); | ||
| break; | ||
| default: result = referenceEquals(oldValue, newValue); | ||
| } | ||
| } catch (error) { | ||
| console.warn("[CompareValues] Comparison failed, falling back to reference equality:", error); | ||
| result = referenceEquals(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/error-handling.ts | ||
| /** | ||
| * @fileoverview Error Handling Utilities | ||
| * | ||
| * 일관된 에러 처리를 위한 유틸리티 함수들 | ||
| * Context-Action 프레임워크 전반에 걸친 표준화된 에러 처리 패턴 | ||
| */ | ||
| /** | ||
| * Context-Action 프레임워크의 에러 유형 정의 | ||
| */ | ||
| let ContextActionErrorType = /* @__PURE__ */ function(ContextActionErrorType$1) { | ||
| ContextActionErrorType$1["STORE_ERROR"] = "STORE_ERROR"; | ||
| ContextActionErrorType$1["ACTION_ERROR"] = "ACTION_ERROR"; | ||
| ContextActionErrorType$1["REF_ERROR"] = "REF_ERROR"; | ||
| ContextActionErrorType$1["VALIDATION_ERROR"] = "VALIDATION_ERROR"; | ||
| ContextActionErrorType$1["INITIALIZATION_ERROR"] = "INITIALIZATION_ERROR"; | ||
| ContextActionErrorType$1["TIMEOUT_ERROR"] = "TIMEOUT_ERROR"; | ||
| ContextActionErrorType$1["CIRCULAR_REFERENCE_ERROR"] = "CIRCULAR_REFERENCE_ERROR"; | ||
| return ContextActionErrorType$1; | ||
| }({}); | ||
| /** | ||
| * Context-Action 프레임워크의 표준 에러 클래스 | ||
| */ | ||
| var ContextActionError = class ContextActionError extends Error { | ||
| constructor(type, message, context, originalError) { | ||
| super(message); | ||
| this.name = "ContextActionError"; | ||
| this.type = type; | ||
| this.context = context ?? void 0; | ||
| this.timestamp = Date.now(); | ||
| if (Error.captureStackTrace) Error.captureStackTrace(this, ContextActionError); | ||
| if (originalError) this.stack = `${this.stack}\nCaused by: ${originalError.stack}`; | ||
| } | ||
| }; | ||
| /** | ||
| * 에러 로깅 레벨 | ||
| */ | ||
| let ErrorLogLevel = /* @__PURE__ */ function(ErrorLogLevel$1) { | ||
| ErrorLogLevel$1[ErrorLogLevel$1["SILENT"] = 0] = "SILENT"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["ERROR"] = 1] = "ERROR"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["WARN"] = 2] = "WARN"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["INFO"] = 3] = "INFO"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["DEBUG"] = 4] = "DEBUG"; | ||
| return ErrorLogLevel$1; | ||
| }({}); | ||
| /** | ||
| * 현재 에러 핸들링 설정 | ||
| */ | ||
| let currentErrorConfig = { | ||
| logLevel: ErrorLogLevel.DEBUG, | ||
| throwOnError: true, | ||
| enableStackTrace: true, | ||
| maxLogEntries: 100, | ||
| suppressRepeatedErrors: true, | ||
| logErrors: true | ||
| }; | ||
| /** | ||
| * 에러 로그 저장소 | ||
| */ | ||
| let errorLog = []; | ||
| let errorSignatures = /* @__PURE__ */ new Map(); | ||
| /** | ||
| * 에러 시그니처 생성 (중복 에러 감지용) | ||
| */ | ||
| function createErrorSignature(error) { | ||
| return `${error.type}:${error.message}:${error.context?.component || "unknown"}`; | ||
| } | ||
| /** | ||
| * 표준화된 에러 처리 함수 (통합된 에러 바운더리 사용) | ||
| */ | ||
| function handleError(type, message, context, originalError) { | ||
| const error = new ContextActionError(type, message, context, originalError); | ||
| logError(error); | ||
| if (currentErrorConfig.throwOnError) throw error; | ||
| return error; | ||
| } | ||
| /** | ||
| * 에러 로깅 함수 | ||
| */ | ||
| function logError(error) { | ||
| const signature = createErrorSignature(error); | ||
| if (currentErrorConfig.suppressRepeatedErrors) { | ||
| const existingEntry = errorSignatures.get(signature); | ||
| if (existingEntry) { | ||
| existingEntry.count++; | ||
| existingEntry.lastOccurred = Date.now(); | ||
| if (existingEntry.count % 10 === 0) console.warn(`[Context-Action] Repeated error occurred ${existingEntry.count} times:`, error); | ||
| return; | ||
| } | ||
| } | ||
| const logEntry = { | ||
| error, | ||
| count: 1, | ||
| lastOccurred: Date.now() | ||
| }; | ||
| errorLog.push(logEntry); | ||
| errorSignatures.set(signature, logEntry); | ||
| if (errorLog.length > currentErrorConfig.maxLogEntries) { | ||
| const removedEntry = errorLog.shift(); | ||
| if (removedEntry) { | ||
| const removedSignature = createErrorSignature(removedEntry.error); | ||
| errorSignatures.delete(removedSignature); | ||
| } | ||
| } | ||
| if (typeof globalThis !== "undefined" && globalThis.globalErrorBoundary) globalThis.globalErrorBoundary.reportError(error); | ||
| switch (currentErrorConfig.logLevel) { | ||
| case ErrorLogLevel.DEBUG: | ||
| console.debug("[Context-Action] Debug:", error); | ||
| break; | ||
| case ErrorLogLevel.INFO: | ||
| console.info("[Context-Action] Info:", error); | ||
| break; | ||
| case ErrorLogLevel.WARN: | ||
| console.warn("[Context-Action] Warning:", error); | ||
| break; | ||
| case ErrorLogLevel.ERROR: | ||
| console.error("[Context-Action] Error:", error); | ||
| if (currentErrorConfig.enableStackTrace && error.stack) console.error("Stack trace:", error.stack); | ||
| break; | ||
| case ErrorLogLevel.SILENT: break; | ||
| } | ||
| } | ||
| /** | ||
| * 특정 에러 타입에 대한 전용 핸들러들 | ||
| */ | ||
| const ErrorHandlers = { | ||
| store: (message, context, originalError) => { | ||
| const enhancedMessage = `[Store Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.STORE_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| action: (message, context, originalError) => { | ||
| const enhancedMessage = `[Action Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.ACTION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| ref: (message, context, originalError) => { | ||
| const enhancedMessage = `[Ref Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.REF_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| validation: (message, context, originalError) => { | ||
| const enhancedMessage = `[Validation Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.VALIDATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| initialization: (message, context, originalError) => { | ||
| const enhancedMessage = `[Initialization Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.INITIALIZATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| timeout: (message, context, originalError) => { | ||
| const enhancedMessage = `[Timeout Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.TIMEOUT_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| circularReference: (message, context, originalError) => handleError(ContextActionErrorType.CIRCULAR_REFERENCE_ERROR, message, context, originalError) | ||
| }; | ||
| /** | ||
| * 에러 통계 가져오기 | ||
| */ | ||
| function getErrorStatistics() { | ||
| const errorsByType = Object.values(ContextActionErrorType).reduce((acc, type) => { | ||
| acc[type] = 0; | ||
| return acc; | ||
| }, {}); | ||
| errorLog.forEach((entry) => { | ||
| errorsByType[entry.error.type] += entry.count; | ||
| }); | ||
| const mostFrequentErrors = Array.from(errorSignatures.entries()).map(([signature, entry]) => ({ | ||
| signature, | ||
| count: entry.count, | ||
| lastOccurred: entry.lastOccurred | ||
| })).sort((a, b) => b.count - a.count).slice(0, 10); | ||
| const recentErrors = errorLog.slice(-10).map((entry) => entry.error); | ||
| return { | ||
| totalErrors: errorLog.reduce((sum, entry) => sum + entry.count, 0), | ||
| errorsByType, | ||
| mostFrequentErrors, | ||
| recentErrors | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { ContextActionError, ContextActionErrorType, ErrorHandlers, ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getErrorStatistics, getGlobalComparisonOptions, handleError, preloadImmer, produce$1 as produce, safeGet, safeSet, setGlobalComparisonOptions }; | ||
| //# sourceMappingURL=error-handling-CkdfKCZ0.js.map |
| {"version":3,"file":"error-handling-CkdfKCZ0.js","names":["globalImmutabilityOptions: ImmutabilityOptions","immerProduce","original","immerIsDraft","immerOriginal","immerCurrent","produce","DEFAULT_COMPARISON_OPTIONS: ComparisonOptions","globalComparisonOptions: ComparisonOptions","result: boolean","currentErrorConfig: ErrorHandlingConfig","errorLog: ErrorLogEntry[]","errorSignatures: Map<string, ErrorLogEntry>","logEntry: ErrorLogEntry"],"sources":["../src/stores/utils/immutable.ts","../src/stores/utils/comparison.ts","../src/stores/utils/error-handling.ts"],"sourcesContent":["/**\n * @fileoverview Immer-based Immutability Utils\n * \n * Immer를 사용한 안전하고 효율적인 불변성 보장 시스템\n * 기존 복잡한 구현을 Immer로 대체하여 안정성과 성능을 개선\n * \n * @implements store-immutability\n * @memberof core-concepts\n */\n\n// Static Immer import for reliable and predictable behavior\nimport {\n produce as immerProduce,\n isDraft as immerIsDraft,\n original as immerOriginal,\n current as immerCurrent,\n enableMapSet\n} from 'immer';\n\n// Enable Map and Set support in Immer\nenableMapSet();\n\n/**\n * Check if value is a primitive type\n */\nfunction isPrimitive(value: unknown): boolean {\n return (\n value === null ||\n value === undefined ||\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'bigint' ||\n typeof value === 'symbol'\n );\n}\n\n/**\n * Check if value is a complex object that needs Immer\n */\nfunction isComplexObject(value: unknown): boolean {\n if (!value || typeof value !== 'object') return false;\n \n // Arrays are complex\n if (Array.isArray(value)) return true;\n \n // Objects with nested properties\n if (value.constructor === Object) {\n const obj = value as Record<string, unknown>;\n return Object.values(obj).some(val => \n typeof val === 'object' && val !== null\n );\n }\n \n // Class instances, Maps, Sets etc.\n return value.constructor !== Object;\n}\n\n// Simple logger replacement\nconst logger = {\n warn: (message: string, ...args: any[]) => console.warn(`[Context-Action] ${message}`, ...args),\n trace: (message: string, ...args: any[]) => console.trace(`[Context-Action] ${message}`, ...args),\n error: (message: string, ...args: any[]) => console.error(`[Context-Action] ${message}`, ...args),\n debug: (message: string, ...args: any[]) => console.debug(`[Context-Action] ${message}`, ...args)\n};\n\n/**\n * 불변성 설정 옵션\n */\nexport interface ImmutabilityOptions {\n enableCloning?: boolean; // 복사 활성화 여부 (기본: true)\n enableVerification?: boolean; // 개발 모드 검증 활성화 (기본: true)\n warnOnFallback?: boolean; // 폴백 사용 시 경고 (기본: true)\n}\n\n/**\n * 전역 불변성 설정\n */\nlet globalImmutabilityOptions: ImmutabilityOptions = {\n enableCloning: true,\n enableVerification: process.env.NODE_ENV === 'development',\n warnOnFallback: true\n};\n\n/**\n * 복사하지 않아야 할 특별한 객체 타입들을 확인\n */\nfunction isNonCloneableType(value: unknown): boolean {\n if (!value || typeof value !== 'object') return false;\n \n // DOM Elements\n if (typeof Element !== 'undefined' && value instanceof Element) return true;\n if (typeof Node !== 'undefined' && value instanceof Node) return true;\n if (typeof HTMLElement !== 'undefined' && value instanceof HTMLElement) return true;\n \n // DOM-like properties check\n const record = value as Record<string, unknown>;\n if (typeof record.nodeType === 'number' && record.nodeType > 0) return true;\n if (typeof record.nodeName === 'string') return true;\n if (typeof record.tagName === 'string') return true;\n \n // React Fiber properties\n if (record._owner !== undefined || record.stateNode !== undefined) return true;\n \n // Functions (though they shouldn't reach here)\n if (typeof value === 'function') return true;\n \n // Promises\n if (value instanceof Promise) return true;\n if (typeof record.then === 'function' && typeof record.catch === 'function') return true;\n \n // Other unclonable types\n if (value instanceof WeakMap || value instanceof WeakSet) return true;\n \n return false;\n}\n\n/**\n * 최적화된 Immer 기반 깊은 복사\n * Tree-shaking과 성능을 고려한 구현\n * \n * @template T 복사할 값의 타입\n * @param value 복사할 값\n * @param options 복사 옵션\n * @returns 불변성이 보장된 복사본\n */\nexport function deepClone<T>(value: T, _options?: { skipProducer?: boolean }): T {\n // Fast path: Primitive values are already immutable\n if (isPrimitive(value)) {\n return value;\n }\n\n // Function은 복사 불가능하므로 경고 후 원본 반환\n if (typeof value === 'function') {\n if (process.env.NODE_ENV === 'development') {\n logger.warn('Functions cannot be deep cloned, returning original reference');\n }\n return value;\n }\n\n // 복사하지 않아야 할 특별한 객체들\n if (isNonCloneableType(value)) {\n return value;\n }\n\n // RefState 객체는 DOM 요소를 포함하므로 복사하지 않고 원본 반환\n // DOM 요소는 JSON serialization에서 빈 객체로 변환되므로 원본 유지 필요\n if (typeof value === 'object' && value !== null && \n '__contextActionRefState' in value && value.__contextActionRefState === true) {\n return value;\n }\n\n // 🎯 Priority 1: Use Immer (best immutability guarantee)\n try {\n return immerProduce(value, (_draft: any) => {\n // Empty producer for copy-on-write optimization\n // Immer will return original reference if no changes are made\n });\n } catch (error) {\n if (process.env.NODE_ENV === 'development') {\n logger.warn('Immer produce failed, falling back to native methods', error);\n }\n // Continue to next method\n }\n\n // Priority 2: Use native structuredClone if available (Chrome 98+, Node 17+)\n if (typeof structuredClone !== 'undefined') {\n try {\n return structuredClone(value);\n } catch {\n // Fall through to other methods if structuredClone fails\n }\n }\n\n // Priority 3: For simple objects, use optimized simple clone\n if (!isComplexObject(value)) {\n return simpleClone(value);\n }\n\n // Priority 4: Last resort - use fallback clone (JSON-based)\n return fallbackClone(value);\n}\n\n/**\n * Synchronous version with Immer - same as deepClone but with explicit Immer focus\n */\nexport function deepCloneWithImmer<T>(value: T): T {\n // Fast path for primitives\n if (isPrimitive(value)) {\n return value;\n }\n\n // Skip non-cloneable types\n if (isNonCloneableType(value) || typeof value === 'function') {\n return value;\n }\n\n try {\n return immerProduce(value, (_draft: any) => {\n // Empty function for copy-on-write optimization\n });\n } catch (error) {\n if (process.env.NODE_ENV === 'development') {\n logger.warn('Immer produce failed, falling back to simple clone', error);\n }\n return fallbackClone(value);\n }\n}\n\n/**\n * 간단한 객체인지 확인\n */\nfunction isSimpleObject(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n value.constructor === Object &&\n Object.getPrototypeOf(value) === Object.prototype\n );\n}\n\n/**\n * 성능 최적화된 간단한 객체 복사\n */\nfunction simpleClone<T>(value: T, visited = new WeakSet()): T {\n // 순환 참조 감지\n if (typeof value === 'object' && value !== null && visited.has(value)) {\n return '[Circular]' as any;\n }\n\n if (Array.isArray(value)) {\n visited.add(value);\n const result = value.map(item => {\n if (typeof item === 'object' && item !== null) {\n // RefState 객체는 복사하지 않고 원본 유지 (DOM 요소 보존)\n if ('__contextActionRefState' in item && item.__contextActionRefState === true) {\n return item;\n } else {\n return simpleClone(item, visited);\n }\n }\n return item;\n }) as T;\n // visited에서 제거하지 않음 - 전체 cloning이 끝날 때까지 유지\n return result;\n }\n\n if (isSimpleObject(value)) {\n visited.add(value);\n const cloned = {} as Record<string, unknown>;\n for (const [key, val] of Object.entries(value)) {\n if (typeof val === 'object' && val !== null) {\n // RefState 객체는 복사하지 않고 원본 유지 (DOM 요소 보존)\n if ('__contextActionRefState' in val && val.__contextActionRefState === true) {\n cloned[key] = val;\n } else {\n cloned[key] = simpleClone(val, visited);\n }\n } else {\n cloned[key] = val;\n }\n }\n // visited에서 제거하지 않음 - 전체 cloning이 끝날 때까지 유지\n return cloned as T;\n }\n\n return value;\n}\n\n/**\n * 폴백 복사 함수 (Immer가 실패한 경우)\n */\nfunction fallbackClone<T>(value: T): T {\n // RefState를 보존하면서 복사하는 로직\n try {\n const visited = new WeakSet();\n const refStateObjects = new Map<string, object>();\n let refStateId = 0;\n \n // RefState 객체들을 먼저 수집하고 ID 부여\n const collectRefStates = (obj: any) => {\n if (typeof obj !== 'object' || obj === null || visited.has(obj)) return;\n visited.add(obj);\n \n if ('__contextActionRefState' in obj && obj.__contextActionRefState === true) {\n const id = `refstate_${refStateId++}`;\n refStateObjects.set(id, obj);\n }\n \n try {\n if (Array.isArray(obj)) {\n obj.forEach(collectRefStates);\n } else {\n for (const val of Object.values(obj)) {\n collectRefStates(val);\n }\n }\n } catch {\n // Silently handle errors in RefState collection\n }\n };\n \n try {\n collectRefStates(value);\n // Note: WeakSet doesn't have clear() method, and we don't need to clear it\n } catch {\n // Silently handle errors during RefState collection\n }\n \n // JSON 변환 시 RefState 객체는 ID로 교체\n const circularSafeStringify = (obj: unknown): string => {\n const jsonVisited = new WeakSet(); // 새로운 WeakSet을 JSON 직렬화용으로 사용\n return JSON.stringify(obj, function(key, val) {\n if (val !== null && typeof val === 'object') {\n if (jsonVisited.has(val)) {\n return '[Circular]';\n }\n jsonVisited.add(val);\n \n // RefState 객체는 ID 마커로 교체\n if ('__contextActionRefState' in val && val.__contextActionRefState === true) {\n const entries = Array.from(refStateObjects.entries());\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i];\n if (entry && entry[1] === val) {\n return { __REFSTATE_PLACEHOLDER__: entry[0] };\n }\n }\n }\n }\n return val;\n });\n };\n \n const jsonString = circularSafeStringify(value);\n const parsed = JSON.parse(jsonString);\n \n // RefState 플레이스홀더를 원본으로 복원\n const restoreRefStates = (obj: any): any => {\n if (typeof obj !== 'object' || obj === null) return obj;\n \n if (obj.__REFSTATE_PLACEHOLDER__ && refStateObjects.has(obj.__REFSTATE_PLACEHOLDER__)) {\n return refStateObjects.get(obj.__REFSTATE_PLACEHOLDER__);\n }\n \n if (Array.isArray(obj)) {\n return obj.map(restoreRefStates);\n }\n \n const result = {} as any;\n for (const [key, val] of Object.entries(obj)) {\n result[key] = restoreRefStates(val);\n }\n return result;\n };\n \n return restoreRefStates(parsed);\n } catch (jsonError) {\n // 모든 방법이 실패하면 원본 반환\n if (process.env.NODE_ENV === 'development') {\n logger.error('All cloning methods failed, returning original reference', jsonError);\n }\n return value;\n }\n}\n\n/**\n * 불변성 검증 함수 - 복사본이 원본과 독립적인지 확인\n * \n * @param original 원본 값\n * @param cloned 복사된 값\n * @returns 불변성이 보장되면 true, 아니면 false\n */\nexport function verifyImmutability<T>(original: T, cloned: T): boolean {\n // Primitive 값은 항상 불변\n if (\n original === null ||\n original === undefined ||\n typeof original === 'string' ||\n typeof original === 'number' ||\n typeof original === 'boolean' ||\n typeof original === 'bigint' ||\n typeof original === 'symbol'\n ) {\n return original === cloned;\n }\n\n // 복사하지 말아야 할 특별한 객체들 - 참조가 같아야 정상\n if (isNonCloneableType(original)) {\n return original === cloned;\n }\n\n // Functions - 참조가 같아야 정상\n if (typeof original === 'function') {\n return original === cloned;\n }\n\n // 일반 객체나 배열의 경우 \n // Immer는 변경사항이 없으면 원본을 반환할 수 있으므로 이는 정상적인 최적화\n if (typeof original === 'object' && original !== null) {\n return true; // Immer의 최적화를 신뢰\n }\n\n return false;\n}\n\n/**\n * 안전한 getter - 불변성을 보장하는 값 반환\n * \n * @template T 값의 타입\n * @param value 반환할 값\n * @param enableCloning 복사 활성화 여부 (기본: true)\n * @returns 불변성이 보장된 값\n */\nexport function safeGet<T>(value: T, enableCloning: boolean = true): T {\n if (!enableCloning) return value;\n \n // Fast path: primitive types don't need cloning\n if (isPrimitive(value)) return value;\n \n // Fast path: non-cloneable types\n if (isNonCloneableType(value)) return value;\n \n // Fast path: RefState objects\n if (typeof value === 'object' && value !== null && \n '__contextActionRefState' in value && value.__contextActionRefState === true) {\n return value;\n }\n\n const cloned = deepClone(value);\n \n // 개발 모드에서 간단한 검증\n if (process.env.NODE_ENV === 'development' && globalImmutabilityOptions.enableVerification) {\n // 특별한 객체가 아닌 경우에만 검증\n if (!isNonCloneableType(value)) {\n const isImmutable = verifyImmutability(value, cloned);\n if (!isImmutable && typeof value === 'object' && value !== null) {\n // Immer는 최적화를 통해 원본을 반환할 수 있으므로 경고만 출력\n if (Math.random() < 0.01) { // 1% 확률로만 로그 출력하여 성능 최적화\n logger.debug('Immer optimization: same reference returned for unchanged object', {\n type: typeof value,\n constructor: value?.constructor?.name,\n isArray: Array.isArray(value)\n });\n }\n }\n }\n }\n\n return cloned;\n}\n\n/**\n * 안전한 setter - 입력값의 불변성을 보장하는 값 설정\n * \n * @template T 값의 타입\n * @param value 설정할 값\n * @param enableCloning 복사 활성화 여부 (기본: true)\n * @returns 불변성이 보장된 값\n */\nexport function safeSet<T>(value: T, enableCloning: boolean = true): T {\n if (!enableCloning) {\n if (process.env.NODE_ENV === 'development') {\n logger.trace('Cloning disabled for setter, returning original reference');\n }\n return value;\n }\n\n return deepClone(value);\n}\n\n/**\n * 전역 불변성 옵션 설정\n * \n * @param options 불변성 옵션\n */\nexport function setGlobalImmutabilityOptions(options: Partial<ImmutabilityOptions>): void {\n globalImmutabilityOptions = { ...globalImmutabilityOptions, ...options };\n logger.debug('Global immutability options updated', globalImmutabilityOptions);\n}\n\n/**\n * 현재 전역 불변성 옵션 가져오기\n * \n * @returns 현재 불변성 옵션\n */\nexport function getGlobalImmutabilityOptions(): ImmutabilityOptions {\n return { ...globalImmutabilityOptions };\n}\n\n\n/**\n * Immer utilities using static imports\n * Provides the same API as the dynamic version but with immediate availability\n */\nexport const ImmerUtils = {\n /**\n * Check if value is a Draft object\n */\n isDraft(value: unknown): boolean {\n return immerIsDraft(value);\n },\n\n /**\n * Get original object from Draft\n */\n original<T>(value: T): T | undefined {\n return immerOriginal(value);\n },\n\n /**\n * Get current state of Draft\n */\n current<T>(value: T): T {\n return immerCurrent(value);\n },\n\n /**\n * Produce new state with Immer\n */\n produce<T>(baseState: T, producer: (draft: T) => void | T): T {\n return immerProduce(baseState, producer);\n }\n};\n\n// Note: preloadImmer is no longer needed with static imports\n// This function is kept for backwards compatibility\nexport function preloadImmer(): void {\n // No-op: Immer is already loaded statically\n}\n\n/**\n * Synchronous produce using static Immer import\n * Direct wrapper around Immer's produce function\n */\nexport function produce<T>(baseState: T, producer: (draft: T) => void | T): T {\n try {\n return immerProduce(baseState, producer);\n } catch (error) {\n // Fallback: simulate Immer behavior with deep cloning\n if (process.env.NODE_ENV === 'development') {\n logger.warn('Immer produce failed, falling back to deep clone simulation', error);\n }\n \n try {\n // Create a deep clone for the producer to modify\n const draft = deepClone(baseState);\n const result = producer(draft);\n \n // If producer returns a value, use it; otherwise use the modified draft\n return (result !== undefined ? result : draft) as T;\n } catch (fallbackError) {\n // If everything fails, just return original\n if (process.env.NODE_ENV === 'development') {\n logger.error('Produce fallback failed, returning original state', fallbackError);\n }\n return baseState;\n }\n }\n}\n\n","\n\nexport type ComparisonStrategy = 'reference' | 'shallow' | 'deep' | 'custom';\n\nexport type CustomComparator<T = unknown> = (oldValue: T, newValue: T) => boolean;\n\nexport interface ComparisonOptions<T = unknown> {\n strategy: ComparisonStrategy;\n customComparator?: CustomComparator<T>;\n maxDepth?: number;\n ignoreKeys?: string[];\n enableCircularCheck?: boolean;\n}\n\nconst DEFAULT_COMPARISON_OPTIONS: ComparisonOptions = {\n strategy: 'reference',\n maxDepth: 5,\n enableCircularCheck: true,\n};\n\nlet globalComparisonOptions: ComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS };\n\nexport function setGlobalComparisonOptions(options: Partial<ComparisonOptions>): void {\n globalComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS, ...options };\n}\n\nexport function getGlobalComparisonOptions(): ComparisonOptions {\n return { ...globalComparisonOptions };\n}\n\nexport function referenceEquals<T>(oldValue: T, newValue: T): boolean {\n const result = Object.is(oldValue, newValue);\n return result;\n}\n\nexport function shallowEquals<T>(oldValue: T, newValue: T, ignoreKeys: string[] = []): boolean {\n // 참조가 같으면 즉시 true\n if (Object.is(oldValue, newValue)) {\n return true;\n }\n\n // null/undefined 처리\n if (oldValue == null || newValue == null) {\n const result = oldValue === newValue;\n return result;\n }\n\n // 원시 타입 처리\n if (typeof oldValue !== 'object' || typeof newValue !== 'object') {\n const result = oldValue === newValue;\n return result;\n }\n\n // 배열 처리\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (oldValue.length !== newValue.length) {\n return false;\n }\n \n for (let i = 0; i < oldValue.length; i++) {\n if (!Object.is(oldValue[i], newValue[i])) {\n return false;\n }\n }\n \n return true;\n }\n\n // 객체 처리\n const oldKeys = Object.keys(oldValue as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n const newKeys = Object.keys(newValue as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n\n if (oldKeys.length !== newKeys.length) {\n return false;\n }\n\n for (const key of oldKeys) {\n if (!newKeys.includes(key)) {\n return false;\n }\n \n if (!Object.is((oldValue as Record<string, unknown>)[key], (newValue as Record<string, unknown>)[key])) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function deepEquals<T>(\n oldValue: T, \n newValue: T, \n options: {\n maxDepth?: number;\n ignoreKeys?: string[];\n enableCircularCheck?: boolean;\n } = {}\n): boolean {\n const { maxDepth = 5, ignoreKeys = [], enableCircularCheck = true } = options;\n \n // 개선된 순환 참조 감지 시스템\n const visitedPairs = enableCircularCheck ? new WeakMap<object, WeakSet<object>>() : null;\n \n function deepCompare(a: unknown, b: unknown, depth: number, path = ''): boolean {\n // 최대 깊이 초과 시 참조 비교로 fallback\n if (depth > maxDepth) {\n return Object.is(a, b);\n }\n\n // 참조가 같으면 즉시 true\n if (Object.is(a, b)) {\n return true;\n }\n\n // null/undefined 처리\n if (a == null || b == null) {\n return a === b;\n }\n\n // 타입이 다르면 false\n if (typeof a !== typeof b) {\n return false;\n }\n\n // 원시 타입 처리\n if (typeof a !== 'object') {\n return a === b;\n }\n\n // 개선된 순환 참조 체크\n if (visitedPairs && typeof a === 'object' && typeof b === 'object' && a !== null && b !== null) {\n // 비교 쌍의 순환 참조 확인\n if (visitedPairs.has(a)) {\n const pairedSet = visitedPairs.get(a)!;\n if (pairedSet.has(b)) {\n return Object.is(a, b);\n }\n }\n \n // 방문 기록 추가\n if (!visitedPairs.has(a)) {\n visitedPairs.set(a, new WeakSet());\n }\n visitedPairs.get(a)!.add(b);\n \n // 반대 방향도 기록 (대칭적 추적)\n if (!visitedPairs.has(b)) {\n visitedPairs.set(b, new WeakSet());\n }\n visitedPairs.get(b)!.add(a);\n }\n\n // Date 객체 처리\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n // RegExp 객체 처리\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.toString() === b.toString();\n }\n\n // 배열 처리\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n \n for (let i = 0; i < a.length; i++) {\n if (!deepCompare(a[i], b[i], depth + 1, `${path}[${i}]`)) {\n return false;\n }\n }\n \n return true;\n }\n\n // 배열과 객체 타입 불일치\n if (Array.isArray(a) || Array.isArray(b)) {\n return false;\n }\n\n // 객체 처리\n const aKeys = Object.keys(a as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n const bKeys = Object.keys(b as Record<string, unknown>).filter(key => !ignoreKeys.includes(key));\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (const key of aKeys) {\n if (!bKeys.includes(key)) {\n return false;\n }\n \n if (!deepCompare((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key], depth + 1, `${path}.${key}`)) {\n return false;\n }\n }\n\n return true;\n }\n\n const result = deepCompare(oldValue, newValue, 0);\n \n return result;\n}\n\nexport function compareValues<T>(\n oldValue: T, \n newValue: T, \n options: Partial<ComparisonOptions<T>> = {}\n): boolean {\n const finalOptions = { ...globalComparisonOptions, ...options };\n const { strategy, customComparator, maxDepth, ignoreKeys, enableCircularCheck } = finalOptions;\n\n let result: boolean;\n\n try {\n // HMR 최적화: 자동 전략 선택 (strategy가 'reference'가 아닌 경우)\n if (strategy !== 'reference' && strategy !== 'custom' && typeof oldValue === 'object' && typeof newValue === 'object') {\n // JSON 직렬화 시도로 크기와 복잡도 판단\n try {\n const oldStr = JSON.stringify(oldValue);\n const newStr = JSON.stringify(newValue);\n \n // 작은 객체 (1KB 미만): JSON 문자열 비교가 가장 빠름\n if (oldStr.length < 1000 && newStr.length < 1000) {\n result = oldStr === newStr;\n return result;\n }\n } catch (error) {\n // JSON 직렬화 실패 시 (순환 참조, BigInt, Symbol, Function 등)\n // 디버그 모드에서만 로깅하여 성능 영향 최소화\n if (process.env.NODE_ENV === 'development') {\n console.debug('[ComparisonOptimization] JSON serialization failed, falling back to original strategy:', error);\n }\n // 원래 전략으로 계속 진행 (fallthrough)\n }\n }\n\n // 원래 전략 실행\n switch (strategy) {\n case 'reference':\n result = referenceEquals(oldValue, newValue);\n break;\n \n case 'shallow':\n result = shallowEquals(oldValue, newValue, ignoreKeys);\n break;\n \n case 'deep': {\n const deepOptions = {\n ...(maxDepth !== undefined && { maxDepth }),\n ...(ignoreKeys !== undefined && { ignoreKeys }),\n ...(enableCircularCheck !== undefined && { enableCircularCheck })\n };\n result = deepEquals(oldValue, newValue, deepOptions);\n break;\n }\n \n case 'custom':\n if (!customComparator) {\n result = referenceEquals(oldValue, newValue);\n } else {\n result = customComparator(oldValue, newValue);\n }\n break;\n \n default:\n result = referenceEquals(oldValue, newValue);\n }\n } catch (error) {\n // 비교 중 예상치 못한 오류 발생 시 안전한 참조 비교로 fallback\n if (process.env.NODE_ENV === 'development') {\n console.warn('[CompareValues] Comparison failed, falling back to reference equality:', error);\n }\n result = referenceEquals(oldValue, newValue);\n }\n\n return result;\n}\n\n\n\n","/**\n * @fileoverview Error Handling Utilities\n * \n * 일관된 에러 처리를 위한 유틸리티 함수들\n * Context-Action 프레임워크 전반에 걸친 표준화된 에러 처리 패턴\n */\n\n\n/**\n * Context-Action 프레임워크의 에러 유형 정의\n */\nexport enum ContextActionErrorType {\n STORE_ERROR = 'STORE_ERROR',\n ACTION_ERROR = 'ACTION_ERROR',\n REF_ERROR = 'REF_ERROR',\n VALIDATION_ERROR = 'VALIDATION_ERROR',\n INITIALIZATION_ERROR = 'INITIALIZATION_ERROR',\n TIMEOUT_ERROR = 'TIMEOUT_ERROR',\n CIRCULAR_REFERENCE_ERROR = 'CIRCULAR_REFERENCE_ERROR'\n}\n\n/**\n * Context-Action 프레임워크의 표준 에러 클래스\n */\nexport class ContextActionError extends Error {\n public readonly type: ContextActionErrorType;\n public readonly context: Record<string, unknown> | undefined;\n public readonly timestamp: number;\n\n constructor(\n type: ContextActionErrorType,\n message: string,\n context?: Record<string, unknown>,\n originalError?: Error\n ) {\n super(message);\n this.name = 'ContextActionError';\n this.type = type;\n this.context = context ?? undefined;\n this.timestamp = Date.now();\n \n // Error.captureStackTrace가 사용 가능하면 스택 최적화\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ContextActionError);\n }\n \n // 원본 에러가 있으면 스택 추가 (captureStackTrace 후에 실행)\n if (originalError) {\n this.stack = `${this.stack}\\nCaused by: ${originalError.stack}`;\n }\n }\n}\n\n/**\n * 에러 로깅 레벨\n */\nexport enum ErrorLogLevel {\n SILENT = 0,\n ERROR = 1,\n WARN = 2,\n INFO = 3,\n DEBUG = 4\n}\n\n/**\n * 에러 핸들링 설정\n */\nexport interface ErrorHandlingConfig {\n logLevel: ErrorLogLevel;\n throwOnError: boolean;\n enableStackTrace: boolean;\n maxLogEntries: number;\n suppressRepeatedErrors: boolean;\n logErrors: boolean;\n}\n\n/**\n * 기본 에러 핸들링 설정\n */\nconst defaultErrorConfig: ErrorHandlingConfig = {\n logLevel: process.env.NODE_ENV === 'development' ? ErrorLogLevel.DEBUG : ErrorLogLevel.ERROR,\n throwOnError: process.env.NODE_ENV === 'development',\n enableStackTrace: true,\n maxLogEntries: 100,\n suppressRepeatedErrors: true,\n logErrors: true\n};\n\n/**\n * 현재 에러 핸들링 설정\n */\nlet currentErrorConfig: ErrorHandlingConfig = { ...defaultErrorConfig };\n\n/**\n * 에러 로그 엔트리\n */\ninterface ErrorLogEntry {\n error: ContextActionError;\n count: number;\n lastOccurred: number;\n}\n\n/**\n * 에러 로그 저장소\n */\nlet errorLog: ErrorLogEntry[] = [];\nlet errorSignatures: Map<string, ErrorLogEntry> = new Map();\n\n/**\n * 에러 핸들링 설정 업데이트\n */\nexport function setErrorHandlingConfig(config: Partial<ErrorHandlingConfig>): void {\n currentErrorConfig = { ...currentErrorConfig, ...config };\n}\n\n/**\n * 현재 에러 핸들링 설정 가져오기\n */\nexport function getErrorHandlingConfig(): ErrorHandlingConfig {\n return { ...currentErrorConfig };\n}\n\n/**\n * 에러 시그니처 생성 (중복 에러 감지용)\n */\nfunction createErrorSignature(error: ContextActionError): string {\n return `${error.type}:${error.message}:${error.context?.component || 'unknown'}`;\n}\n\n/**\n * 표준화된 에러 처리 함수 (통합된 에러 바운더리 사용)\n */\nexport function handleError(\n type: ContextActionErrorType,\n message: string,\n context?: Record<string, unknown>,\n originalError?: Error\n): ContextActionError {\n const error = new ContextActionError(type, message, context, originalError);\n \n // 에러 로깅\n logError(error);\n \n // 설정에 따라 에러 throw\n if (currentErrorConfig.throwOnError) {\n throw error;\n }\n \n return error;\n}\n\n\n/**\n * 에러 로깅 함수\n */\nfunction logError(error: ContextActionError): void {\n const signature = createErrorSignature(error);\n \n // 중복 에러 억제 설정이 활성화된 경우\n if (currentErrorConfig.suppressRepeatedErrors) {\n const existingEntry = errorSignatures.get(signature);\n if (existingEntry) {\n existingEntry.count++;\n existingEntry.lastOccurred = Date.now();\n \n // 중복 에러는 덜 자주 로깅\n if (existingEntry.count % 10 === 0) {\n console.warn(\n `[Context-Action] Repeated error occurred ${existingEntry.count} times:`,\n error\n );\n }\n return;\n }\n }\n \n // 새 에러 엔트리 생성\n const logEntry: ErrorLogEntry = {\n error,\n count: 1,\n lastOccurred: Date.now()\n };\n \n // 에러 로그에 추가\n errorLog.push(logEntry);\n errorSignatures.set(signature, logEntry);\n \n // 로그 크기 제한\n if (errorLog.length > currentErrorConfig.maxLogEntries) {\n const removedEntry = errorLog.shift();\n if (removedEntry) {\n const removedSignature = createErrorSignature(removedEntry.error);\n errorSignatures.delete(removedSignature);\n }\n }\n\n // globalErrorBoundary에 에러 보고 (테스트 환경에서 사용)\n if (typeof globalThis !== 'undefined' && (globalThis as any).globalErrorBoundary) {\n (globalThis as any).globalErrorBoundary.reportError(error);\n }\n \n // 로그 레벨에 따른 출력\n switch (currentErrorConfig.logLevel) {\n case ErrorLogLevel.DEBUG:\n console.debug('[Context-Action] Debug:', error);\n break;\n case ErrorLogLevel.INFO:\n console.info('[Context-Action] Info:', error);\n break;\n case ErrorLogLevel.WARN:\n console.warn('[Context-Action] Warning:', error);\n break;\n case ErrorLogLevel.ERROR:\n console.error('[Context-Action] Error:', error);\n if (currentErrorConfig.enableStackTrace && error.stack) {\n console.error('Stack trace:', error.stack);\n }\n break;\n case ErrorLogLevel.SILENT:\n // 무음 모드\n break;\n }\n}\n\n\n\n/**\n * 특정 에러 타입에 대한 전용 핸들러들\n */\nexport const ErrorHandlers = {\n /**\n * Store 관련 에러 처리\n */\n store: (message: string, context?: Record<string, unknown>, originalError?: Error) => {\n const enhancedMessage = `[Store Error] ${message}\\nContext: ${JSON.stringify(context, null, 2)}`;\n return handleError(ContextActionErrorType.STORE_ERROR, enhancedMessage, context, originalError);\n },\n \n /**\n * Action 관련 에러 처리\n */\n action: (message: string, context?: Record<string, unknown>, originalError?: Error) => {\n const enhancedMessage = `[Action Error] ${message}\\nContext: ${JSON.stringify(context, null, 2)}`;\n return handleError(ContextActionErrorType.ACTION_ERROR, enhancedMessage, context, originalError);\n },\n \n /**\n * Ref 관련 에러 처리\n */\n ref: (message: string, context?: Record<string, unknown>, originalError?: Error) => {\n const enhancedMessage = `[Ref Error] ${message}\\nContext: ${JSON.stringify(context, null, 2)}`;\n return handleError(ContextActionErrorType.REF_ERROR, enhancedMessage, context, originalError);\n },\n \n /**\n * 검증 관련 에러 처리\n */\n validation: (message: string, context?: Record<string, unknown>, originalError?: Error) => {\n const enhancedMessage = `[Validation Error] ${message}\\nContext: ${JSON.stringify(context, null, 2)}`;\n return handleError(ContextActionErrorType.VALIDATION_ERROR, enhancedMessage, context, originalError);\n },\n \n /**\n * 초기화 관련 에러 처리\n */\n initialization: (message: string, context?: Record<string, unknown>, originalError?: Error) => {\n const enhancedMessage = `[Initialization Error] ${message}\\nContext: ${JSON.stringify(context, null, 2)}`;\n return handleError(ContextActionErrorType.INITIALIZATION_ERROR, enhancedMessage, context, originalError);\n },\n \n /**\n * 타임아웃 관련 에러 처리\n */\n timeout: (message: string, context?: Record<string, unknown>, originalError?: Error) => {\n const enhancedMessage = `[Timeout Error] ${message}\\nContext: ${JSON.stringify(context, null, 2)}`;\n return handleError(ContextActionErrorType.TIMEOUT_ERROR, enhancedMessage, context, originalError);\n },\n \n /**\n * 순환 참조 관련 에러 처리\n */\n circularReference: (message: string, context?: Record<string, unknown>, originalError?: Error) =>\n handleError(ContextActionErrorType.CIRCULAR_REFERENCE_ERROR, message, context, originalError)\n} as const;\n\n/**\n * 에러 로그 통계 정보\n */\nexport interface ErrorStatistics {\n totalErrors: number;\n errorsByType: Record<ContextActionErrorType, number>;\n mostFrequentErrors: Array<{\n signature: string;\n count: number;\n lastOccurred: number;\n }>;\n recentErrors: ContextActionError[];\n}\n\n/**\n * 에러 통계 가져오기\n */\nexport function getErrorStatistics(): ErrorStatistics {\n const errorsByType = Object.values(ContextActionErrorType).reduce((acc, type) => {\n acc[type] = 0;\n return acc;\n }, {} as Record<ContextActionErrorType, number>);\n \n // 타입별 에러 카운트\n errorLog.forEach(entry => {\n errorsByType[entry.error.type] += entry.count;\n });\n \n // 가장 빈번한 에러들\n const mostFrequentErrors = Array.from(errorSignatures.entries())\n .map(([signature, entry]) => ({\n signature,\n count: entry.count,\n lastOccurred: entry.lastOccurred\n }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n \n // 최근 에러들 (최근 10개)\n const recentErrors = errorLog\n .slice(-10)\n .map(entry => entry.error);\n \n return {\n totalErrors: errorLog.reduce((sum, entry) => sum + entry.count, 0),\n errorsByType,\n mostFrequentErrors,\n recentErrors\n };\n}\n\n\n"],"mappings":"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"} |
| //#region rolldown:runtime | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| //#endregion | ||
| let immer = require("immer"); | ||
| immer = __toESM(immer); | ||
| //#region src/stores/utils/immutable.ts | ||
| (0, immer.enableMapSet)(); | ||
| /** | ||
| * Check if value is a primitive type | ||
| */ | ||
| function isPrimitive(value) { | ||
| return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "symbol"; | ||
| } | ||
| /** | ||
| * Check if value is a complex object that needs Immer | ||
| */ | ||
| function isComplexObject(value) { | ||
| if (!value || typeof value !== "object") return false; | ||
| if (Array.isArray(value)) return true; | ||
| if (value.constructor === Object) { | ||
| const obj = value; | ||
| return Object.values(obj).some((val) => typeof val === "object" && val !== null); | ||
| } | ||
| return value.constructor !== Object; | ||
| } | ||
| const logger = { | ||
| warn: (message, ...args) => console.warn(`[Context-Action] ${message}`, ...args), | ||
| trace: (message, ...args) => console.trace(`[Context-Action] ${message}`, ...args), | ||
| error: (message, ...args) => console.error(`[Context-Action] ${message}`, ...args), | ||
| debug: (message, ...args) => console.debug(`[Context-Action] ${message}`, ...args) | ||
| }; | ||
| /** | ||
| * 전역 불변성 설정 | ||
| */ | ||
| let globalImmutabilityOptions = { | ||
| enableCloning: true, | ||
| enableVerification: process.env.NODE_ENV === "development", | ||
| warnOnFallback: true | ||
| }; | ||
| /** | ||
| * 복사하지 않아야 할 특별한 객체 타입들을 확인 | ||
| */ | ||
| function isNonCloneableType(value) { | ||
| if (!value || typeof value !== "object") return false; | ||
| if (typeof Element !== "undefined" && value instanceof Element) return true; | ||
| if (typeof Node !== "undefined" && value instanceof Node) return true; | ||
| if (typeof HTMLElement !== "undefined" && value instanceof HTMLElement) return true; | ||
| const record = value; | ||
| if (typeof record.nodeType === "number" && record.nodeType > 0) return true; | ||
| if (typeof record.nodeName === "string") return true; | ||
| if (typeof record.tagName === "string") return true; | ||
| if (record._owner !== void 0 || record.stateNode !== void 0) return true; | ||
| if (typeof value === "function") return true; | ||
| if (value instanceof Promise) return true; | ||
| if (typeof record.then === "function" && typeof record.catch === "function") return true; | ||
| if (value instanceof WeakMap || value instanceof WeakSet) return true; | ||
| return false; | ||
| } | ||
| /** | ||
| * 최적화된 Immer 기반 깊은 복사 | ||
| * Tree-shaking과 성능을 고려한 구현 | ||
| * | ||
| * @template T 복사할 값의 타입 | ||
| * @param value 복사할 값 | ||
| * @param options 복사 옵션 | ||
| * @returns 불변성이 보장된 복사본 | ||
| */ | ||
| function deepClone(value, _options) { | ||
| if (isPrimitive(value)) return value; | ||
| if (typeof value === "function") { | ||
| if (process.env.NODE_ENV === "development") logger.warn("Functions cannot be deep cloned, returning original reference"); | ||
| return value; | ||
| } | ||
| if (isNonCloneableType(value)) return value; | ||
| if (typeof value === "object" && value !== null && "__contextActionRefState" in value && value.__contextActionRefState === true) return value; | ||
| try { | ||
| return (0, immer.produce)(value, (_draft) => {}); | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") logger.warn("Immer produce failed, falling back to native methods", error); | ||
| } | ||
| if (typeof structuredClone !== "undefined") try { | ||
| return structuredClone(value); | ||
| } catch {} | ||
| if (!isComplexObject(value)) return simpleClone(value); | ||
| return fallbackClone(value); | ||
| } | ||
| /** | ||
| * Synchronous version with Immer - same as deepClone but with explicit Immer focus | ||
| */ | ||
| function deepCloneWithImmer(value) { | ||
| if (isPrimitive(value)) return value; | ||
| if (isNonCloneableType(value) || typeof value === "function") return value; | ||
| try { | ||
| return (0, immer.produce)(value, (_draft) => {}); | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") logger.warn("Immer produce failed, falling back to simple clone", error); | ||
| return fallbackClone(value); | ||
| } | ||
| } | ||
| /** | ||
| * 간단한 객체인지 확인 | ||
| */ | ||
| function isSimpleObject(value) { | ||
| return typeof value === "object" && value !== null && value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype; | ||
| } | ||
| /** | ||
| * 성능 최적화된 간단한 객체 복사 | ||
| */ | ||
| function simpleClone(value, visited = /* @__PURE__ */ new WeakSet()) { | ||
| if (typeof value === "object" && value !== null && visited.has(value)) return "[Circular]"; | ||
| if (Array.isArray(value)) { | ||
| visited.add(value); | ||
| return value.map((item) => { | ||
| if (typeof item === "object" && item !== null) if ("__contextActionRefState" in item && item.__contextActionRefState === true) return item; | ||
| else return simpleClone(item, visited); | ||
| return item; | ||
| }); | ||
| } | ||
| if (isSimpleObject(value)) { | ||
| visited.add(value); | ||
| const cloned = {}; | ||
| for (const [key, val] of Object.entries(value)) if (typeof val === "object" && val !== null) if ("__contextActionRefState" in val && val.__contextActionRefState === true) cloned[key] = val; | ||
| else cloned[key] = simpleClone(val, visited); | ||
| else cloned[key] = val; | ||
| return cloned; | ||
| } | ||
| return value; | ||
| } | ||
| /** | ||
| * 폴백 복사 함수 (Immer가 실패한 경우) | ||
| */ | ||
| function fallbackClone(value) { | ||
| try { | ||
| const visited = /* @__PURE__ */ new WeakSet(); | ||
| const refStateObjects = /* @__PURE__ */ new Map(); | ||
| let refStateId = 0; | ||
| const collectRefStates = (obj) => { | ||
| if (typeof obj !== "object" || obj === null || visited.has(obj)) return; | ||
| visited.add(obj); | ||
| if ("__contextActionRefState" in obj && obj.__contextActionRefState === true) { | ||
| const id = `refstate_${refStateId++}`; | ||
| refStateObjects.set(id, obj); | ||
| } | ||
| try { | ||
| if (Array.isArray(obj)) obj.forEach(collectRefStates); | ||
| else for (const val of Object.values(obj)) collectRefStates(val); | ||
| } catch {} | ||
| }; | ||
| try { | ||
| collectRefStates(value); | ||
| } catch {} | ||
| const circularSafeStringify = (obj) => { | ||
| const jsonVisited = /* @__PURE__ */ new WeakSet(); | ||
| return JSON.stringify(obj, function(key, val) { | ||
| if (val !== null && typeof val === "object") { | ||
| if (jsonVisited.has(val)) return "[Circular]"; | ||
| jsonVisited.add(val); | ||
| if ("__contextActionRefState" in val && val.__contextActionRefState === true) { | ||
| const entries = Array.from(refStateObjects.entries()); | ||
| for (let i = 0; i < entries.length; i++) { | ||
| const entry = entries[i]; | ||
| if (entry && entry[1] === val) return { __REFSTATE_PLACEHOLDER__: entry[0] }; | ||
| } | ||
| } | ||
| } | ||
| return val; | ||
| }); | ||
| }; | ||
| const jsonString = circularSafeStringify(value); | ||
| const parsed = JSON.parse(jsonString); | ||
| const restoreRefStates = (obj) => { | ||
| if (typeof obj !== "object" || obj === null) return obj; | ||
| if (obj.__REFSTATE_PLACEHOLDER__ && refStateObjects.has(obj.__REFSTATE_PLACEHOLDER__)) return refStateObjects.get(obj.__REFSTATE_PLACEHOLDER__); | ||
| if (Array.isArray(obj)) return obj.map(restoreRefStates); | ||
| const result = {}; | ||
| for (const [key, val] of Object.entries(obj)) result[key] = restoreRefStates(val); | ||
| return result; | ||
| }; | ||
| return restoreRefStates(parsed); | ||
| } catch (jsonError) { | ||
| if (process.env.NODE_ENV === "development") logger.error("All cloning methods failed, returning original reference", jsonError); | ||
| return value; | ||
| } | ||
| } | ||
| /** | ||
| * 불변성 검증 함수 - 복사본이 원본과 독립적인지 확인 | ||
| * | ||
| * @param original 원본 값 | ||
| * @param cloned 복사된 값 | ||
| * @returns 불변성이 보장되면 true, 아니면 false | ||
| */ | ||
| function verifyImmutability(original, cloned) { | ||
| if (original === null || original === void 0 || typeof original === "string" || typeof original === "number" || typeof original === "boolean" || typeof original === "bigint" || typeof original === "symbol") return original === cloned; | ||
| if (isNonCloneableType(original)) return original === cloned; | ||
| if (typeof original === "function") return original === cloned; | ||
| if (typeof original === "object" && original !== null) return true; | ||
| return false; | ||
| } | ||
| /** | ||
| * 안전한 getter - 불변성을 보장하는 값 반환 | ||
| * | ||
| * @template T 값의 타입 | ||
| * @param value 반환할 값 | ||
| * @param enableCloning 복사 활성화 여부 (기본: true) | ||
| * @returns 불변성이 보장된 값 | ||
| */ | ||
| function safeGet(value, enableCloning = true) { | ||
| if (!enableCloning) return value; | ||
| if (isPrimitive(value)) return value; | ||
| if (isNonCloneableType(value)) return value; | ||
| if (typeof value === "object" && value !== null && "__contextActionRefState" in value && value.__contextActionRefState === true) return value; | ||
| const cloned = deepClone(value); | ||
| if (process.env.NODE_ENV === "development" && globalImmutabilityOptions.enableVerification) { | ||
| if (!isNonCloneableType(value)) { | ||
| if (!verifyImmutability(value, cloned) && typeof value === "object" && value !== null) { | ||
| if (Math.random() < .01) logger.debug("Immer optimization: same reference returned for unchanged object", { | ||
| type: typeof value, | ||
| constructor: value?.constructor?.name, | ||
| isArray: Array.isArray(value) | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| return cloned; | ||
| } | ||
| /** | ||
| * 안전한 setter - 입력값의 불변성을 보장하는 값 설정 | ||
| * | ||
| * @template T 값의 타입 | ||
| * @param value 설정할 값 | ||
| * @param enableCloning 복사 활성화 여부 (기본: true) | ||
| * @returns 불변성이 보장된 값 | ||
| */ | ||
| function safeSet(value, enableCloning = true) { | ||
| if (!enableCloning) { | ||
| if (process.env.NODE_ENV === "development") logger.trace("Cloning disabled for setter, returning original reference"); | ||
| return value; | ||
| } | ||
| return deepClone(value); | ||
| } | ||
| /** | ||
| * Immer utilities using static imports | ||
| * Provides the same API as the dynamic version but with immediate availability | ||
| */ | ||
| const ImmerUtils = { | ||
| isDraft(value) { | ||
| return (0, immer.isDraft)(value); | ||
| }, | ||
| original(value) { | ||
| return (0, immer.original)(value); | ||
| }, | ||
| current(value) { | ||
| return (0, immer.current)(value); | ||
| }, | ||
| produce(baseState, producer) { | ||
| return (0, immer.produce)(baseState, producer); | ||
| } | ||
| }; | ||
| function preloadImmer() {} | ||
| /** | ||
| * Synchronous produce using static Immer import | ||
| * Direct wrapper around Immer's produce function | ||
| */ | ||
| function produce(baseState, producer) { | ||
| try { | ||
| return (0, immer.produce)(baseState, producer); | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") logger.warn("Immer produce failed, falling back to deep clone simulation", error); | ||
| try { | ||
| const draft = deepClone(baseState); | ||
| const result = producer(draft); | ||
| return result !== void 0 ? result : draft; | ||
| } catch (fallbackError) { | ||
| if (process.env.NODE_ENV === "development") logger.error("Produce fallback failed, returning original state", fallbackError); | ||
| return baseState; | ||
| } | ||
| } | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/comparison.ts | ||
| const DEFAULT_COMPARISON_OPTIONS = { | ||
| strategy: "reference", | ||
| maxDepth: 5, | ||
| enableCircularCheck: true | ||
| }; | ||
| let globalComparisonOptions = { ...DEFAULT_COMPARISON_OPTIONS }; | ||
| function setGlobalComparisonOptions(options) { | ||
| globalComparisonOptions = { | ||
| ...DEFAULT_COMPARISON_OPTIONS, | ||
| ...options | ||
| }; | ||
| } | ||
| function getGlobalComparisonOptions() { | ||
| return { ...globalComparisonOptions }; | ||
| } | ||
| function referenceEquals(oldValue, newValue) { | ||
| return Object.is(oldValue, newValue); | ||
| } | ||
| function shallowEquals(oldValue, newValue, ignoreKeys = []) { | ||
| if (Object.is(oldValue, newValue)) return true; | ||
| if (oldValue == null || newValue == null) return oldValue === newValue; | ||
| if (typeof oldValue !== "object" || typeof newValue !== "object") return oldValue === newValue; | ||
| if (Array.isArray(oldValue) && Array.isArray(newValue)) { | ||
| if (oldValue.length !== newValue.length) return false; | ||
| for (let i = 0; i < oldValue.length; i++) if (!Object.is(oldValue[i], newValue[i])) return false; | ||
| return true; | ||
| } | ||
| const oldKeys = Object.keys(oldValue).filter((key) => !ignoreKeys.includes(key)); | ||
| const newKeys = Object.keys(newValue).filter((key) => !ignoreKeys.includes(key)); | ||
| if (oldKeys.length !== newKeys.length) return false; | ||
| for (const key of oldKeys) { | ||
| if (!newKeys.includes(key)) return false; | ||
| if (!Object.is(oldValue[key], newValue[key])) return false; | ||
| } | ||
| return true; | ||
| } | ||
| function deepEquals(oldValue, newValue, options = {}) { | ||
| const { maxDepth = 5, ignoreKeys = [], enableCircularCheck = true } = options; | ||
| const visitedPairs = enableCircularCheck ? /* @__PURE__ */ new WeakMap() : null; | ||
| function deepCompare(a, b, depth, path = "") { | ||
| if (depth > maxDepth) return Object.is(a, b); | ||
| if (Object.is(a, b)) return true; | ||
| if (a == null || b == null) return a === b; | ||
| if (typeof a !== typeof b) return false; | ||
| if (typeof a !== "object") return a === b; | ||
| if (visitedPairs && typeof a === "object" && typeof b === "object" && a !== null && b !== null) { | ||
| if (visitedPairs.has(a)) { | ||
| if (visitedPairs.get(a).has(b)) return Object.is(a, b); | ||
| } | ||
| if (!visitedPairs.has(a)) visitedPairs.set(a, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(a).add(b); | ||
| if (!visitedPairs.has(b)) visitedPairs.set(b, /* @__PURE__ */ new WeakSet()); | ||
| visitedPairs.get(b).add(a); | ||
| } | ||
| if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); | ||
| if (a instanceof RegExp && b instanceof RegExp) return a.toString() === b.toString(); | ||
| if (Array.isArray(a) && Array.isArray(b)) { | ||
| if (a.length !== b.length) return false; | ||
| for (let i = 0; i < a.length; i++) if (!deepCompare(a[i], b[i], depth + 1, `${path}[${i}]`)) return false; | ||
| return true; | ||
| } | ||
| if (Array.isArray(a) || Array.isArray(b)) return false; | ||
| const aKeys = Object.keys(a).filter((key) => !ignoreKeys.includes(key)); | ||
| const bKeys = Object.keys(b).filter((key) => !ignoreKeys.includes(key)); | ||
| if (aKeys.length !== bKeys.length) return false; | ||
| for (const key of aKeys) { | ||
| if (!bKeys.includes(key)) return false; | ||
| if (!deepCompare(a[key], b[key], depth + 1, `${path}.${key}`)) return false; | ||
| } | ||
| return true; | ||
| } | ||
| return deepCompare(oldValue, newValue, 0); | ||
| } | ||
| function compareValues(oldValue, newValue, options = {}) { | ||
| const { strategy, customComparator, maxDepth, ignoreKeys, enableCircularCheck } = { | ||
| ...globalComparisonOptions, | ||
| ...options | ||
| }; | ||
| let result; | ||
| try { | ||
| if (strategy !== "reference" && strategy !== "custom" && typeof oldValue === "object" && typeof newValue === "object") try { | ||
| const oldStr = JSON.stringify(oldValue); | ||
| const newStr = JSON.stringify(newValue); | ||
| if (oldStr.length < 1e3 && newStr.length < 1e3) { | ||
| result = oldStr === newStr; | ||
| return result; | ||
| } | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") console.debug("[ComparisonOptimization] JSON serialization failed, falling back to original strategy:", error); | ||
| } | ||
| switch (strategy) { | ||
| case "reference": | ||
| result = referenceEquals(oldValue, newValue); | ||
| break; | ||
| case "shallow": | ||
| result = shallowEquals(oldValue, newValue, ignoreKeys); | ||
| break; | ||
| case "deep": | ||
| result = deepEquals(oldValue, newValue, { | ||
| ...maxDepth !== void 0 && { maxDepth }, | ||
| ...ignoreKeys !== void 0 && { ignoreKeys }, | ||
| ...enableCircularCheck !== void 0 && { enableCircularCheck } | ||
| }); | ||
| break; | ||
| case "custom": | ||
| if (!customComparator) result = referenceEquals(oldValue, newValue); | ||
| else result = customComparator(oldValue, newValue); | ||
| break; | ||
| default: result = referenceEquals(oldValue, newValue); | ||
| } | ||
| } catch (error) { | ||
| if (process.env.NODE_ENV === "development") console.warn("[CompareValues] Comparison failed, falling back to reference equality:", error); | ||
| result = referenceEquals(oldValue, newValue); | ||
| } | ||
| return result; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/error-handling.ts | ||
| /** | ||
| * @fileoverview Error Handling Utilities | ||
| * | ||
| * 일관된 에러 처리를 위한 유틸리티 함수들 | ||
| * Context-Action 프레임워크 전반에 걸친 표준화된 에러 처리 패턴 | ||
| */ | ||
| /** | ||
| * Context-Action 프레임워크의 에러 유형 정의 | ||
| */ | ||
| let ContextActionErrorType = /* @__PURE__ */ function(ContextActionErrorType$1) { | ||
| ContextActionErrorType$1["STORE_ERROR"] = "STORE_ERROR"; | ||
| ContextActionErrorType$1["ACTION_ERROR"] = "ACTION_ERROR"; | ||
| ContextActionErrorType$1["REF_ERROR"] = "REF_ERROR"; | ||
| ContextActionErrorType$1["VALIDATION_ERROR"] = "VALIDATION_ERROR"; | ||
| ContextActionErrorType$1["INITIALIZATION_ERROR"] = "INITIALIZATION_ERROR"; | ||
| ContextActionErrorType$1["TIMEOUT_ERROR"] = "TIMEOUT_ERROR"; | ||
| ContextActionErrorType$1["CIRCULAR_REFERENCE_ERROR"] = "CIRCULAR_REFERENCE_ERROR"; | ||
| return ContextActionErrorType$1; | ||
| }({}); | ||
| /** | ||
| * Context-Action 프레임워크의 표준 에러 클래스 | ||
| */ | ||
| var ContextActionError = class ContextActionError extends Error { | ||
| constructor(type, message, context, originalError) { | ||
| super(message); | ||
| this.name = "ContextActionError"; | ||
| this.type = type; | ||
| this.context = context ?? void 0; | ||
| this.timestamp = Date.now(); | ||
| if (Error.captureStackTrace) Error.captureStackTrace(this, ContextActionError); | ||
| if (originalError) this.stack = `${this.stack}\nCaused by: ${originalError.stack}`; | ||
| } | ||
| }; | ||
| /** | ||
| * 에러 로깅 레벨 | ||
| */ | ||
| let ErrorLogLevel = /* @__PURE__ */ function(ErrorLogLevel$1) { | ||
| ErrorLogLevel$1[ErrorLogLevel$1["SILENT"] = 0] = "SILENT"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["ERROR"] = 1] = "ERROR"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["WARN"] = 2] = "WARN"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["INFO"] = 3] = "INFO"; | ||
| ErrorLogLevel$1[ErrorLogLevel$1["DEBUG"] = 4] = "DEBUG"; | ||
| return ErrorLogLevel$1; | ||
| }({}); | ||
| /** | ||
| * 현재 에러 핸들링 설정 | ||
| */ | ||
| let currentErrorConfig = { | ||
| logLevel: process.env.NODE_ENV === "development" ? ErrorLogLevel.DEBUG : ErrorLogLevel.ERROR, | ||
| throwOnError: process.env.NODE_ENV === "development", | ||
| enableStackTrace: true, | ||
| maxLogEntries: 100, | ||
| suppressRepeatedErrors: true, | ||
| logErrors: true | ||
| }; | ||
| /** | ||
| * 에러 로그 저장소 | ||
| */ | ||
| let errorLog = []; | ||
| let errorSignatures = /* @__PURE__ */ new Map(); | ||
| /** | ||
| * 에러 시그니처 생성 (중복 에러 감지용) | ||
| */ | ||
| function createErrorSignature(error) { | ||
| return `${error.type}:${error.message}:${error.context?.component || "unknown"}`; | ||
| } | ||
| /** | ||
| * 표준화된 에러 처리 함수 (통합된 에러 바운더리 사용) | ||
| */ | ||
| function handleError(type, message, context, originalError) { | ||
| const error = new ContextActionError(type, message, context, originalError); | ||
| logError(error); | ||
| if (currentErrorConfig.throwOnError) throw error; | ||
| return error; | ||
| } | ||
| /** | ||
| * 에러 로깅 함수 | ||
| */ | ||
| function logError(error) { | ||
| const signature = createErrorSignature(error); | ||
| if (currentErrorConfig.suppressRepeatedErrors) { | ||
| const existingEntry = errorSignatures.get(signature); | ||
| if (existingEntry) { | ||
| existingEntry.count++; | ||
| existingEntry.lastOccurred = Date.now(); | ||
| if (existingEntry.count % 10 === 0) console.warn(`[Context-Action] Repeated error occurred ${existingEntry.count} times:`, error); | ||
| return; | ||
| } | ||
| } | ||
| const logEntry = { | ||
| error, | ||
| count: 1, | ||
| lastOccurred: Date.now() | ||
| }; | ||
| errorLog.push(logEntry); | ||
| errorSignatures.set(signature, logEntry); | ||
| if (errorLog.length > currentErrorConfig.maxLogEntries) { | ||
| const removedEntry = errorLog.shift(); | ||
| if (removedEntry) { | ||
| const removedSignature = createErrorSignature(removedEntry.error); | ||
| errorSignatures.delete(removedSignature); | ||
| } | ||
| } | ||
| if (typeof globalThis !== "undefined" && globalThis.globalErrorBoundary) globalThis.globalErrorBoundary.reportError(error); | ||
| switch (currentErrorConfig.logLevel) { | ||
| case ErrorLogLevel.DEBUG: | ||
| console.debug("[Context-Action] Debug:", error); | ||
| break; | ||
| case ErrorLogLevel.INFO: | ||
| console.info("[Context-Action] Info:", error); | ||
| break; | ||
| case ErrorLogLevel.WARN: | ||
| console.warn("[Context-Action] Warning:", error); | ||
| break; | ||
| case ErrorLogLevel.ERROR: | ||
| console.error("[Context-Action] Error:", error); | ||
| if (currentErrorConfig.enableStackTrace && error.stack) console.error("Stack trace:", error.stack); | ||
| break; | ||
| case ErrorLogLevel.SILENT: break; | ||
| } | ||
| } | ||
| /** | ||
| * 특정 에러 타입에 대한 전용 핸들러들 | ||
| */ | ||
| const ErrorHandlers = { | ||
| store: (message, context, originalError) => { | ||
| const enhancedMessage = `[Store Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.STORE_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| action: (message, context, originalError) => { | ||
| const enhancedMessage = `[Action Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.ACTION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| ref: (message, context, originalError) => { | ||
| const enhancedMessage = `[Ref Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.REF_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| validation: (message, context, originalError) => { | ||
| const enhancedMessage = `[Validation Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.VALIDATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| initialization: (message, context, originalError) => { | ||
| const enhancedMessage = `[Initialization Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.INITIALIZATION_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| timeout: (message, context, originalError) => { | ||
| const enhancedMessage = `[Timeout Error] ${message}\nContext: ${JSON.stringify(context, null, 2)}`; | ||
| return handleError(ContextActionErrorType.TIMEOUT_ERROR, enhancedMessage, context, originalError); | ||
| }, | ||
| circularReference: (message, context, originalError) => handleError(ContextActionErrorType.CIRCULAR_REFERENCE_ERROR, message, context, originalError) | ||
| }; | ||
| /** | ||
| * 에러 통계 가져오기 | ||
| */ | ||
| function getErrorStatistics() { | ||
| const errorsByType = Object.values(ContextActionErrorType).reduce((acc, type) => { | ||
| acc[type] = 0; | ||
| return acc; | ||
| }, {}); | ||
| errorLog.forEach((entry) => { | ||
| errorsByType[entry.error.type] += entry.count; | ||
| }); | ||
| const mostFrequentErrors = Array.from(errorSignatures.entries()).map(([signature, entry]) => ({ | ||
| signature, | ||
| count: entry.count, | ||
| lastOccurred: entry.lastOccurred | ||
| })).sort((a, b) => b.count - a.count).slice(0, 10); | ||
| const recentErrors = errorLog.slice(-10).map((entry) => entry.error); | ||
| return { | ||
| totalErrors: errorLog.reduce((sum, entry) => sum + entry.count, 0), | ||
| errorsByType, | ||
| mostFrequentErrors, | ||
| recentErrors | ||
| }; | ||
| } | ||
| //#endregion | ||
| Object.defineProperty(exports, 'ContextActionError', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return ContextActionError; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'ContextActionErrorType', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return ContextActionErrorType; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'ErrorHandlers', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return ErrorHandlers; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'ImmerUtils', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return ImmerUtils; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, '__toESM', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __toESM; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'compareValues', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return compareValues; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'deepClone', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return deepClone; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'deepCloneWithImmer', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return deepCloneWithImmer; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'getErrorStatistics', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return getErrorStatistics; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'getGlobalComparisonOptions', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return getGlobalComparisonOptions; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'handleError', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return handleError; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'preloadImmer', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return preloadImmer; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'produce', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return produce; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'safeGet', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return safeGet; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'safeSet', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return safeSet; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'setGlobalComparisonOptions', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return setGlobalComparisonOptions; | ||
| } | ||
| }); |
| //#region src/stores/core/types.d.ts | ||
| type Listener = () => void; | ||
| type Unsubscribe = () => void; | ||
| type Subscribe = (listener: Listener) => Unsubscribe; | ||
| interface Snapshot<T = unknown> { | ||
| value: T; | ||
| name: string; | ||
| lastUpdate: number; | ||
| version?: number; | ||
| isValid?: boolean; | ||
| validationError?: string; | ||
| metrics?: { | ||
| creationTime: number; | ||
| sizeEstimate?: number; | ||
| notificationCount?: number; | ||
| }; | ||
| security?: { | ||
| validated: boolean; | ||
| sanitized?: boolean; | ||
| trustLevel?: number; | ||
| }; | ||
| } | ||
| interface IStore<T = unknown> { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Snapshot<T>; | ||
| setValue: (value: T, options?: StoreSetValueOptions<T>) => void; | ||
| update: (updater: (current: T) => T) => void; | ||
| getValue: () => T; | ||
| getListenerCount?: () => number; | ||
| dispose?: () => void; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| isStoreDisposed?: () => boolean; | ||
| getMetrics?: () => StoreMetrics; | ||
| resetMetrics?: () => void; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| getSecurityOptions?: () => SecurityOptions | undefined; | ||
| } | ||
| interface IStoreRegistry { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Array<[string, IStore]>; | ||
| register: (name: string, store: IStore, metadata?: StoreMetadata$1) => void; | ||
| unregister: (name: string) => boolean; | ||
| getStore: (name: string) => IStore | undefined; | ||
| getAllStores: () => Map<string, IStore>; | ||
| hasStore: (name: string) => boolean; | ||
| getStoreCount: () => number; | ||
| getStoreNames: () => string[]; | ||
| clear: () => void; | ||
| forEach: (callback: (store: IStore, name: string) => void) => void; | ||
| dispose?: () => void; | ||
| isDisposed?: () => boolean; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| getHealthStatus?: () => { | ||
| totalStores: number; | ||
| healthyStores: number; | ||
| errorStores: number; | ||
| disposedStores: number; | ||
| memoryUsage?: number; | ||
| }; | ||
| performHealthCheck?: () => Promise<Map<string, boolean>>; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| setAutoCleanup?: (enabled: boolean) => void; | ||
| } | ||
| interface StoreSyncConfig<T, R = Snapshot<T>> { | ||
| defaultValue?: T; | ||
| selector?: (snapshot: Snapshot<T>) => R; | ||
| isEqual?: (prev: R, next: R) => boolean; | ||
| errorBoundary?: boolean; | ||
| suspense?: boolean; | ||
| } | ||
| interface HookOptions<T> { | ||
| defaultValue?: T; | ||
| onError?: (error: Error, retryCount?: number) => void | boolean; | ||
| dependencies?: React.DependencyList; | ||
| enableRetry?: boolean; | ||
| maxRetries?: number; | ||
| retryDelay?: number; | ||
| enableMetrics?: boolean; | ||
| throttle?: number; | ||
| debounce?: number; | ||
| } | ||
| interface StoreSetValueOptions<T> { | ||
| skipClone?: boolean; | ||
| skipComparison?: boolean; | ||
| eventHandling?: 'block' | 'transform' | 'allow'; | ||
| eventTransform?: (event: unknown) => T; | ||
| sanitizer?: (value: T) => T; | ||
| validator?: (value: T) => boolean | string; | ||
| } | ||
| interface StoreMetrics { | ||
| totalSets: number; | ||
| totalGets: number; | ||
| totalUpdates: number; | ||
| totalNotifications: number; | ||
| averageOperationTime: number; | ||
| peakListenerCount: number; | ||
| totalErrors: number; | ||
| } | ||
| interface SecurityOptions { | ||
| preventPrototypePollution?: boolean; | ||
| preventXSS?: boolean; | ||
| maxDepth?: number; | ||
| maxStringLength?: number; | ||
| allowedProperties?: RegExp; | ||
| blockedProperties?: RegExp; | ||
| } | ||
| interface StoreMetadata$1 { | ||
| registeredAt?: number; | ||
| name?: string; | ||
| [key: string]: unknown; | ||
| } | ||
| interface DynamicStoreOptions<T> { | ||
| defaultValue?: T; | ||
| createIfNotExists?: boolean; | ||
| onNotFound?: (storeName: string) => void; | ||
| securityOptions?: SecurityOptions; | ||
| autoCleanup?: boolean; | ||
| enableMetrics?: boolean; | ||
| } | ||
| interface React18Options { | ||
| enableDeferred?: boolean; | ||
| enableTransition?: boolean; | ||
| priorityThreshold?: number; | ||
| enableConcurrent?: boolean; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/core/StoreRegistry.d.ts | ||
| interface StoreMetadata { | ||
| registeredAt: number; | ||
| name: string; | ||
| debug?: boolean; | ||
| } | ||
| declare class StoreRegistry implements IStoreRegistry { | ||
| private stores; | ||
| private metadata; | ||
| private listeners; | ||
| private _snapshot; | ||
| readonly name: string; | ||
| constructor(name?: string); | ||
| subscribe(listener: Listener): Unsubscribe; | ||
| register(name: string, store: IStore<any>, metadata?: Partial<StoreMetadata>): void; | ||
| unregister(name: string): boolean; | ||
| getStore(name: string): IStore<any> | undefined; | ||
| hasStore(name: string): boolean; | ||
| getStoreNames(): string[]; | ||
| getAllStores(): Map<string, IStore<any>>; | ||
| getStoreMetadata(nameOrStore: string | IStore<any>): StoreMetadata | undefined; | ||
| updateStoreMetadata(nameOrStore: string | IStore<any>, metadata: Partial<StoreMetadata>): boolean; | ||
| getSnapshot(): Array<[string, IStore<any>]>; | ||
| clear(): void; | ||
| dispose(): void; | ||
| getStoreCount(): number; | ||
| forEach(callback: (store: IStore<any>, name: string) => void): void; | ||
| getStats(): { | ||
| totalStores: number; | ||
| storeNames: string[]; | ||
| registryName: string; | ||
| }; | ||
| private _updateSnapshot; | ||
| private _notifyListeners; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/comparison.d.ts | ||
| type ComparisonStrategy = 'reference' | 'shallow' | 'deep' | 'custom'; | ||
| type CustomComparator<T = unknown> = (oldValue: T, newValue: T) => boolean; | ||
| interface ComparisonOptions<T = unknown> { | ||
| strategy: ComparisonStrategy; | ||
| customComparator?: CustomComparator<T>; | ||
| maxDepth?: number; | ||
| ignoreKeys?: string[]; | ||
| enableCircularCheck?: boolean; | ||
| } | ||
| declare function setGlobalComparisonOptions(options: Partial<ComparisonOptions>): void; | ||
| declare function getGlobalComparisonOptions(): ComparisonOptions; | ||
| declare function compareValues<T>(oldValue: T, newValue: T, options?: Partial<ComparisonOptions<T>>): boolean; | ||
| //#endregion | ||
| //#region src/stores/core/Store.d.ts | ||
| declare class Store<T = unknown> implements IStore<T> { | ||
| private listeners; | ||
| protected _value: T; | ||
| protected _snapshot: Snapshot<T>; | ||
| private _lastClonedValue; | ||
| private _lastClonedVersion; | ||
| private _version; | ||
| private isUpdating; | ||
| private updateQueue; | ||
| private notificationMode; | ||
| private pendingNotification; | ||
| private animationFrameId; | ||
| private pendingUpdatesCount; | ||
| private cleanupTasks; | ||
| private isDisposed; | ||
| private errorCount; | ||
| private lastErrorTime; | ||
| private readonly MAX_ERROR_COUNT; | ||
| private readonly ERROR_RESET_TIME; | ||
| private subscriptionRegistry; | ||
| readonly name: string; | ||
| private customComparator; | ||
| private comparisonOptions; | ||
| private cloningEnabled; | ||
| constructor(name: string, initialValue: T); | ||
| subscribe: (listener: Listener) => Unsubscribe; | ||
| getSnapshot: () => Snapshot<T>; | ||
| getValue(): T; | ||
| setValue(value: T, options?: StoreSetValueOptions<T>): void; | ||
| update(updater: (current: T) => T): void; | ||
| getListenerCount(): number; | ||
| clearListeners(): void; | ||
| registerCleanup(task: () => void): () => void; | ||
| dispose(): void; | ||
| isStoreDisposed(): boolean; | ||
| setCustomComparator(comparator: (oldValue: T, newValue: T) => boolean): void; | ||
| setComparisonOptions(options: Partial<ComparisonOptions<T>>): void; | ||
| setCloningEnabled(enabled: boolean): void; | ||
| isCloningEnabled(): boolean; | ||
| protected _compareValues(oldValue: T, newValue: T): boolean; | ||
| protected _createSnapshot(): Snapshot<T>; | ||
| protected _scheduleNotification(): void; | ||
| private _scheduleWithRAF; | ||
| private _executeNotification; | ||
| private _handleListenerError; | ||
| private _notifyListeners; | ||
| } | ||
| declare function createStore<T>(name: string, initialValue: T): Store<T>; | ||
| //#endregion | ||
| export { ComparisonOptions, ComparisonStrategy, CustomComparator, DynamicStoreOptions, HookOptions, IStore, React18Options, Snapshot, Store, StoreRegistry, StoreSyncConfig, compareValues, createStore, getGlobalComparisonOptions, setGlobalComparisonOptions }; | ||
| //# sourceMappingURL=Store--dj9U0mo.d.cts.map |
| {"version":3,"file":"Store--dj9U0mo.d.cts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/core/StoreRegistry.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"} |
| //#region src/stores/core/types.d.ts | ||
| type Listener = () => void; | ||
| type Unsubscribe = () => void; | ||
| type Subscribe = (listener: Listener) => Unsubscribe; | ||
| interface Snapshot<T = unknown> { | ||
| value: T; | ||
| name: string; | ||
| lastUpdate: number; | ||
| version?: number; | ||
| isValid?: boolean; | ||
| validationError?: string; | ||
| metrics?: { | ||
| creationTime: number; | ||
| sizeEstimate?: number; | ||
| notificationCount?: number; | ||
| }; | ||
| security?: { | ||
| validated: boolean; | ||
| sanitized?: boolean; | ||
| trustLevel?: number; | ||
| }; | ||
| } | ||
| interface IStore<T = unknown> { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Snapshot<T>; | ||
| setValue: (value: T, options?: StoreSetValueOptions<T>) => void; | ||
| update: (updater: (current: T) => T) => void; | ||
| getValue: () => T; | ||
| getListenerCount?: () => number; | ||
| dispose?: () => void; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| isStoreDisposed?: () => boolean; | ||
| getMetrics?: () => StoreMetrics; | ||
| resetMetrics?: () => void; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| getSecurityOptions?: () => SecurityOptions | undefined; | ||
| } | ||
| interface IStoreRegistry { | ||
| readonly name: string; | ||
| subscribe: Subscribe; | ||
| getSnapshot: () => Array<[string, IStore]>; | ||
| register: (name: string, store: IStore, metadata?: StoreMetadata$1) => void; | ||
| unregister: (name: string) => boolean; | ||
| getStore: (name: string) => IStore | undefined; | ||
| getAllStores: () => Map<string, IStore>; | ||
| hasStore: (name: string) => boolean; | ||
| getStoreCount: () => number; | ||
| getStoreNames: () => string[]; | ||
| clear: () => void; | ||
| forEach: (callback: (store: IStore, name: string) => void) => void; | ||
| dispose?: () => void; | ||
| isDisposed?: () => boolean; | ||
| registerCleanup?: (task: () => void) => () => void; | ||
| getHealthStatus?: () => { | ||
| totalStores: number; | ||
| healthyStores: number; | ||
| errorStores: number; | ||
| disposedStores: number; | ||
| memoryUsage?: number; | ||
| }; | ||
| performHealthCheck?: () => Promise<Map<string, boolean>>; | ||
| setSecurityOptions?: (options: SecurityOptions) => void; | ||
| setAutoCleanup?: (enabled: boolean) => void; | ||
| } | ||
| interface StoreSyncConfig<T, R = Snapshot<T>> { | ||
| defaultValue?: T; | ||
| selector?: (snapshot: Snapshot<T>) => R; | ||
| isEqual?: (prev: R, next: R) => boolean; | ||
| errorBoundary?: boolean; | ||
| suspense?: boolean; | ||
| } | ||
| interface HookOptions<T> { | ||
| defaultValue?: T; | ||
| onError?: (error: Error, retryCount?: number) => void | boolean; | ||
| dependencies?: React.DependencyList; | ||
| enableRetry?: boolean; | ||
| maxRetries?: number; | ||
| retryDelay?: number; | ||
| enableMetrics?: boolean; | ||
| throttle?: number; | ||
| debounce?: number; | ||
| } | ||
| interface StoreSetValueOptions<T> { | ||
| skipClone?: boolean; | ||
| skipComparison?: boolean; | ||
| eventHandling?: 'block' | 'transform' | 'allow'; | ||
| eventTransform?: (event: unknown) => T; | ||
| sanitizer?: (value: T) => T; | ||
| validator?: (value: T) => boolean | string; | ||
| } | ||
| interface StoreMetrics { | ||
| totalSets: number; | ||
| totalGets: number; | ||
| totalUpdates: number; | ||
| totalNotifications: number; | ||
| averageOperationTime: number; | ||
| peakListenerCount: number; | ||
| totalErrors: number; | ||
| } | ||
| interface SecurityOptions { | ||
| preventPrototypePollution?: boolean; | ||
| preventXSS?: boolean; | ||
| maxDepth?: number; | ||
| maxStringLength?: number; | ||
| allowedProperties?: RegExp; | ||
| blockedProperties?: RegExp; | ||
| } | ||
| interface StoreMetadata$1 { | ||
| registeredAt?: number; | ||
| name?: string; | ||
| [key: string]: unknown; | ||
| } | ||
| interface DynamicStoreOptions<T> { | ||
| defaultValue?: T; | ||
| createIfNotExists?: boolean; | ||
| onNotFound?: (storeName: string) => void; | ||
| securityOptions?: SecurityOptions; | ||
| autoCleanup?: boolean; | ||
| enableMetrics?: boolean; | ||
| } | ||
| interface React18Options { | ||
| enableDeferred?: boolean; | ||
| enableTransition?: boolean; | ||
| priorityThreshold?: number; | ||
| enableConcurrent?: boolean; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/core/StoreRegistry.d.ts | ||
| interface StoreMetadata { | ||
| registeredAt: number; | ||
| name: string; | ||
| debug?: boolean; | ||
| } | ||
| declare class StoreRegistry implements IStoreRegistry { | ||
| private stores; | ||
| private metadata; | ||
| private listeners; | ||
| private _snapshot; | ||
| readonly name: string; | ||
| constructor(name?: string); | ||
| subscribe(listener: Listener): Unsubscribe; | ||
| register(name: string, store: IStore<any>, metadata?: Partial<StoreMetadata>): void; | ||
| unregister(name: string): boolean; | ||
| getStore(name: string): IStore<any> | undefined; | ||
| hasStore(name: string): boolean; | ||
| getStoreNames(): string[]; | ||
| getAllStores(): Map<string, IStore<any>>; | ||
| getStoreMetadata(nameOrStore: string | IStore<any>): StoreMetadata | undefined; | ||
| updateStoreMetadata(nameOrStore: string | IStore<any>, metadata: Partial<StoreMetadata>): boolean; | ||
| getSnapshot(): Array<[string, IStore<any>]>; | ||
| clear(): void; | ||
| dispose(): void; | ||
| getStoreCount(): number; | ||
| forEach(callback: (store: IStore<any>, name: string) => void): void; | ||
| getStats(): { | ||
| totalStores: number; | ||
| storeNames: string[]; | ||
| registryName: string; | ||
| }; | ||
| private _updateSnapshot; | ||
| private _notifyListeners; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/comparison.d.ts | ||
| type ComparisonStrategy = 'reference' | 'shallow' | 'deep' | 'custom'; | ||
| type CustomComparator<T = unknown> = (oldValue: T, newValue: T) => boolean; | ||
| interface ComparisonOptions<T = unknown> { | ||
| strategy: ComparisonStrategy; | ||
| customComparator?: CustomComparator<T>; | ||
| maxDepth?: number; | ||
| ignoreKeys?: string[]; | ||
| enableCircularCheck?: boolean; | ||
| } | ||
| declare function setGlobalComparisonOptions(options: Partial<ComparisonOptions>): void; | ||
| declare function getGlobalComparisonOptions(): ComparisonOptions; | ||
| declare function compareValues<T>(oldValue: T, newValue: T, options?: Partial<ComparisonOptions<T>>): boolean; | ||
| //#endregion | ||
| //#region src/stores/core/Store.d.ts | ||
| declare class Store<T = unknown> implements IStore<T> { | ||
| private listeners; | ||
| protected _value: T; | ||
| protected _snapshot: Snapshot<T>; | ||
| private _lastClonedValue; | ||
| private _lastClonedVersion; | ||
| private _version; | ||
| private isUpdating; | ||
| private updateQueue; | ||
| private notificationMode; | ||
| private pendingNotification; | ||
| private animationFrameId; | ||
| private pendingUpdatesCount; | ||
| private cleanupTasks; | ||
| private isDisposed; | ||
| private errorCount; | ||
| private lastErrorTime; | ||
| private readonly MAX_ERROR_COUNT; | ||
| private readonly ERROR_RESET_TIME; | ||
| private subscriptionRegistry; | ||
| readonly name: string; | ||
| private customComparator; | ||
| private comparisonOptions; | ||
| private cloningEnabled; | ||
| constructor(name: string, initialValue: T); | ||
| subscribe: (listener: Listener) => Unsubscribe; | ||
| getSnapshot: () => Snapshot<T>; | ||
| getValue(): T; | ||
| setValue(value: T, options?: StoreSetValueOptions<T>): void; | ||
| update(updater: (current: T) => T): void; | ||
| getListenerCount(): number; | ||
| clearListeners(): void; | ||
| registerCleanup(task: () => void): () => void; | ||
| dispose(): void; | ||
| isStoreDisposed(): boolean; | ||
| setCustomComparator(comparator: (oldValue: T, newValue: T) => boolean): void; | ||
| setComparisonOptions(options: Partial<ComparisonOptions<T>>): void; | ||
| setCloningEnabled(enabled: boolean): void; | ||
| isCloningEnabled(): boolean; | ||
| protected _compareValues(oldValue: T, newValue: T): boolean; | ||
| protected _createSnapshot(): Snapshot<T>; | ||
| protected _scheduleNotification(): void; | ||
| private _scheduleWithRAF; | ||
| private _executeNotification; | ||
| private _handleListenerError; | ||
| private _notifyListeners; | ||
| } | ||
| declare function createStore<T>(name: string, initialValue: T): Store<T>; | ||
| //#endregion | ||
| export { ComparisonOptions, ComparisonStrategy, CustomComparator, DynamicStoreOptions, HookOptions, IStore, React18Options, Snapshot, Store, StoreRegistry, StoreSyncConfig, compareValues, createStore, getGlobalComparisonOptions, setGlobalComparisonOptions }; | ||
| //# sourceMappingURL=Store-CoQcuZnp.d.ts.map |
| {"version":3,"file":"Store-CoQcuZnp.d.ts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/core/StoreRegistry.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"} |
| import { ErrorHandlers } from "./error-handling-CkdfKCZ0.js"; | ||
| import React, { useEffect, useRef } from "react"; | ||
| //#region src/stores/utils/type-helpers.ts | ||
| /** | ||
| * Type guard for checking if a value is a Store | ||
| */ | ||
| function isStore(value) { | ||
| return value != null && typeof value === "object" && "subscribe" in value && "getSnapshot" in value && "setValue" in value && "getValue" in value && "name" in value && typeof value.subscribe === "function" && typeof value.getSnapshot === "function" && typeof value.setValue === "function" && typeof value.getValue === "function" && typeof value.name === "string"; | ||
| } | ||
| /** | ||
| * Type guard for checking if a value is a valid store value | ||
| */ | ||
| function isValidStoreValue(value) { | ||
| return value !== void 0; | ||
| } | ||
| /** | ||
| * Utility function for creating type-safe store configurations | ||
| */ | ||
| function createStoreConfig(config) { | ||
| return { | ||
| ...config, | ||
| validateValue: config.validateValue || isValidStoreValue | ||
| }; | ||
| } | ||
| /** | ||
| * Type-safe store value extractor | ||
| */ | ||
| function extractStoreValue(store) { | ||
| if (!store || !isStore(store)) return; | ||
| try { | ||
| return store.getValue(); | ||
| } catch { | ||
| return; | ||
| } | ||
| } | ||
| /** | ||
| * Type-safe multiple store value extractor | ||
| */ | ||
| function extractStoreValues(stores) { | ||
| const result = {}; | ||
| for (const [key, store] of Object.entries(stores)) { | ||
| const value = extractStoreValue(store); | ||
| if (value !== void 0) result[key] = value; | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Create a type-safe equality function with fallback | ||
| */ | ||
| function createSafeEqualityFn(customFn) { | ||
| return (a, b) => { | ||
| try { | ||
| return customFn ? customFn(a, b) : Object.is(a, b); | ||
| } catch { | ||
| return Object.is(a, b); | ||
| } | ||
| }; | ||
| } | ||
| /** | ||
| * Type utilities for store configuration validation | ||
| */ | ||
| const TypeUtils = { | ||
| validateStoreConfig(config) { | ||
| return config != null && typeof config === "object" && "name" in config && typeof config.name === "string" && config.name !== "" && "initialValue" in config; | ||
| }, | ||
| validateStore(store) { | ||
| return isStore(store); | ||
| }, | ||
| getSafeValue(value, fallback) { | ||
| return value !== void 0 && value !== null ? value : fallback; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/utils/provider-composition.ts | ||
| /** | ||
| * Composes multiple Provider components into a single Provider component that accepts children. | ||
| * Uses React.createElement for direct provider nesting without HOC overhead. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Without composition - nested Provider hell | ||
| * function App() { | ||
| * return ( | ||
| * <UserProvider> | ||
| * <ProductProvider> | ||
| * <OrderProvider> | ||
| * <UIProvider> | ||
| * <AppContent /> | ||
| * </UIProvider> | ||
| * </OrderProvider> | ||
| * </ProductProvider> | ||
| * </UserProvider> | ||
| * ); | ||
| * } | ||
| * | ||
| * // With composition - clean and maintainable | ||
| * const AllProviders = composeProviders( | ||
| * UserProvider, | ||
| * ProductProvider, | ||
| * OrderProvider, | ||
| * UIProvider | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Conditional composition based on features | ||
| * const providers = [ | ||
| * CoreProvider, | ||
| * featureFlags.auth && AuthProvider, | ||
| * featureFlags.analytics && AnalyticsProvider | ||
| * ].filter(Boolean) as ProviderComponent[]; | ||
| * | ||
| * const AppProviders = composeProviders(...providers); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AppProviders> | ||
| * <Routes /> | ||
| * </AppProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Domain-grouped composition | ||
| * const BusinessProviders = composeProviders( | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ); | ||
| * | ||
| * const InfrastructureProviders = composeProviders( | ||
| * DataModelProvider, | ||
| * CacheModelProvider, | ||
| * LoggerModelProvider | ||
| * ); | ||
| * | ||
| * const AllProviders = composeProviders( | ||
| * InfrastructureProviders, | ||
| * BusinessProviders | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Environment-specific composition | ||
| * function createEnvironmentProviders() { | ||
| * const isDevelopment = process.env.NODE_ENV === 'development'; | ||
| * const isProduction = process.env.NODE_ENV === 'production'; | ||
| * | ||
| * const providers = [ | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ]; | ||
| * | ||
| * if (isDevelopment) { | ||
| * providers.push(DebugModelProvider, DevToolsModelProvider); | ||
| * } | ||
| * | ||
| * if (isProduction) { | ||
| * providers.push(AnalyticsModelProvider, ErrorTrackingModelProvider); | ||
| * } | ||
| * | ||
| * return composeProviders(...providers); | ||
| * } | ||
| * | ||
| * function App() { | ||
| * const EnvironmentProviders = createEnvironmentProviders(); | ||
| * | ||
| * return ( | ||
| * <EnvironmentProviders> | ||
| * <AppContent /> | ||
| * </EnvironmentProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param providers - Array of Provider components to compose | ||
| * @returns A single Provider component that wraps children with all providers | ||
| */ | ||
| function composeProviders(...providers) { | ||
| return ({ children }) => { | ||
| return providers.reduceRight((children$1, Provider) => React.createElement(Provider, null, children$1), children); | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/subscription-manager.ts | ||
| /** | ||
| * Enhanced subscription manager for automatic cleanup and monitoring | ||
| * | ||
| * Provides centralized management of store subscriptions with automatic cleanup, | ||
| * lifecycle tracking, and memory leak prevention. Designed for use in complex | ||
| * components with multiple store dependencies. | ||
| */ | ||
| var SubscriptionManager = class { | ||
| constructor() { | ||
| this.subscriptions = /* @__PURE__ */ new Map(); | ||
| this.subscriptionCounter = 0; | ||
| this.isDisposed = false; | ||
| } | ||
| /** | ||
| * Add a subscription with automatic tracking | ||
| * | ||
| * @param unsubscribe - Function to call for cleanup | ||
| * @param storeName - Name of the store for debugging | ||
| * @returns Subscription ID for manual management | ||
| */ | ||
| add(unsubscribe, storeName = "unknown") { | ||
| if (this.isDisposed) throw new Error("SubscriptionManager has been disposed"); | ||
| const subscriptionId = `sub_${++this.subscriptionCounter}_${Date.now()}`; | ||
| const entry = { | ||
| unsubscribe, | ||
| storeName, | ||
| createdAt: Date.now(), | ||
| isActive: true | ||
| }; | ||
| this.subscriptions.set(subscriptionId, entry); | ||
| return subscriptionId; | ||
| } | ||
| /** | ||
| * Add a store subscription with automatic cleanup | ||
| * | ||
| * @param store - Store to subscribe to | ||
| * @param listener - Listener function | ||
| * @returns Subscription ID | ||
| */ | ||
| addStoreSubscription(store, listener) { | ||
| try { | ||
| const unsubscribe = store.subscribe(listener); | ||
| return this.add(unsubscribe, store.name); | ||
| } catch (error) { | ||
| ErrorHandlers.store("Failed to create store subscription", { storeName: store.name }, error instanceof Error ? error : void 0); | ||
| throw error; | ||
| } | ||
| } | ||
| /** | ||
| * Remove a specific subscription | ||
| * | ||
| * @param subscriptionId - ID returned from add() | ||
| * @returns true if subscription was found and removed | ||
| */ | ||
| remove(subscriptionId) { | ||
| const entry = this.subscriptions.get(subscriptionId); | ||
| if (!entry) return false; | ||
| if (entry.isActive) try { | ||
| entry.unsubscribe(); | ||
| entry.isActive = false; | ||
| } catch (error) { | ||
| ErrorHandlers.store("Error during subscription cleanup", { | ||
| subscriptionId, | ||
| storeName: entry.storeName | ||
| }, error instanceof Error ? error : void 0); | ||
| } | ||
| this.subscriptions.delete(subscriptionId); | ||
| return true; | ||
| } | ||
| /** | ||
| * Clean up all subscriptions | ||
| */ | ||
| cleanupAll() { | ||
| Array.from(this.subscriptions.keys()).forEach((id) => { | ||
| this.remove(id); | ||
| }); | ||
| } | ||
| /** | ||
| * Get subscription statistics | ||
| */ | ||
| getStats() { | ||
| const now = Date.now(); | ||
| const activeSubscriptions = Array.from(this.subscriptions.values()).filter((s) => s.isActive); | ||
| const subscriptionsByStore = {}; | ||
| let totalAge = 0; | ||
| let oldestTime = now; | ||
| activeSubscriptions.forEach((entry) => { | ||
| subscriptionsByStore[entry.storeName] = (subscriptionsByStore[entry.storeName] || 0) + 1; | ||
| const age = now - entry.createdAt; | ||
| totalAge += age; | ||
| oldestTime = Math.min(oldestTime, entry.createdAt); | ||
| }); | ||
| return { | ||
| totalSubscriptions: this.subscriptions.size, | ||
| activeSubscriptions: activeSubscriptions.length, | ||
| averageAge: activeSubscriptions.length > 0 ? totalAge / activeSubscriptions.length : 0, | ||
| oldestSubscription: activeSubscriptions.length > 0 ? now - oldestTime : 0, | ||
| subscriptionsByStore | ||
| }; | ||
| } | ||
| /** | ||
| * Dispose the manager and cleanup all subscriptions | ||
| */ | ||
| dispose() { | ||
| if (this.isDisposed) return; | ||
| this.cleanupAll(); | ||
| this.subscriptions.clear(); | ||
| this.isDisposed = true; | ||
| } | ||
| /** | ||
| * Check if manager is disposed | ||
| */ | ||
| isManagerDisposed() { | ||
| return this.isDisposed; | ||
| } | ||
| }; | ||
| /** | ||
| * React hook for automatic subscription management | ||
| * | ||
| * Provides automatic cleanup of subscriptions when component unmounts. | ||
| * Useful for components that need to subscribe to multiple stores. | ||
| * | ||
| * @returns SubscriptionManager instance | ||
| */ | ||
| function useSubscriptionManager() { | ||
| const managerRef = useRef(null); | ||
| if (!managerRef.current) managerRef.current = new SubscriptionManager(); | ||
| useEffect(() => { | ||
| return () => { | ||
| if (managerRef.current) { | ||
| managerRef.current.dispose(); | ||
| managerRef.current = null; | ||
| } | ||
| }; | ||
| }, []); | ||
| return managerRef.current; | ||
| } | ||
| if (typeof window !== "undefined" && true) window.__contextActionDebug = { SubscriptionManager }; | ||
| //#endregion | ||
| export { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager }; | ||
| //# sourceMappingURL=utils-B_r1_2dw.js.map |
| {"version":3,"file":"utils-B_r1_2dw.js","names":["children","entry: SubscriptionEntry","subscriptionsByStore: Record<string, number>"],"sources":["../src/stores/utils/type-helpers.ts","../src/stores/utils/provider-composition.ts","../src/stores/utils/subscription-manager.ts"],"sourcesContent":["/**\n * @fileoverview Enhanced Type Helpers\n * \n * Advanced type utilities for improved type inference and type safety\n * throughout the Context-Action framework.\n */\n\nimport type { Store } from '../core/Store';\n\n/**\n * Extract the value type from a Store\n */\nexport type StoreValue<S> = S extends Store<infer T> ? T : never;\n\n/**\n * Extract value types from multiple stores\n */\nexport type StoresValues<S extends readonly Store<any>[]> = {\n [K in keyof S]: StoreValue<S[K]>\n};\n\n/**\n * Extract value types from a record of stores\n */\nexport type StoreRecordValues<S extends Record<string, Store<any>>> = {\n [K in keyof S]: StoreValue<S[K]>\n};\n\n/**\n * Type-safe store selector function type\n */\nexport type StoreSelector<T, R> = (value: T) => R;\n\n/**\n * Type-safe equality function type\n */\nexport type EqualityFunction<T> = (a: T, b: T) => boolean;\n\n/**\n * Store listener function type\n */\nexport type StoreListener = () => void;\n\n/**\n * Store updater function type\n */\nexport type StoreUpdater<T> = (current: T) => T;\n\n/**\n * Type guard for checking if a value is a Store\n */\nexport function isStore<T = unknown>(value: unknown): value is Store<T> {\n return (\n value != null &&\n typeof value === 'object' &&\n 'subscribe' in value &&\n 'getSnapshot' in value &&\n 'setValue' in value &&\n 'getValue' in value &&\n 'name' in value &&\n typeof value.subscribe === 'function' &&\n typeof value.getSnapshot === 'function' &&\n typeof value.setValue === 'function' &&\n typeof value.getValue === 'function' &&\n typeof value.name === 'string'\n );\n}\n\n/**\n * Type guard for checking if a value is a valid store value\n */\nexport function isValidStoreValue<T>(value: unknown): value is T {\n // Basic validation - can be extended based on requirements\n return value !== undefined;\n}\n\n/**\n * Utility type for making certain properties optional\n */\nexport type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;\n\n/**\n * Utility type for making certain properties required\n */\nexport type RequiredBy<T, K extends keyof T> = T & Required<Pick<T, K>>;\n\n/**\n * Deep readonly type for immutable store values\n */\nexport type DeepReadonly<T> = {\n readonly [P in keyof T]: T[P] extends (infer U)[]\n ? DeepReadonlyArray<U>\n : T[P] extends object\n ? DeepReadonly<T[P]>\n : T[P];\n};\n\ninterface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}\n\n/**\n * Type for store initialization configuration\n */\nexport interface StoreInitConfig<T> {\n name: string;\n initialValue: T;\n validateValue?: (value: unknown) => value is T;\n transformValue?: (value: unknown) => T;\n}\n\n/**\n * Utility function for creating type-safe store configurations\n */\nexport function createStoreConfig<T>(config: StoreInitConfig<T>): StoreInitConfig<T> {\n return {\n ...config,\n validateValue: config.validateValue || isValidStoreValue,\n };\n}\n\n/**\n * Type-safe store value extractor\n */\nexport function extractStoreValue<T>(store: Store<T> | undefined | null): T | undefined {\n if (!store || !isStore(store)) {\n return undefined;\n }\n \n try {\n return store.getValue();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Type-safe multiple store value extractor\n */\nexport function extractStoreValues<S extends Record<string, Store<any>>>(\n stores: S\n): Partial<StoreRecordValues<S>> {\n const result = {} as Partial<StoreRecordValues<S>>;\n \n for (const [key, store] of Object.entries(stores)) {\n const value = extractStoreValue(store);\n if (value !== undefined) {\n (result as any)[key] = value;\n }\n }\n \n return result;\n}\n\n/**\n * Create a type-safe equality function with fallback\n */\nexport function createSafeEqualityFn<T>(\n customFn?: EqualityFunction<T>\n): EqualityFunction<T> {\n return (a: T, b: T) => {\n try {\n return customFn ? customFn(a, b) : Object.is(a, b);\n } catch {\n // Fallback to reference equality on error\n return Object.is(a, b);\n }\n };\n}\n\n/**\n * Type utilities for store configuration validation\n */\nexport const TypeUtils = {\n /**\n * Validate store configuration at runtime\n */\n validateStoreConfig<T>(config: unknown): config is StoreInitConfig<T> {\n return (\n config != null &&\n typeof config === 'object' &&\n 'name' in config &&\n typeof (config as Record<string, unknown>).name === 'string' &&\n (config as Record<string, unknown>).name !== '' &&\n 'initialValue' in config\n );\n },\n\n /**\n * Validate store instance\n */\n validateStore<T>(store: unknown): store is Store<T> {\n return isStore(store);\n },\n\n /**\n * Get safe value with type checking\n */\n getSafeValue<T>(value: unknown, fallback: T): T {\n return value !== undefined && value !== null ? value as T : fallback;\n }\n} as const;","/**\n * @fileoverview Provider composition utilities for managing multiple contexts\n * @implements provider-composition\n * @memberof store-utilities\n * \n * Utilities for composing multiple Provider components to reduce nesting\n * and improve maintainability when dealing with many split contexts.\n */\n\nimport React from 'react';\n\n/**\n * Type for Provider components that accept children\n */\nexport type ProviderComponent = React.ComponentType<{ children: React.ReactNode }>;\n\n/**\n * Composes multiple Provider components into a single Provider component that accepts children.\n * Uses React.createElement for direct provider nesting without HOC overhead.\n * \n * @example\n * ```tsx\n * // Without composition - nested Provider hell\n * function App() {\n * return (\n * <UserProvider>\n * <ProductProvider>\n * <OrderProvider>\n * <UIProvider>\n * <AppContent />\n * </UIProvider>\n * </OrderProvider>\n * </ProductProvider>\n * </UserProvider>\n * );\n * }\n * \n * // With composition - clean and maintainable\n * const AllProviders = composeProviders(\n * UserProvider,\n * ProductProvider,\n * OrderProvider,\n * UIProvider\n * );\n * \n * function App() {\n * return (\n * <AllProviders>\n * <AppContent />\n * </AllProviders>\n * );\n * }\n * ```\n * \n * @example\n * ```tsx\n * // Conditional composition based on features\n * const providers = [\n * CoreProvider,\n * featureFlags.auth && AuthProvider,\n * featureFlags.analytics && AnalyticsProvider\n * ].filter(Boolean) as ProviderComponent[];\n * \n * const AppProviders = composeProviders(...providers);\n * \n * function App() {\n * return (\n * <AppProviders>\n * <Routes />\n * </AppProviders>\n * );\n * }\n * ```\n * \n * @example\n * ```tsx\n * // Domain-grouped composition\n * const BusinessProviders = composeProviders(\n * UserModelProvider,\n * ProductModelProvider,\n * OrderModelProvider\n * );\n * \n * const InfrastructureProviders = composeProviders(\n * DataModelProvider,\n * CacheModelProvider,\n * LoggerModelProvider\n * );\n * \n * const AllProviders = composeProviders(\n * InfrastructureProviders,\n * BusinessProviders\n * );\n * \n * function App() {\n * return (\n * <AllProviders>\n * <AppContent />\n * </AllProviders>\n * );\n * }\n * ```\n * \n * @example\n * ```tsx\n * // Environment-specific composition\n * function createEnvironmentProviders() {\n * const isDevelopment = process.env.NODE_ENV === 'development';\n * const isProduction = process.env.NODE_ENV === 'production';\n * \n * const providers = [\n * UserModelProvider,\n * ProductModelProvider,\n * OrderModelProvider\n * ];\n * \n * if (isDevelopment) {\n * providers.push(DebugModelProvider, DevToolsModelProvider);\n * }\n * \n * if (isProduction) {\n * providers.push(AnalyticsModelProvider, ErrorTrackingModelProvider);\n * }\n * \n * return composeProviders(...providers);\n * }\n * \n * function App() {\n * const EnvironmentProviders = createEnvironmentProviders();\n * \n * return (\n * <EnvironmentProviders>\n * <AppContent />\n * </EnvironmentProviders>\n * );\n * }\n * ```\n * \n * @param providers - Array of Provider components to compose\n * @returns A single Provider component that wraps children with all providers\n */\nexport function composeProviders(\n ...providers: ProviderComponent[]\n): ProviderComponent {\n return ({ children }: { children: React.ReactNode }) => {\n return providers.reduceRight(\n (children, Provider) => React.createElement(Provider, null, children),\n children\n );\n };\n}","/**\n * @fileoverview Subscription Management System\n *\n * Centralized subscription management for automatic cleanup and memory leak prevention.\n * Provides utilities for managing multiple store subscriptions with lifecycle management.\n */\n\nimport { useRef, useEffect } from 'react';\nimport type { Store } from '../core/Store';\nimport { ErrorHandlers } from './error-handling';\n\n/**\n * Individual subscription entry with metadata\n */\nexport interface SubscriptionEntry {\n unsubscribe: () => void;\n storeName: string;\n createdAt: number;\n isActive: boolean;\n}\n\n/**\n * Subscription statistics for monitoring\n */\nexport interface SubscriptionStats {\n totalSubscriptions: number;\n activeSubscriptions: number;\n averageAge: number;\n oldestSubscription: number;\n subscriptionsByStore: Record<string, number>;\n}\n\n/**\n * Enhanced subscription manager for automatic cleanup and monitoring\n * \n * Provides centralized management of store subscriptions with automatic cleanup,\n * lifecycle tracking, and memory leak prevention. Designed for use in complex\n * components with multiple store dependencies.\n */\nexport class SubscriptionManager {\n private subscriptions = new Map<string, SubscriptionEntry>();\n private subscriptionCounter = 0;\n private isDisposed = false;\n\n /**\n * Add a subscription with automatic tracking\n * \n * @param unsubscribe - Function to call for cleanup\n * @param storeName - Name of the store for debugging\n * @returns Subscription ID for manual management\n */\n add(unsubscribe: () => void, storeName: string = 'unknown'): string {\n if (this.isDisposed) {\n throw new Error('SubscriptionManager has been disposed');\n }\n\n const subscriptionId = `sub_${++this.subscriptionCounter}_${Date.now()}`;\n \n const entry: SubscriptionEntry = {\n unsubscribe,\n storeName,\n createdAt: Date.now(),\n isActive: true\n };\n\n this.subscriptions.set(subscriptionId, entry);\n \n return subscriptionId;\n }\n\n /**\n * Add a store subscription with automatic cleanup\n * \n * @param store - Store to subscribe to\n * @param listener - Listener function\n * @returns Subscription ID\n */\n addStoreSubscription<T>(store: Store<T>, listener: () => void): string {\n try {\n const unsubscribe = store.subscribe(listener);\n return this.add(unsubscribe, store.name);\n } catch (error) {\n ErrorHandlers.store(\n 'Failed to create store subscription',\n { storeName: store.name },\n error instanceof Error ? error : undefined\n );\n throw error;\n }\n }\n\n /**\n * Remove a specific subscription\n * \n * @param subscriptionId - ID returned from add()\n * @returns true if subscription was found and removed\n */\n remove(subscriptionId: string): boolean {\n const entry = this.subscriptions.get(subscriptionId);\n if (!entry) {\n return false;\n }\n\n if (entry.isActive) {\n try {\n entry.unsubscribe();\n entry.isActive = false;\n } catch (error) {\n ErrorHandlers.store(\n 'Error during subscription cleanup',\n { \n subscriptionId,\n storeName: entry.storeName \n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n this.subscriptions.delete(subscriptionId);\n return true;\n }\n\n\n\n /**\n * Clean up all subscriptions\n */\n cleanupAll(): void {\n const subscriptionIds = Array.from(this.subscriptions.keys());\n \n subscriptionIds.forEach(id => {\n this.remove(id);\n });\n }\n\n /**\n * Get subscription statistics\n */\n getStats(): SubscriptionStats {\n const now = Date.now();\n const activeSubscriptions = Array.from(this.subscriptions.values()).filter(s => s.isActive);\n \n const subscriptionsByStore: Record<string, number> = {};\n let totalAge = 0;\n let oldestTime = now;\n \n activeSubscriptions.forEach(entry => {\n // Count by store\n subscriptionsByStore[entry.storeName] = (subscriptionsByStore[entry.storeName] || 0) + 1;\n \n // Age calculations\n const age = now - entry.createdAt;\n totalAge += age;\n oldestTime = Math.min(oldestTime, entry.createdAt);\n });\n \n return {\n totalSubscriptions: this.subscriptions.size,\n activeSubscriptions: activeSubscriptions.length,\n averageAge: activeSubscriptions.length > 0 ? totalAge / activeSubscriptions.length : 0,\n oldestSubscription: activeSubscriptions.length > 0 ? now - oldestTime : 0,\n subscriptionsByStore\n };\n }\n\n\n /**\n * Dispose the manager and cleanup all subscriptions\n */\n dispose(): void {\n if (this.isDisposed) {\n return;\n }\n\n this.cleanupAll();\n this.subscriptions.clear();\n this.isDisposed = true;\n }\n\n /**\n * Check if manager is disposed\n */\n isManagerDisposed(): boolean {\n return this.isDisposed;\n }\n}\n\n/**\n * React hook for automatic subscription management\n * \n * Provides automatic cleanup of subscriptions when component unmounts.\n * Useful for components that need to subscribe to multiple stores.\n * \n * @returns SubscriptionManager instance\n */\nexport function useSubscriptionManager(): SubscriptionManager {\n const managerRef = useRef<SubscriptionManager | null>(null);\n\n if (!managerRef.current) {\n managerRef.current = new SubscriptionManager();\n }\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (managerRef.current) {\n managerRef.current.dispose();\n managerRef.current = null;\n }\n };\n }, []);\n\n return managerRef.current;\n}\n\n// Development-only debugging support\nif (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {\n (window as any).__contextActionDebug = { SubscriptionManager };\n}"],"mappings":"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"} |
| import { Store } from "./Store--dj9U0mo.cjs"; | ||
| import React from "react"; | ||
| //#region src/stores/utils/immutable.d.ts | ||
| declare function deepClone<T>(value: T, _options?: { | ||
| skipProducer?: boolean; | ||
| }): T; | ||
| declare function deepCloneWithImmer<T>(value: T): T; | ||
| declare function safeGet<T>(value: T, enableCloning?: boolean): T; | ||
| declare function safeSet<T>(value: T, enableCloning?: boolean): T; | ||
| declare const ImmerUtils: { | ||
| isDraft(value: unknown): boolean; | ||
| original<T>(value: T): T | undefined; | ||
| current<T>(value: T): T; | ||
| produce<T>(baseState: T, producer: (draft: T) => void | T): T; | ||
| }; | ||
| declare function preloadImmer(): void; | ||
| declare function produce<T>(baseState: T, producer: (draft: T) => void | T): T; | ||
| //#endregion | ||
| //#region src/stores/utils/type-helpers.d.ts | ||
| type StoreValue<S> = S extends Store<infer T> ? T : never; | ||
| type StoresValues<S extends readonly Store<any>[]> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreRecordValues<S extends Record<string, Store<any>>> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreSelector<T, R> = (value: T) => R; | ||
| type EqualityFunction<T> = (a: T, b: T) => boolean; | ||
| type StoreListener = () => void; | ||
| type StoreUpdater<T> = (current: T) => T; | ||
| declare function isStore<T = unknown>(value: unknown): value is Store<T>; | ||
| declare function isValidStoreValue<T>(value: unknown): value is T; | ||
| type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; | ||
| type RequiredBy<T, K extends keyof T> = T & Required<Pick<T, K>>; | ||
| type DeepReadonly<T> = { readonly [P in keyof T]: T[P] extends (infer U)[] ? DeepReadonlyArray<U> : T[P] extends object ? DeepReadonly<T[P]> : T[P] }; | ||
| interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {} | ||
| interface StoreInitConfig<T> { | ||
| name: string; | ||
| initialValue: T; | ||
| validateValue?: (value: unknown) => value is T; | ||
| transformValue?: (value: unknown) => T; | ||
| } | ||
| declare function createStoreConfig<T>(config: StoreInitConfig<T>): StoreInitConfig<T>; | ||
| declare function extractStoreValue<T>(store: Store<T> | undefined | null): T | undefined; | ||
| declare function extractStoreValues<S extends Record<string, Store<any>>>(stores: S): Partial<StoreRecordValues<S>>; | ||
| declare function createSafeEqualityFn<T>(customFn?: EqualityFunction<T>): EqualityFunction<T>; | ||
| declare const TypeUtils: { | ||
| readonly validateStoreConfig: <T>(config: unknown) => config is StoreInitConfig<T>; | ||
| readonly validateStore: <T>(store: unknown) => store is Store<T>; | ||
| readonly getSafeValue: <T>(value: unknown, fallback: T) => T; | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/utils/provider-composition.d.ts | ||
| type ProviderComponent = React.ComponentType<{ | ||
| children: React.ReactNode; | ||
| }>; | ||
| declare function composeProviders(...providers: ProviderComponent[]): ProviderComponent; | ||
| //#endregion | ||
| //#region src/stores/utils/subscription-manager.d.ts | ||
| interface SubscriptionEntry { | ||
| unsubscribe: () => void; | ||
| storeName: string; | ||
| createdAt: number; | ||
| isActive: boolean; | ||
| } | ||
| interface SubscriptionStats { | ||
| totalSubscriptions: number; | ||
| activeSubscriptions: number; | ||
| averageAge: number; | ||
| oldestSubscription: number; | ||
| subscriptionsByStore: Record<string, number>; | ||
| } | ||
| declare class SubscriptionManager { | ||
| private subscriptions; | ||
| private subscriptionCounter; | ||
| private isDisposed; | ||
| add(unsubscribe: () => void, storeName?: string): string; | ||
| addStoreSubscription<T>(store: Store<T>, listener: () => void): string; | ||
| remove(subscriptionId: string): boolean; | ||
| cleanupAll(): void; | ||
| getStats(): SubscriptionStats; | ||
| dispose(): void; | ||
| isManagerDisposed(): boolean; | ||
| } | ||
| declare function useSubscriptionManager(): SubscriptionManager; | ||
| //#endregion | ||
| export { type DeepReadonly, type EqualityFunction, ImmerUtils, type PartialBy, type ProviderComponent, type RequiredBy, type StoreInitConfig, type StoreListener, type StoreRecordValues, type StoreSelector, type StoreUpdater, type StoreValue, type StoresValues, type SubscriptionEntry, SubscriptionManager, type SubscriptionStats, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, useSubscriptionManager }; | ||
| //# sourceMappingURL=utils-Cq-l1Kd1.d.cts.map |
| {"version":3,"file":"utils-Cq-l1Kd1.d.cts","names":[],"sources":["../src/stores/utils/immutable.ts","../src/stores/utils/type-helpers.ts","../src/stores/utils/provider-composition.ts","../src/stores/utils/subscription-manager.ts"],"sourcesContent":[],"mappings":"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"} |
| import { Store } from "./Store-CoQcuZnp.js"; | ||
| import React from "react"; | ||
| //#region src/stores/utils/immutable.d.ts | ||
| declare function deepClone<T>(value: T, _options?: { | ||
| skipProducer?: boolean; | ||
| }): T; | ||
| declare function deepCloneWithImmer<T>(value: T): T; | ||
| declare function safeGet<T>(value: T, enableCloning?: boolean): T; | ||
| declare function safeSet<T>(value: T, enableCloning?: boolean): T; | ||
| declare const ImmerUtils: { | ||
| isDraft(value: unknown): boolean; | ||
| original<T>(value: T): T | undefined; | ||
| current<T>(value: T): T; | ||
| produce<T>(baseState: T, producer: (draft: T) => void | T): T; | ||
| }; | ||
| declare function preloadImmer(): void; | ||
| declare function produce<T>(baseState: T, producer: (draft: T) => void | T): T; | ||
| //#endregion | ||
| //#region src/stores/utils/type-helpers.d.ts | ||
| type StoreValue<S> = S extends Store<infer T> ? T : never; | ||
| type StoresValues<S extends readonly Store<any>[]> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreRecordValues<S extends Record<string, Store<any>>> = { [K in keyof S]: StoreValue<S[K]> }; | ||
| type StoreSelector<T, R> = (value: T) => R; | ||
| type EqualityFunction<T> = (a: T, b: T) => boolean; | ||
| type StoreListener = () => void; | ||
| type StoreUpdater<T> = (current: T) => T; | ||
| declare function isStore<T = unknown>(value: unknown): value is Store<T>; | ||
| declare function isValidStoreValue<T>(value: unknown): value is T; | ||
| type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; | ||
| type RequiredBy<T, K extends keyof T> = T & Required<Pick<T, K>>; | ||
| type DeepReadonly<T> = { readonly [P in keyof T]: T[P] extends (infer U)[] ? DeepReadonlyArray<U> : T[P] extends object ? DeepReadonly<T[P]> : T[P] }; | ||
| interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {} | ||
| interface StoreInitConfig<T> { | ||
| name: string; | ||
| initialValue: T; | ||
| validateValue?: (value: unknown) => value is T; | ||
| transformValue?: (value: unknown) => T; | ||
| } | ||
| declare function createStoreConfig<T>(config: StoreInitConfig<T>): StoreInitConfig<T>; | ||
| declare function extractStoreValue<T>(store: Store<T> | undefined | null): T | undefined; | ||
| declare function extractStoreValues<S extends Record<string, Store<any>>>(stores: S): Partial<StoreRecordValues<S>>; | ||
| declare function createSafeEqualityFn<T>(customFn?: EqualityFunction<T>): EqualityFunction<T>; | ||
| declare const TypeUtils: { | ||
| readonly validateStoreConfig: <T>(config: unknown) => config is StoreInitConfig<T>; | ||
| readonly validateStore: <T>(store: unknown) => store is Store<T>; | ||
| readonly getSafeValue: <T>(value: unknown, fallback: T) => T; | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/utils/provider-composition.d.ts | ||
| type ProviderComponent = React.ComponentType<{ | ||
| children: React.ReactNode; | ||
| }>; | ||
| declare function composeProviders(...providers: ProviderComponent[]): ProviderComponent; | ||
| //#endregion | ||
| //#region src/stores/utils/subscription-manager.d.ts | ||
| interface SubscriptionEntry { | ||
| unsubscribe: () => void; | ||
| storeName: string; | ||
| createdAt: number; | ||
| isActive: boolean; | ||
| } | ||
| interface SubscriptionStats { | ||
| totalSubscriptions: number; | ||
| activeSubscriptions: number; | ||
| averageAge: number; | ||
| oldestSubscription: number; | ||
| subscriptionsByStore: Record<string, number>; | ||
| } | ||
| declare class SubscriptionManager { | ||
| private subscriptions; | ||
| private subscriptionCounter; | ||
| private isDisposed; | ||
| add(unsubscribe: () => void, storeName?: string): string; | ||
| addStoreSubscription<T>(store: Store<T>, listener: () => void): string; | ||
| remove(subscriptionId: string): boolean; | ||
| cleanupAll(): void; | ||
| getStats(): SubscriptionStats; | ||
| dispose(): void; | ||
| isManagerDisposed(): boolean; | ||
| } | ||
| declare function useSubscriptionManager(): SubscriptionManager; | ||
| //#endregion | ||
| export { type DeepReadonly, type EqualityFunction, ImmerUtils, type PartialBy, type ProviderComponent, type RequiredBy, type StoreInitConfig, type StoreListener, type StoreRecordValues, type StoreSelector, type StoreUpdater, type StoreValue, type StoresValues, type SubscriptionEntry, SubscriptionManager, type SubscriptionStats, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, useSubscriptionManager }; | ||
| //# sourceMappingURL=utils-DGg-aIzZ.d.ts.map |
| {"version":3,"file":"utils-DGg-aIzZ.d.ts","names":[],"sources":["../src/stores/utils/immutable.ts","../src/stores/utils/type-helpers.ts","../src/stores/utils/provider-composition.ts","../src/stores/utils/subscription-manager.ts"],"sourcesContent":[],"mappings":"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"} |
| const require_error_handling = require('./error-handling-ibCwx4ki.cjs'); | ||
| let react = require("react"); | ||
| react = require_error_handling.__toESM(react); | ||
| //#region src/stores/utils/type-helpers.ts | ||
| /** | ||
| * Type guard for checking if a value is a Store | ||
| */ | ||
| function isStore(value) { | ||
| return value != null && typeof value === "object" && "subscribe" in value && "getSnapshot" in value && "setValue" in value && "getValue" in value && "name" in value && typeof value.subscribe === "function" && typeof value.getSnapshot === "function" && typeof value.setValue === "function" && typeof value.getValue === "function" && typeof value.name === "string"; | ||
| } | ||
| /** | ||
| * Type guard for checking if a value is a valid store value | ||
| */ | ||
| function isValidStoreValue(value) { | ||
| return value !== void 0; | ||
| } | ||
| /** | ||
| * Utility function for creating type-safe store configurations | ||
| */ | ||
| function createStoreConfig(config) { | ||
| return { | ||
| ...config, | ||
| validateValue: config.validateValue || isValidStoreValue | ||
| }; | ||
| } | ||
| /** | ||
| * Type-safe store value extractor | ||
| */ | ||
| function extractStoreValue(store) { | ||
| if (!store || !isStore(store)) return; | ||
| try { | ||
| return store.getValue(); | ||
| } catch { | ||
| return; | ||
| } | ||
| } | ||
| /** | ||
| * Type-safe multiple store value extractor | ||
| */ | ||
| function extractStoreValues(stores) { | ||
| const result = {}; | ||
| for (const [key, store] of Object.entries(stores)) { | ||
| const value = extractStoreValue(store); | ||
| if (value !== void 0) result[key] = value; | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Create a type-safe equality function with fallback | ||
| */ | ||
| function createSafeEqualityFn(customFn) { | ||
| return (a, b) => { | ||
| try { | ||
| return customFn ? customFn(a, b) : Object.is(a, b); | ||
| } catch { | ||
| return Object.is(a, b); | ||
| } | ||
| }; | ||
| } | ||
| /** | ||
| * Type utilities for store configuration validation | ||
| */ | ||
| const TypeUtils = { | ||
| validateStoreConfig(config) { | ||
| return config != null && typeof config === "object" && "name" in config && typeof config.name === "string" && config.name !== "" && "initialValue" in config; | ||
| }, | ||
| validateStore(store) { | ||
| return isStore(store); | ||
| }, | ||
| getSafeValue(value, fallback) { | ||
| return value !== void 0 && value !== null ? value : fallback; | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/stores/utils/provider-composition.ts | ||
| /** | ||
| * Composes multiple Provider components into a single Provider component that accepts children. | ||
| * Uses React.createElement for direct provider nesting without HOC overhead. | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Without composition - nested Provider hell | ||
| * function App() { | ||
| * return ( | ||
| * <UserProvider> | ||
| * <ProductProvider> | ||
| * <OrderProvider> | ||
| * <UIProvider> | ||
| * <AppContent /> | ||
| * </UIProvider> | ||
| * </OrderProvider> | ||
| * </ProductProvider> | ||
| * </UserProvider> | ||
| * ); | ||
| * } | ||
| * | ||
| * // With composition - clean and maintainable | ||
| * const AllProviders = composeProviders( | ||
| * UserProvider, | ||
| * ProductProvider, | ||
| * OrderProvider, | ||
| * UIProvider | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Conditional composition based on features | ||
| * const providers = [ | ||
| * CoreProvider, | ||
| * featureFlags.auth && AuthProvider, | ||
| * featureFlags.analytics && AnalyticsProvider | ||
| * ].filter(Boolean) as ProviderComponent[]; | ||
| * | ||
| * const AppProviders = composeProviders(...providers); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AppProviders> | ||
| * <Routes /> | ||
| * </AppProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Domain-grouped composition | ||
| * const BusinessProviders = composeProviders( | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ); | ||
| * | ||
| * const InfrastructureProviders = composeProviders( | ||
| * DataModelProvider, | ||
| * CacheModelProvider, | ||
| * LoggerModelProvider | ||
| * ); | ||
| * | ||
| * const AllProviders = composeProviders( | ||
| * InfrastructureProviders, | ||
| * BusinessProviders | ||
| * ); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <AllProviders> | ||
| * <AppContent /> | ||
| * </AllProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Environment-specific composition | ||
| * function createEnvironmentProviders() { | ||
| * const isDevelopment = process.env.NODE_ENV === 'development'; | ||
| * const isProduction = process.env.NODE_ENV === 'production'; | ||
| * | ||
| * const providers = [ | ||
| * UserModelProvider, | ||
| * ProductModelProvider, | ||
| * OrderModelProvider | ||
| * ]; | ||
| * | ||
| * if (isDevelopment) { | ||
| * providers.push(DebugModelProvider, DevToolsModelProvider); | ||
| * } | ||
| * | ||
| * if (isProduction) { | ||
| * providers.push(AnalyticsModelProvider, ErrorTrackingModelProvider); | ||
| * } | ||
| * | ||
| * return composeProviders(...providers); | ||
| * } | ||
| * | ||
| * function App() { | ||
| * const EnvironmentProviders = createEnvironmentProviders(); | ||
| * | ||
| * return ( | ||
| * <EnvironmentProviders> | ||
| * <AppContent /> | ||
| * </EnvironmentProviders> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param providers - Array of Provider components to compose | ||
| * @returns A single Provider component that wraps children with all providers | ||
| */ | ||
| function composeProviders(...providers) { | ||
| return ({ children }) => { | ||
| return providers.reduceRight((children$1, Provider) => react.default.createElement(Provider, null, children$1), children); | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/stores/utils/subscription-manager.ts | ||
| /** | ||
| * Enhanced subscription manager for automatic cleanup and monitoring | ||
| * | ||
| * Provides centralized management of store subscriptions with automatic cleanup, | ||
| * lifecycle tracking, and memory leak prevention. Designed for use in complex | ||
| * components with multiple store dependencies. | ||
| */ | ||
| var SubscriptionManager = class { | ||
| constructor() { | ||
| this.subscriptions = /* @__PURE__ */ new Map(); | ||
| this.subscriptionCounter = 0; | ||
| this.isDisposed = false; | ||
| } | ||
| /** | ||
| * Add a subscription with automatic tracking | ||
| * | ||
| * @param unsubscribe - Function to call for cleanup | ||
| * @param storeName - Name of the store for debugging | ||
| * @returns Subscription ID for manual management | ||
| */ | ||
| add(unsubscribe, storeName = "unknown") { | ||
| if (this.isDisposed) throw new Error("SubscriptionManager has been disposed"); | ||
| const subscriptionId = `sub_${++this.subscriptionCounter}_${Date.now()}`; | ||
| const entry = { | ||
| unsubscribe, | ||
| storeName, | ||
| createdAt: Date.now(), | ||
| isActive: true | ||
| }; | ||
| this.subscriptions.set(subscriptionId, entry); | ||
| return subscriptionId; | ||
| } | ||
| /** | ||
| * Add a store subscription with automatic cleanup | ||
| * | ||
| * @param store - Store to subscribe to | ||
| * @param listener - Listener function | ||
| * @returns Subscription ID | ||
| */ | ||
| addStoreSubscription(store, listener) { | ||
| try { | ||
| const unsubscribe = store.subscribe(listener); | ||
| return this.add(unsubscribe, store.name); | ||
| } catch (error) { | ||
| require_error_handling.ErrorHandlers.store("Failed to create store subscription", { storeName: store.name }, error instanceof Error ? error : void 0); | ||
| throw error; | ||
| } | ||
| } | ||
| /** | ||
| * Remove a specific subscription | ||
| * | ||
| * @param subscriptionId - ID returned from add() | ||
| * @returns true if subscription was found and removed | ||
| */ | ||
| remove(subscriptionId) { | ||
| const entry = this.subscriptions.get(subscriptionId); | ||
| if (!entry) return false; | ||
| if (entry.isActive) try { | ||
| entry.unsubscribe(); | ||
| entry.isActive = false; | ||
| } catch (error) { | ||
| require_error_handling.ErrorHandlers.store("Error during subscription cleanup", { | ||
| subscriptionId, | ||
| storeName: entry.storeName | ||
| }, error instanceof Error ? error : void 0); | ||
| } | ||
| this.subscriptions.delete(subscriptionId); | ||
| return true; | ||
| } | ||
| /** | ||
| * Clean up all subscriptions | ||
| */ | ||
| cleanupAll() { | ||
| Array.from(this.subscriptions.keys()).forEach((id) => { | ||
| this.remove(id); | ||
| }); | ||
| } | ||
| /** | ||
| * Get subscription statistics | ||
| */ | ||
| getStats() { | ||
| const now = Date.now(); | ||
| const activeSubscriptions = Array.from(this.subscriptions.values()).filter((s) => s.isActive); | ||
| const subscriptionsByStore = {}; | ||
| let totalAge = 0; | ||
| let oldestTime = now; | ||
| activeSubscriptions.forEach((entry) => { | ||
| subscriptionsByStore[entry.storeName] = (subscriptionsByStore[entry.storeName] || 0) + 1; | ||
| const age = now - entry.createdAt; | ||
| totalAge += age; | ||
| oldestTime = Math.min(oldestTime, entry.createdAt); | ||
| }); | ||
| return { | ||
| totalSubscriptions: this.subscriptions.size, | ||
| activeSubscriptions: activeSubscriptions.length, | ||
| averageAge: activeSubscriptions.length > 0 ? totalAge / activeSubscriptions.length : 0, | ||
| oldestSubscription: activeSubscriptions.length > 0 ? now - oldestTime : 0, | ||
| subscriptionsByStore | ||
| }; | ||
| } | ||
| /** | ||
| * Dispose the manager and cleanup all subscriptions | ||
| */ | ||
| dispose() { | ||
| if (this.isDisposed) return; | ||
| this.cleanupAll(); | ||
| this.subscriptions.clear(); | ||
| this.isDisposed = true; | ||
| } | ||
| /** | ||
| * Check if manager is disposed | ||
| */ | ||
| isManagerDisposed() { | ||
| return this.isDisposed; | ||
| } | ||
| }; | ||
| /** | ||
| * React hook for automatic subscription management | ||
| * | ||
| * Provides automatic cleanup of subscriptions when component unmounts. | ||
| * Useful for components that need to subscribe to multiple stores. | ||
| * | ||
| * @returns SubscriptionManager instance | ||
| */ | ||
| function useSubscriptionManager() { | ||
| const managerRef = (0, react.useRef)(null); | ||
| if (!managerRef.current) managerRef.current = new SubscriptionManager(); | ||
| (0, react.useEffect)(() => { | ||
| return () => { | ||
| if (managerRef.current) { | ||
| managerRef.current.dispose(); | ||
| managerRef.current = null; | ||
| } | ||
| }; | ||
| }, []); | ||
| return managerRef.current; | ||
| } | ||
| if (typeof window !== "undefined" && process.env.NODE_ENV === "development") window.__contextActionDebug = { SubscriptionManager }; | ||
| //#endregion | ||
| Object.defineProperty(exports, 'SubscriptionManager', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return SubscriptionManager; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'TypeUtils', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return TypeUtils; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'composeProviders', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return composeProviders; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createSafeEqualityFn', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createSafeEqualityFn; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'createStoreConfig', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return createStoreConfig; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'extractStoreValue', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return extractStoreValue; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'extractStoreValues', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return extractStoreValues; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'isStore', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return isStore; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'isValidStoreValue', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return isValidStoreValue; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'useSubscriptionManager', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return useSubscriptionManager; | ||
| } | ||
| }); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
727648
23.58%9446
29.75%32
-5.88%22
4.76%3
Infinity%+ Added
+ Added
- Removed
- Removed
Updated