@context-action/react
Advanced tools
| 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":";;;;aAWY,sBAAA;;;;EAAA,gBAAA,GAAA,kBAAsB;EAarB,oBAAA,GAAmB,sBAAA;EAAA,aAAA,GAAA,eAAA;0BACR,GAAA,0BAAA;;AAKd,cANG,kBAAA,SAA2B,KAAA,CAM9B;WAEI,IAAA,EAPU,sBAOV;WACM,OAAA,EAPO,MAOP,CAAA,MAAA,EAAA,OAAA,CAAA,GAAA,SAAA;WAToB,SAAA,EAAA,MAAA;EAAK,WAAA,CAAA,IAAA,EAMnC,sBANmC,EAAA,OAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAQ/B,MAR+B,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,aAAA,CAAA,EASzB,KATyB;AA4G7C;ACpHmD,iBDoHnC,WAAA,CCpHmC,IAAA,EDqH3C,sBCrH2C,EAAA,OAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EDuHvC,MCvHuC,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,aAAA,CAAA,EDwHjC,KCxHiC,CAAA,EDyHhD,kBCzHgD;;;UAHlC,uBAAA;YACL;EDHA,QAAA,CAAA,ECIC,SDJD,GAAA,CAAA,CAAsB,KAAA,ECIA,kBDJA,EAAA,SAAA,ECI+B,SDJ/B,EAAA,GCI6C,SDJ7C,CAAA;EAarB,OAAA,CAAA,EAAA,CAAA,KAAA,ECRO,kBDQY,EAAA,SAAA,ECRmB,SDQnB,EAAA,GAAA,IAAA;EAAA,kBAAA,CAAA,EAAA,OAAA;WACR,CAAA,ECPV,KDOU,CAAA,MAAA,GAAA,MAAA,CAAA;;AAKd,UCNO,uBAAA,CDMP;UAEI,EAAA,OAAA;OACM,ECPX,kBDOW,GAAA,IAAA;WAToB,ECG3B,SDH2B,GAAA,IAAA;EAAK,OAAA,EAAA,MAAA,GAAA,IAAA;AA4G7C;AAA2B,cC9Fd,kBAAA,SAA2B,SD8Fb,CC9FuB,uBD8FvB,EC9FgD,uBD8FhD,CAAA,CAAA;UACnB,cAAA;aAEI,CAAA,KAAA,EC9FS,uBD8FT;SACM,wBAAA,CAAA,KAAA,ECpFuB,KDoFvB,CAAA,ECpF+B,ODoF/B,CCpFuC,uBDoFvC,CAAA;mBACf,CAAA,KAAA,ECzEwB,KDyExB,EAAA,SAAA,ECzE0C,SDyE1C,CAAA,EAAA,IAAA;EAAkB,kBAAA,CAAA,SAAA,EC1CW,uBD0CX,CAAA,EAAA,IAAA;;;YCDb,OAAA,CAAA;EA3HS,QAAA,qBAAuB;EAAA,QAAA,yBAAA;UAC5B,wBAAA;;AACsB,iBAwRlB,sBAxRkB,CAAA,UAAA,MAAA,CAAA,CAAA,gBAAA,EAyRd,OAAA,CAAM,aAzRQ,CAyRM,CAzRN,CAAA,EAAA,kBAAA,CAAA,EA0RX,IA1RW,CA0RN,uBA1RM,EAAA,UAAA,CAAA,CAAA,EA2R/B,OAAA,CAAM,aA3RyB,CA2RX,CA3RW,CAAA;AAA+B,iBA6SjD,wBAAA,CA7SiD,SAAA,EAAA,MAAA,EAAA,cAAA,CAAA,EA+S9C,SA/S8C,CAAA,EAgT9D,OAAA,CAAM,aAhTwD,CAAA;UAAc,EAgT5C,SAhT4C;;;;UCK9D,mBAAA,SAA4B;;AFT7C;AAaa,UEII,iBFJe,CAAA,UAAA,CAAA,CAAA,CAAA,CAAA;EAAA,iBAAA,EEKX,KAAA,CAAM,SFLK,CEKK,cFLL,CEKoB,CFLpB,CAAA,CAAA;;AAEL,UESV,mBFTU,CAAA,UAAA,CAAA,CAAA,CAAA,CAAA;UAIjB,EEME,KAAA,CAAM,EFNR,CAAA;IAEI,QAAA,EEImB,SFJnB;;kBAR0B,EAAA,GAAA,GEad,iBFbc,CEaI,CFbJ,CAAA;EAAK,iBAAA,EAAA,GAAA,GEclB,cFdkB,CEcH,CFdG,CAAA,CAAA,UAAA,CAAA;EA4G7B,gBAAW,EAAA,CAAA,UAAA,ME7FU,CF6FV,CAAA,CAAA,MAAA,EE5Ff,CF4Fe,EAAA,OAAA,EE3Fd,aF2Fc,CE3FA,CF2FA,CE3FE,CF2FF,CAAA,CAAA,EAAA,MAAA,CAAA,EE1Fd,aF0Fc,EAAA,GAAA,IAAA;EAAA,iBAAA,EAAA,GAAA,GExFA,cFwFA,CExFe,CFwFf,CAAA,GAAA,IAAA;6BACnB,EAAA,GAAA,GAAA;IAEI,QAAA,EAAA,CAAA,UAAA,MEzFmB,CFyFnB,CAAA,CAAA,MAAA,EExFE,CFwFF,EAAA,OAAA,CAAA,EEvFI,CFuFJ,CEvFM,CFuFN,CAAA,EAAA,OAAA,CAAA,EEtFI,eFsFJ,EAAA,GErFH,OFqFG,CAAA,IAAA,CAAA;IACM,kBAAA,EAAA,CAAA,UAAA,MErFuB,CFqFvB,EAAA,IAAA,IAAA,CAAA,CAAA,MAAA,EEpFJ,CFoFI,EAAA,OAAA,CAAA,EEnFF,CFmFE,CEnFA,CFmFA,CAAA,EAAA,OAAA,CAAA,EElFF,eFkFE,EAAA,GEjFT,OFiFS,CEjFD,eFiFC,CEjFe,CFiFf,CAAA,CAAA;IACf,QAAA,EAAA,GAAA,GAAA,IAAA;IAAkB,eAAA,EAAA,GAAA,GAAA,IAAA;;WE9EV,KAAA,CAAM,QAAQ,kBAAkB;;;;iBC9B3B,gEAEL,sBACR,oBAAoB;iBAGP,0CACN,sBACP,oBAAoB"} |
| import { ErrorHandlers, compareValues, getErrorStatistics, produce, safeGet, safeSet } from "./error-handling-CY0aBmPl.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 (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,...subscriptionOptions } = options; | ||
| const subscribe = useCallback((callback) => { | ||
| if (!store) return () => {}; | ||
| if (subscriptionOptions.debounce || subscriptionOptions.throttle || subscriptionOptions.condition) return createEnhancedSubscriber(store, subscriptionOptions)(callback); | ||
| return store.subscribe(callback); | ||
| }, [store, subscriptionOptions]); | ||
| 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) { | ||
| 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 storeValue = store.getValue(); | ||
| const selectedValue = stableSelector(storeValue); | ||
| 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) => { | ||
| const prevKey = prevProps[key]; | ||
| const currentKey = this.props[key]; | ||
| return prevKey !== currentKey; | ||
| })) 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(); | ||
| const 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]); | ||
| const 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]); | ||
| return { | ||
| dispatch, | ||
| dispatchWithResult | ||
| }; | ||
| }; | ||
| 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"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions); | ||
| }, [context.actionRegisterRef]); | ||
| const dispatchWithResult = useCallback((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions); | ||
| }, [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-BzNYMKTH.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-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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"} |
| const require_error_handling = require('./error-handling-V4WsOwLB.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 (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,...subscriptionOptions } = options; | ||
| const subscribe = (0, react.useCallback)((callback) => { | ||
| if (!store) return () => {}; | ||
| if (subscriptionOptions.debounce || subscriptionOptions.throttle || subscriptionOptions.condition) return createEnhancedSubscriber(store, subscriptionOptions)(callback); | ||
| return store.subscribe(callback); | ||
| }, [store, subscriptionOptions]); | ||
| 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) { | ||
| 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 storeValue = store.getValue(); | ||
| const selectedValue = stableSelector(storeValue); | ||
| 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) => { | ||
| const prevKey = prevProps[key]; | ||
| const currentKey = this.props[key]; | ||
| return prevKey !== currentKey; | ||
| })) 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(); | ||
| const 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]); | ||
| const 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]); | ||
| return { | ||
| dispatch, | ||
| dispatchWithResult | ||
| }; | ||
| }; | ||
| 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"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatch(action, payload, dispatchOptions); | ||
| }, [context.actionRegisterRef]); | ||
| const dispatchWithResult = (0, react.useCallback)((action, payload, options) => { | ||
| const register = context.actionRegisterRef.current; | ||
| if (!register) throw new Error("ActionRegister not initialized"); | ||
| const dispatchOptions = { | ||
| ...options, | ||
| ...options?.signal ? {} : { autoAbort: { | ||
| enabled: true, | ||
| allowHandlerAbort: true, | ||
| onControllerCreated: (controller) => { | ||
| activeControllersRef.current.add(controller); | ||
| } | ||
| } } | ||
| }; | ||
| return register.dispatchWithResult(action, payload, dispatchOptions); | ||
| }, [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 { ComparisonOptions, ComparisonStrategy, CustomComparator, DynamicStoreOptions, HookOptions, React18Options, Snapshot, Store, StoreRegistry, StoreSyncConfig, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store-BWXLgYbF.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-BATcgK15.cjs"; | ||
| import { ActionContextConfig, ActionContextReturn, ContextActionError, ContextActionErrorType, StoreErrorBoundary, StoreErrorBoundaryProps, StoreErrorBoundaryState, createActionContext, createStoreErrorBoundary, handleError, withStoreErrorBoundary } from "./ActionContext-BnM5V83y.cjs"; | ||
| //#region src/stores/hooks/useComputedStore.d.ts | ||
| interface ComputedStoreConfig<R> { | ||
| equalityFn?: (a: R, b: R) => boolean; | ||
| debug?: boolean; | ||
| name?: string; | ||
| initialValue?: R; | ||
| onError?: (error: Error) => void; | ||
| debounceMs?: number; | ||
| enableCache?: boolean; | ||
| cacheSize?: number; | ||
| } | ||
| declare function useComputedStore<T, R>(store: Store<T>, compute: (value: T) => R, config?: ComputedStoreConfig<R>): R; | ||
| //#endregion | ||
| //#region src/stores/hooks/useLocalStore.d.ts | ||
| declare function useLocalStore<T>(initialValue: T, name?: string): Snapshot<T> & { | ||
| store: Store<T>; | ||
| }; | ||
| //#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 }; | ||
| //# sourceMappingURL=advanced.d.cts.map |
| {"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"} |
| import { ComparisonOptions, ComparisonStrategy, CustomComparator, DynamicStoreOptions, HookOptions, React18Options, Snapshot, Store, StoreRegistry, StoreSyncConfig, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store-Cdy48kLP.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-cwvrN0GD.js"; | ||
| import { ActionContextConfig, ActionContextReturn, ContextActionError, ContextActionErrorType, StoreErrorBoundary, StoreErrorBoundaryProps, StoreErrorBoundaryState, createActionContext, createStoreErrorBoundary, handleError, withStoreErrorBoundary } from "./ActionContext-Cq5LNd0Y.js"; | ||
| //#region src/stores/hooks/useComputedStore.d.ts | ||
| interface ComputedStoreConfig<R> { | ||
| equalityFn?: (a: R, b: R) => boolean; | ||
| debug?: boolean; | ||
| name?: string; | ||
| initialValue?: R; | ||
| onError?: (error: Error) => void; | ||
| debounceMs?: number; | ||
| enableCache?: boolean; | ||
| cacheSize?: number; | ||
| } | ||
| declare function useComputedStore<T, R>(store: Store<T>, compute: (value: T) => R, config?: ComputedStoreConfig<R>): R; | ||
| //#endregion | ||
| //#region src/stores/hooks/useLocalStore.d.ts | ||
| declare function useLocalStore<T>(initialValue: T, name?: string): Snapshot<T> & { | ||
| store: Store<T>; | ||
| }; | ||
| //#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 }; | ||
| //# sourceMappingURL=advanced.d.ts.map |
| {"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.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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"} |
| 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": { | ||
| const deepOptions = { | ||
| ...maxDepth !== void 0 && { maxDepth }, | ||
| ...ignoreKeys !== void 0 && { ignoreKeys }, | ||
| ...enableCircularCheck !== void 0 && { enableCircularCheck } | ||
| }; | ||
| result = deepEquals(oldValue, newValue, deepOptions); | ||
| 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-CY0aBmPl.js.map |
| {"version":3,"file":"error-handling-CY0aBmPl.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": { | ||
| const deepOptions = { | ||
| ...maxDepth !== void 0 && { maxDepth }, | ||
| ...ignoreKeys !== void 0 && { ignoreKeys }, | ||
| ...enableCircularCheck !== void 0 && { enableCircularCheck } | ||
| }; | ||
| result = deepEquals(oldValue, newValue, deepOptions); | ||
| 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; | ||
| } | ||
| }); |
+168
| import { ComparisonOptions, IStore, Snapshot, Store, StoreRegistry, createStore } from "./Store-BWXLgYbF.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 react_jsx_runtime0 from "react/jsx-runtime"; | ||
| //#region src/stores/hooks/useStoreValue.d.ts | ||
| interface StoreValueOptions<R> { | ||
| equalityFn?: (a: R, b: R) => boolean; | ||
| condition?: () => boolean; | ||
| debounce?: number; | ||
| throttle?: number; | ||
| initialValue?: R; | ||
| 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; | ||
| //#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; | ||
| //#endregion | ||
| //#region src/stores/patterns/declarative-store-pattern-v2.d.ts | ||
| interface StoreConfig<T = any> { | ||
| initialValue: T; | ||
| strategy?: 'reference' | 'shallow' | 'deep'; | ||
| description?: string; | ||
| debug?: boolean; | ||
| tags?: string[]; | ||
| version?: string; | ||
| comparisonOptions?: Partial<ComparisonOptions<T>>; | ||
| } | ||
| type InitialStores<T extends Record<string, any>> = { [K in keyof T]: StoreConfig<T[K]> | T[K] }; | ||
| type StoreDefinitions = Record<string, StoreConfig<any> | any>; | ||
| type InferStoreTypes<T extends StoreDefinitions> = { [K in keyof T]: T[K] extends StoreConfig<infer V> ? V : T[K] extends ((...args: any[]) => any) ? never : T[K] extends object ? T[K] extends { | ||
| length: number; | ||
| } ? T[K] : T[K] extends Date ? T[K] : T[K] : T[K] }; | ||
| declare class StoreManager<T extends Record<string, any>> { | ||
| readonly name: string; | ||
| readonly registry: StoreRegistry; | ||
| readonly initialStores: InitialStores<T>; | ||
| readonly stores: Map<keyof T, Store<any>>; | ||
| constructor(name: string, initialStores: InitialStores<T>); | ||
| getStore<K extends keyof T>(storeName: K): Store<T[K]>; | ||
| clear(): void; | ||
| getInfo(): { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| } | ||
| declare function createStoreContext<T extends Record<string, any>>(contextName: string, initialStores: InitialStores<T>): ReturnType<typeof createStoreContextImpl<T>>; | ||
| declare function createStoreContext<T extends StoreDefinitions>(contextName: string, storeDefinitions: T): ReturnType<typeof createStoreContextImpl<InferStoreTypes<T>>>; | ||
| declare function createStoreContextImpl<T extends Record<string, any>>(contextName: string, initialStores: InitialStores<T>): { | ||
| readonly Provider: ({ | ||
| children, | ||
| registryId | ||
| }: { | ||
| children: ReactNode; | ||
| registryId?: string; | ||
| }) => react_jsx_runtime0.JSX.Element; | ||
| readonly useStore: <K extends keyof T>(storeName: K) => Store<T[K]>; | ||
| readonly useStoreManager: () => StoreManager<T>; | ||
| readonly useStoreInfo: () => { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| readonly useStoreClear: () => () => void; | ||
| readonly withProvider: <P extends {}>(Component: React.ComponentType<P>, config?: WithProviderConfig) => React.FC<P>; | ||
| readonly contextName: string; | ||
| readonly initialStores: InitialStores<T>; | ||
| }; | ||
| interface WithProviderConfig { | ||
| displayName?: string; | ||
| registryId?: string; | ||
| autoCleanup?: boolean; | ||
| errorBoundary?: boolean; | ||
| } | ||
| //#endregion | ||
| //#region src/refs/types.d.ts | ||
| type RefTarget = any; | ||
| interface RefOperationResult<T = any> { | ||
| success: boolean; | ||
| result?: T; | ||
| error?: Error; | ||
| duration?: number; | ||
| timestamp: number; | ||
| } | ||
| interface RefOperationOptions { | ||
| timeout?: number; | ||
| retries?: number; | ||
| signal?: AbortSignal; | ||
| priority?: number; | ||
| operationId?: string; | ||
| metadata?: Record<string, any>; | ||
| } | ||
| type RefOperation<T extends RefTarget, R = any> = (target: T, options?: RefOperationOptions) => R | Promise<R>; | ||
| interface RefInitConfig<T extends RefTarget = RefTarget> { | ||
| name: string; | ||
| initialMetadata?: Record<string, any>; | ||
| mountTimeout?: number; | ||
| autoCleanup?: boolean; | ||
| validator?: (target: any) => target is T; | ||
| cleanup?: (target: T) => void | Promise<void>; | ||
| } | ||
| type RefDefinitions = Record<string, RefInitConfig<any>>; | ||
| type InferRefTypes<T extends RefDefinitions> = { [K in keyof T]: T[K] extends RefInitConfig<infer R> ? R : RefTarget }; | ||
| //#endregion | ||
| //#region src/refs/hooks/useRefPolling.d.ts | ||
| interface RefPollingOptions { | ||
| interval?: number; | ||
| timeout?: number; | ||
| onTick?: (elapsed: number, isMounted: boolean) => void; | ||
| onTimeout?: (elapsed: number) => void; | ||
| onSuccess?: (elapsed: number, target: any) => void; | ||
| } | ||
| //#endregion | ||
| //#region src/refs/createRefContext.d.ts | ||
| interface RefContextReturn<T> { | ||
| Provider: React.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>>; | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| onMount: (callback: (target: T[K]) => void) => () => void; | ||
| executeIfMounted: <Result>(operation: (target: T[K] & 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>>; | ||
| }; | ||
| useGetAllRefs: () => () => Partial<T>; | ||
| useRefPolling: () => <K extends keyof T>(refName: K, options?: RefPollingOptions) => { | ||
| promise: Promise<T[K]>; | ||
| cancel: () => void; | ||
| isMounted: () => boolean; | ||
| }; | ||
| useRefMountState: <K extends keyof T>(refName: K) => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| mountedTarget: T[K] | null; | ||
| }; | ||
| useOnMountStateChange: <K extends keyof T>(refName: K, callback: (mounted: boolean, target: T[K] | null) => void) => void; | ||
| useRefMountChecker: <K extends keyof T>(refName: K) => () => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| target: T[K] | null; | ||
| }; | ||
| contextName: string; | ||
| refDefinitions?: T extends RefDefinitions ? T : undefined; | ||
| } | ||
| interface CreateRefContextOptions { | ||
| defaultMountTimeout?: number; | ||
| disableTimeout?: boolean; | ||
| } | ||
| declare function createRefContext<T extends Record<string, any>>(contextName: string, options?: CreateRefContextOptions): RefContextReturn<T>; | ||
| declare function createRefContext<T extends RefDefinitions>(contextName: string, refDefinitions: T, options?: CreateRefContextOptions): RefContextReturn<InferRefTypes<T>>; | ||
| //#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 }; | ||
| //# sourceMappingURL=index.d.cts.map |
| {"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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"} |
+168
| import { ComparisonOptions, IStore, Snapshot, Store, StoreRegistry, createStore } from "./Store-Cdy48kLP.js"; | ||
| import { ActionContextConfig, ActionContextReturn, ActionContextType, StoreErrorBoundary, StoreErrorBoundaryProps, createActionContext } from "./ActionContext-Cq5LNd0Y.js"; | ||
| import React, { ReactNode } from "react"; | ||
| import * as react_jsx_runtime0 from "react/jsx-runtime"; | ||
| import { ActionHandler, ActionPayloadMap, ActionRegister, ActionRegisterConfig, ExecutionMode, HandlerConfig, PipelineController, UnregisterFunction } from "@context-action/core"; | ||
| //#region src/stores/hooks/useStoreValue.d.ts | ||
| interface StoreValueOptions<R> { | ||
| equalityFn?: (a: R, b: R) => boolean; | ||
| condition?: () => boolean; | ||
| debounce?: number; | ||
| throttle?: number; | ||
| initialValue?: R; | ||
| 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; | ||
| //#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; | ||
| //#endregion | ||
| //#region src/stores/patterns/declarative-store-pattern-v2.d.ts | ||
| interface StoreConfig<T = any> { | ||
| initialValue: T; | ||
| strategy?: 'reference' | 'shallow' | 'deep'; | ||
| description?: string; | ||
| debug?: boolean; | ||
| tags?: string[]; | ||
| version?: string; | ||
| comparisonOptions?: Partial<ComparisonOptions<T>>; | ||
| } | ||
| type InitialStores<T extends Record<string, any>> = { [K in keyof T]: StoreConfig<T[K]> | T[K] }; | ||
| type StoreDefinitions = Record<string, StoreConfig<any> | any>; | ||
| type InferStoreTypes<T extends StoreDefinitions> = { [K in keyof T]: T[K] extends StoreConfig<infer V> ? V : T[K] extends ((...args: any[]) => any) ? never : T[K] extends object ? T[K] extends { | ||
| length: number; | ||
| } ? T[K] : T[K] extends Date ? T[K] : T[K] : T[K] }; | ||
| declare class StoreManager<T extends Record<string, any>> { | ||
| readonly name: string; | ||
| readonly registry: StoreRegistry; | ||
| readonly initialStores: InitialStores<T>; | ||
| readonly stores: Map<keyof T, Store<any>>; | ||
| constructor(name: string, initialStores: InitialStores<T>); | ||
| getStore<K extends keyof T>(storeName: K): Store<T[K]>; | ||
| clear(): void; | ||
| getInfo(): { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| } | ||
| declare function createStoreContext<T extends Record<string, any>>(contextName: string, initialStores: InitialStores<T>): ReturnType<typeof createStoreContextImpl<T>>; | ||
| declare function createStoreContext<T extends StoreDefinitions>(contextName: string, storeDefinitions: T): ReturnType<typeof createStoreContextImpl<InferStoreTypes<T>>>; | ||
| declare function createStoreContextImpl<T extends Record<string, any>>(contextName: string, initialStores: InitialStores<T>): { | ||
| readonly Provider: ({ | ||
| children, | ||
| registryId | ||
| }: { | ||
| children: ReactNode; | ||
| registryId?: string; | ||
| }) => react_jsx_runtime0.JSX.Element; | ||
| readonly useStore: <K extends keyof T>(storeName: K) => Store<T[K]>; | ||
| readonly useStoreManager: () => StoreManager<T>; | ||
| readonly useStoreInfo: () => { | ||
| name: string; | ||
| storeCount: number; | ||
| availableStores: string[]; | ||
| }; | ||
| readonly useStoreClear: () => () => void; | ||
| readonly withProvider: <P extends {}>(Component: React.ComponentType<P>, config?: WithProviderConfig) => React.FC<P>; | ||
| readonly contextName: string; | ||
| readonly initialStores: InitialStores<T>; | ||
| }; | ||
| interface WithProviderConfig { | ||
| displayName?: string; | ||
| registryId?: string; | ||
| autoCleanup?: boolean; | ||
| errorBoundary?: boolean; | ||
| } | ||
| //#endregion | ||
| //#region src/refs/types.d.ts | ||
| type RefTarget = any; | ||
| interface RefOperationResult<T = any> { | ||
| success: boolean; | ||
| result?: T; | ||
| error?: Error; | ||
| duration?: number; | ||
| timestamp: number; | ||
| } | ||
| interface RefOperationOptions { | ||
| timeout?: number; | ||
| retries?: number; | ||
| signal?: AbortSignal; | ||
| priority?: number; | ||
| operationId?: string; | ||
| metadata?: Record<string, any>; | ||
| } | ||
| type RefOperation<T extends RefTarget, R = any> = (target: T, options?: RefOperationOptions) => R | Promise<R>; | ||
| interface RefInitConfig<T extends RefTarget = RefTarget> { | ||
| name: string; | ||
| initialMetadata?: Record<string, any>; | ||
| mountTimeout?: number; | ||
| autoCleanup?: boolean; | ||
| validator?: (target: any) => target is T; | ||
| cleanup?: (target: T) => void | Promise<void>; | ||
| } | ||
| type RefDefinitions = Record<string, RefInitConfig<any>>; | ||
| type InferRefTypes<T extends RefDefinitions> = { [K in keyof T]: T[K] extends RefInitConfig<infer R> ? R : RefTarget }; | ||
| //#endregion | ||
| //#region src/refs/hooks/useRefPolling.d.ts | ||
| interface RefPollingOptions { | ||
| interval?: number; | ||
| timeout?: number; | ||
| onTick?: (elapsed: number, isMounted: boolean) => void; | ||
| onTimeout?: (elapsed: number) => void; | ||
| onSuccess?: (elapsed: number, target: any) => void; | ||
| } | ||
| //#endregion | ||
| //#region src/refs/createRefContext.d.ts | ||
| interface RefContextReturn<T> { | ||
| Provider: React.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>>; | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| onMount: (callback: (target: T[K]) => void) => () => void; | ||
| executeIfMounted: <Result>(operation: (target: T[K] & 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>>; | ||
| }; | ||
| useGetAllRefs: () => () => Partial<T>; | ||
| useRefPolling: () => <K extends keyof T>(refName: K, options?: RefPollingOptions) => { | ||
| promise: Promise<T[K]>; | ||
| cancel: () => void; | ||
| isMounted: () => boolean; | ||
| }; | ||
| useRefMountState: <K extends keyof T>(refName: K) => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| mountedTarget: T[K] | null; | ||
| }; | ||
| useOnMountStateChange: <K extends keyof T>(refName: K, callback: (mounted: boolean, target: T[K] | null) => void) => void; | ||
| useRefMountChecker: <K extends keyof T>(refName: K) => () => { | ||
| isMounted: boolean; | ||
| isWaitingForMount: boolean; | ||
| target: T[K] | null; | ||
| }; | ||
| contextName: string; | ||
| refDefinitions?: T extends RefDefinitions ? T : undefined; | ||
| } | ||
| interface CreateRefContextOptions { | ||
| defaultMountTimeout?: number; | ||
| disableTimeout?: boolean; | ||
| } | ||
| declare function createRefContext<T extends Record<string, any>>(contextName: string, options?: CreateRefContextOptions): RefContextReturn<T>; | ||
| declare function createRefContext<T extends RefDefinitions>(contextName: string, refDefinitions: T, options?: CreateRefContextOptions): RefContextReturn<InferRefTypes<T>>; | ||
| //#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 }; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"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.js","names":["name: string","initialValue: T[K]","strategy: 'reference' | 'shallow' | 'deep'","description: string | undefined","tags: string[]","version: string | undefined","comparisonOptions: StoreConfig<T[K]>['comparisonOptions']","Component","timeoutMs: number | undefined","intervalId: ReturnType<typeof setInterval> | null","timeoutId: ReturnType<typeof setTimeout> | null","isMounted","Provider: React.FC<{ children: ReactNode }>","timeout: number | undefined","refNames: K[]","result: Partial<T>","useRefPolling","useRefPollingHook","options"],"sources":["../src/stores/hooks/useStoreValue.ts","../src/stores/patterns/declarative-store-pattern-v2.tsx","../src/refs/hooks/useRefMount.ts","../src/refs/hooks/useRefOperation.ts","../src/refs/hooks/useRefPolling.ts","../src/refs/hooks/useRefMountState.ts","../src/refs/createRefContext.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { shallowEqual, defaultEqualityFn } from './useStoreSelector';\nimport type { Store } from '../core/Store';\nimport { useSafeStoreSubscription } from '../utils/sync-external-store-utils';\n\n/**\n * Create a type assertion helper for stores created with initial values\n */\nexport function assertStoreValue<T>(value: T | undefined, storeName: string): T {\n if (value === undefined) {\n throw new Error(\n `Store \"${storeName}\" returned undefined value. ` +\n 'This should not happen with properly initialized stores.'\n );\n }\n return value;\n}\n\n/**\n * Performance-optimized store value hook with advanced features\n * \n * Enhanced version of useStoreValue that prevents unnecessary re-renders through\n * intelligent subscription management, selective updates, debouncing, throttling,\n * and conditional subscription. Follows React best practices and hooks rules.\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks\n * \n * @public\n */\n\n/**\n * Performance optimization options for useStoreValue hook\n * \n * Advanced configuration options for controlling subscription behavior,\n * comparison strategies, timing controls, debugging features, and React 18+ optimizations.\n * \n * @template R - The type of the selected/computed value\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#performance-best-practices\n * \n * @public\n */\nexport interface StoreValueOptions<R> {\n /** Custom equality comparison function to determine when to trigger re-renders */\n equalityFn?: (a: R, b: R) => boolean;\n\n /** Subscription condition - pause subscription when false */\n condition?: () => boolean;\n\n /** Debounce delay in milliseconds - groups rapid changes together */\n debounce?: number;\n\n /** Throttle interval in milliseconds - limits update frequency */\n throttle?: number;\n\n /** Initial value to use before first subscription */\n initialValue?: R;\n\n /** Enable debug logging for subscription behavior */\n debug?: boolean;\n\n /** Hook name for debugging purposes */\n name?: string;\n}\n\n// Store가 확정된 경우 - 기본 구독\nexport function useStoreValue<T>(\n store: Store<T>, \n options?: StoreValueOptions<T>\n): T;\n\n// Store가 undefined일 수 있는 경우 - 안전한 구독\nexport function useStoreValue<T>(\n store: Store<T> | undefined | null,\n options?: StoreValueOptions<T>\n): T | undefined;\n\n// Store가 확정된 경우 + selector - 선택적 구독\nexport function useStoreValue<T, R>(\n store: Store<T>, \n selector: (value: T) => R,\n options?: StoreValueOptions<R>\n): R;\n\n// Store가 undefined일 수 있는 경우 + selector - 안전한 선택적 구독 \nexport function useStoreValue<T, R>(\n store: Store<T> | undefined | null, \n selector: (value: T) => R,\n options?: StoreValueOptions<R>\n): R | undefined;\n\nexport function useStoreValue<T, R>(\n store: Store<T> | undefined | null,\n selectorOrOptions?: ((value: T) => R) | StoreValueOptions<T>,\n options?: StoreValueOptions<R>\n): T | R | undefined {\n // 파라미터 정규화\n const selector = typeof selectorOrOptions === 'function' ? selectorOrOptions : undefined;\n const finalOptions = (typeof selectorOrOptions === 'function' ? options : selectorOrOptions) || {};\n\n const {\n equalityFn = defaultEqualityFn,\n condition,\n debounce,\n throttle,\n initialValue,\n debug = false,\n name = store?.name || 'unknown'\n } = finalOptions;\n\n // useSyncExternalStore 기반 구독\n const subscriptionOptions = {\n debug,\n name,\n equalityFn: equalityFn as (a: R, b: R) => boolean,\n initialValue: initialValue as R,\n ...(debounce !== undefined && { debounce }),\n ...(throttle !== undefined && { throttle }),\n ...(condition && { condition })\n };\n\n const value = useSafeStoreSubscription(\n store,\n selector,\n subscriptionOptions\n );\n\n return value;\n}\n\n/**\n * Hook for selecting multiple values from a store with optimized re-renders\n * \n * Subscribes to multiple computed values from a single store using selector functions.\n * Optimizes performance by only triggering re-renders when the selected values change,\n * using shallow comparison to detect changes in the combined result object.\n * \n * @template T - Type of the store value\n * @template S - Type of the selectors object mapping keys to selector functions\n * \n * @param store - The store to subscribe to (can be undefined for conditional usage)\n * @param selectors - Object mapping result keys to selector functions\n * \n * @returns Object with selected values, or undefined if store is undefined\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usestoreselector-advanced-usage\n *\n * @public\\n */\nexport function useStoreValues<T, S extends Record<string, (value: T) => any>>(\n store: Store<T> | undefined | null,\n selectors: S\n): { [K in keyof S]: ReturnType<S[K]> } | undefined {\n // 통합 선택자 함수 생성\n const selectorFunction = useMemo(() => {\n return (value: T) => {\n const result = {} as { [K in keyof S]: ReturnType<S[K]> };\n for (const [key, selector] of Object.entries(selectors)) {\n result[key as keyof S] = selector(value);\n }\n return result;\n };\n }, [selectors]);\n \n // useSyncExternalStore 기반 구독\n const storeValue = useSafeStoreSubscription(\n store,\n selectorFunction,\n {\n equalityFn: shallowEqual,\n name: `${store?.name || 'unknown'}-values`\n }\n ) as { [K in keyof S]: ReturnType<S[K]> } | undefined;\n \n return store ? storeValue : undefined;\n}","/**\n * @fileoverview Store Context Pattern - Simplified and Unified Store Management\n * \n * A simplified version that focuses on store management with excellent type inference.\n * Removes complexity while maintaining all essential features. Follows the Store Only Pattern\n * for pure state management without action dispatching.\n * \n * This pattern provides type-safe store creation with automatic inference from initial values,\n * making it the recommended approach for state management in the Context-Action framework.\n */\n\nimport React, { createContext, useContext, ReactNode, useRef, useMemo } from 'react';\nimport { StoreRegistry } from '../core/StoreRegistry';\nimport { createStore } from '../core/Store';\nimport type { Store } from '../core/Store';\nimport type { ComparisonOptions } from '../utils/comparison';\n\n/**\n * Store configuration interface for store context pattern\n * \n * Defines configuration options for individual stores including initial values,\n * comparison strategies, debugging options, and metadata.\n * \n * @template T - The type of values stored in this store\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/\n * \n * @public\n */\nexport interface StoreConfig<T = any> {\n initialValue: T;\n strategy?: 'reference' | 'shallow' | 'deep';\n description?: string;\n debug?: boolean;\n tags?: string[];\n version?: string;\n comparisonOptions?: Partial<ComparisonOptions<T>>;\n}\n\n/**\n * Initial stores type mapping for declarative store pattern\n * \n * Maps store names to their configuration or direct initial values.\n * Supports both full configuration objects and direct value assignment\n * for simplified store definition.\n * \n * @template T - Record of store names to their value types\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage\n * \n * @public\n */\nexport type InitialStores<T extends Record<string, any>> = {\n [K in keyof T]: StoreConfig<T[K]> | T[K]; // Allow direct value or config\n};\n\n/**\n * Store definitions that can infer types from initialValue\n * \n * Generic type for store definitions that supports automatic type inference.\n * Each store can be defined with either a full configuration or a direct value.\n * \n * @public\n */\nexport type StoreDefinitions = Record<string, StoreConfig<any> | any>;\n\n/**\n * Infer store value types from store definitions\n * \n * Utility type that extracts the value types from store definitions,\n * supporting both configuration objects and direct values. Excludes\n * functions and properly handles arrays, dates, and objects.\n * \n * @template T - Store definitions record\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage\n * \n * @public\n */\nexport type InferStoreTypes<T extends StoreDefinitions> = {\n [K in keyof T]: T[K] extends StoreConfig<infer V> \n ? V \n : T[K] extends (...args: any[]) => any\n ? never // Exclude functions\n : T[K] extends object\n ? T[K] extends { length: number }\n ? T[K] // Arrays\n : T[K] extends Date\n ? T[K] // Dates\n : T[K] // Objects\n : T[K]; // Primitives\n};\n\n/**\n * @deprecated Use InitialStores instead for better type inference\n * \n * Legacy type alias for backward compatibility. New code should use\n * InitialStores<T> which provides better type inference and cleaner API.\n * \n * @public\n */\nexport type StoreSchema<T extends Record<string, any>> = InitialStores<T>;\n\n/**\n * Internal store registry manager\n * \n * Manages store creation, caching, and registry coordination for the\n * store context pattern. Handles store lifecycle and provides\n * type-safe access to individual stores.\n * \n * @template T - Record of store names to their value types\n * \n * @public\n */\nexport class StoreManager<T extends Record<string, any>> {\n public readonly registry: StoreRegistry;\n public readonly initialStores: InitialStores<T>;\n public readonly stores = new Map<keyof T, Store<any>>();\n\n constructor(\n public readonly name: string,\n initialStores: InitialStores<T>\n ) {\n this.registry = new StoreRegistry(name);\n this.initialStores = initialStores;\n }\n\n /**\n * Get or create a store with type-safe inference\n * \n * Retrieves an existing store or creates a new one based on the initial\n * configuration. Provides excellent type inference and caches stores\n * for performance.\n * \n * @template K - Store name key\n * @param storeName - Name of the store to retrieve or create\n * @returns Typed store instance\n * \n * @internal\n */\n getStore<K extends keyof T>(storeName: K): Store<T[K]> {\n // Return existing store if available\n const existing = this.stores.get(storeName);\n if (existing) {\n return existing;\n }\n\n // Create new store from initial configuration\n const storeConfig = this.initialStores[storeName];\n \n // Handle both direct values and config objects\n let initialValue: T[K];\n let strategy: 'reference' | 'shallow' | 'deep' = 'reference';\n let description: string | undefined;\n let debug = false;\n let tags: string[] = ['declarative'];\n let version: string | undefined;\n let comparisonOptions: StoreConfig<T[K]>['comparisonOptions'];\n\n if (storeConfig && typeof storeConfig === 'object' && 'initialValue' in storeConfig) {\n // Config object with extended options\n const config = storeConfig as StoreConfig<T[K]>;\n initialValue = config.initialValue;\n strategy = config.strategy || 'reference';\n description = config.description;\n debug = config.debug || false;\n tags = config.tags ? ['declarative', ...config.tags] : ['declarative', strategy];\n version = config.version;\n comparisonOptions = config.comparisonOptions;\n } else {\n // Direct value\n initialValue = storeConfig as T[K];\n tags = ['declarative', strategy];\n }\n\n // Create store\n const store = createStore(String(storeName), initialValue);\n \n // Set comparison strategy with extended options\n const finalComparisonOptions = {\n strategy,\n ...comparisonOptions\n };\n store.setComparisonOptions(finalComparisonOptions);\n\n // Register in StoreRegistry with extended metadata\n const metadata = {\n name: String(storeName),\n tags,\n description: description || `Store: ${String(storeName)}`,\n debug,\n ...(version !== undefined && { version })\n };\n \n this.registry.register(String(storeName), store, metadata);\n\n // Debug logging if enabled\n if (debug && process.env.NODE_ENV === 'development') {\n console.log(`🏪 Store context store created: ${String(storeName)}`, {\n strategy,\n tags,\n version,\n description,\n hasCustomComparison: !!comparisonOptions?.customComparator,\n ignoreKeys: comparisonOptions?.ignoreKeys\n });\n }\n\n // Cache the store\n this.stores.set(storeName, store);\n\n return store;\n }\n\n /**\n * Clear all stores\n */\n clear(): void {\n this.registry.clear();\n this.stores.clear();\n }\n\n /**\n * Get registry info\n */\n getInfo() {\n return {\n name: this.name,\n storeCount: this.stores.size,\n availableStores: Object.keys(this.initialStores)\n };\n }\n}\n\n/**\n * Context type for the store pattern\n */\ninterface StoreContextValue<T extends Record<string, any>> {\n managerRef: React.RefObject<StoreManager<T> | null>;\n}\n\n/**\n * Overload 1: Explicit generic types - User provides explicit type interface\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage\n */\nexport function createStoreContext<T extends Record<string, any>>(\n contextName: string,\n initialStores: InitialStores<T>\n): ReturnType<typeof createStoreContextImpl<T>>;\n\n/**\n * Overload 2: Type inference - Types inferred from store definitions\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage\n */\nexport function createStoreContext<T extends StoreDefinitions>(\n contextName: string,\n storeDefinitions: T\n): ReturnType<typeof createStoreContextImpl<InferStoreTypes<T>>>;\n\n/**\n * Implementation function that handles both overloads\n */\nexport function createStoreContext(\n contextName: string,\n initialStores: any\n): any {\n return createStoreContextImpl(contextName, initialStores);\n}\n\n/**\n * Main implementation function - Simplified and focused on store management\n * \n * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage\n */\nfunction createStoreContextImpl<T extends Record<string, any>>(\n contextName: string,\n initialStores: InitialStores<T>\n) {\n // Create context\n const StoreContext = createContext<StoreContextValue<T> | null>(null);\n\n /**\n * Provider component with optional registry isolation\n */\n function Provider({ \n children, \n registryId \n }: { \n children: ReactNode;\n registryId?: string;\n }) {\n const effectiveRegistryId = registryId || contextName;\n const managerRef = useRef<StoreManager<T> | null>(null);\n \n if (!managerRef.current) {\n managerRef.current = new StoreManager(effectiveRegistryId, initialStores);\n }\n \n return (\n <StoreContext.Provider value={{ managerRef }}>\n {children}\n </StoreContext.Provider>\n );\n }\n\n /**\n * Core hook - Get typed store by name\n * This is the primary API for accessing stores\n */\n function useStore<K extends keyof T>(storeName: K): Store<T[K]> {\n const context = useContext(StoreContext);\n \n if (!context || !context.managerRef.current) {\n throw new Error(\n `useStore must be used within ${contextName}.Provider. ` +\n `Wrap your component with <${contextName}.Provider>`\n );\n }\n \n // Memoize store to prevent infinite re-renders in useEffect dependencies\n return useMemo(() => {\n return context.managerRef.current!.getStore(storeName);\n }, [context.managerRef, storeName]);\n }\n\n /**\n * Get the store manager (for advanced use cases)\n */\n function useStoreManager(): StoreManager<T> {\n const context = useContext(StoreContext);\n \n if (!context || !context.managerRef.current) {\n throw new Error(\n `useStoreManager must be used within ${contextName}.Provider`\n );\n }\n \n return context.managerRef.current;\n }\n\n /**\n * Utility hooks\n */\n function useStoreInfo() {\n const manager = useStoreManager();\n return manager.getInfo();\n }\n\n function useStoreClear() {\n const manager = useStoreManager();\n return () => manager.clear();\n }\n\n\n /**\n * HOC for automatic provider wrapping with optional configuration\n */\n function withProvider<P extends {}>(\n Component: React.ComponentType<P>,\n config?: WithProviderConfig\n ): React.FC<P> {\n const registryId = config?.registryId || contextName;\n \n const WithStoreProvider = (props: P) => {\n const managerRef = useRef<StoreManager<T> | null>(null);\n \n if (!managerRef.current) {\n managerRef.current = new StoreManager(registryId, initialStores);\n }\n \n return (\n <StoreContext.Provider value={{ managerRef }}>\n <Component {...props} />\n </StoreContext.Provider>\n );\n };\n \n WithStoreProvider.displayName = \n config?.displayName || `with${contextName}Provider(${Component.displayName || Component.name})`;\n \n return WithStoreProvider;\n }\n\n\n // Return the public API - focused and clean\n return {\n // Core\n Provider,\n useStore, // Primary API for store access\n \n // Utilities (optional use)\n useStoreManager, // Advanced use cases only\n useStoreInfo,\n useStoreClear,\n \n // HOC patterns\n withProvider,\n \n // Metadata\n contextName,\n initialStores\n } as const;\n}\n\n/**\n * Type helper for defining initial stores with better inference\n */\nexport type InferInitialStores<T> = T extends InitialStores<infer U> ? U : never;\n\n/**\n * Enhanced configuration for withProvider HOC with additional safety features\n */\nexport interface WithProviderConfig {\n /** Custom display name for debugging */\n displayName?: string;\n /** Custom registry identifier for isolation */\n registryId?: string;\n /** Enable automatic cleanup on unmount */\n autoCleanup?: boolean;\n /** Enable error boundary integration */\n errorBoundary?: boolean;\n}\n\n/**\n * Type helper for store values\n */\nexport type StoreValues<T extends Record<string, any>> = {\n [K in keyof T]: T[K] extends StoreConfig<infer V> ? V : T[K];\n};","/**\n * @fileoverview Focused hook for ref mounting logic\n * \n * Separated from useRefHandler for better maintainability and testing\n */\n\nimport { useCallback } from 'react';\nimport type { RefInitConfig } from '../types';\nimport type { CreateRefContextOptions } from '../createRefContext';\n\nexport interface InternalRefState<T> {\n target: T | null;\n isMounted: boolean;\n mountPromise: Promise<T> | null;\n mountResolvers: Set<(target: T) => void>;\n mountRejectors: Set<(error: Error) => void>;\n operationInProgress: boolean;\n listeners: Set<() => void>;\n mountCallbacks: Set<(target: T) => void>;\n}\n\n/**\n * Hook for handling ref mounting logic\n */\nexport function useRefMount<T>(\n refState: InternalRefState<T>,\n refNameStr: string,\n optionsRef: React.MutableRefObject<CreateRefContextOptions | undefined>,\n definitionsRef: React.MutableRefObject<any>\n) {\n const waitForMount = useCallback(async (): Promise<T> => {\n // 이미 마운트된 경우\n if (refState.target && refState.isMounted) {\n return refState.target;\n }\n \n // 기존 Promise가 있으면 재사용\n if (refState.mountPromise) {\n return refState.mountPromise;\n }\n \n // 타임아웃 설정 계산\n const globalOptions = optionsRef.current;\n const refConfig = definitionsRef.current?.[refNameStr] as RefInitConfig<any> | undefined;\n \n let timeoutMs: number | undefined;\n if (globalOptions?.disableTimeout) {\n timeoutMs = undefined;\n } else if (refConfig?.mountTimeout !== undefined) {\n timeoutMs = refConfig.mountTimeout;\n } else if (globalOptions?.defaultMountTimeout !== undefined) {\n timeoutMs = globalOptions.defaultMountTimeout;\n }\n \n // 새로운 Promise 생성\n refState.mountPromise = new Promise<T>((resolve, reject) => {\n refState.mountResolvers.add(resolve);\n refState.mountRejectors.add(reject);\n \n // 타임아웃 설정\n if (timeoutMs !== undefined && timeoutMs > 0) {\n const timeoutId = setTimeout(() => {\n const error = new Error(`Mount timeout after ${timeoutMs}ms for ref '${refNameStr}'`);\n refState.mountRejectors.forEach(rejector => rejector(error));\n refState.mountRejectors.clear();\n refState.mountResolvers.clear();\n refState.mountPromise = null;\n }, timeoutMs);\n \n // resolve/reject 시 타임아웃 정리\n const originalResolve = resolve;\n const originalReject = reject;\n \n const cleanupResolve = (value: T) => {\n clearTimeout(timeoutId);\n originalResolve(value);\n };\n \n const cleanupReject = (error: Error) => {\n clearTimeout(timeoutId);\n originalReject(error);\n };\n \n // resolver/rejector 교체\n refState.mountResolvers.delete(resolve);\n refState.mountRejectors.delete(reject);\n refState.mountResolvers.add(cleanupResolve);\n refState.mountRejectors.add(cleanupReject);\n }\n });\n \n return refState.mountPromise;\n }, [refState, refNameStr, optionsRef, definitionsRef]);\n\n const onMount = useCallback((callback: (target: T) => void) => {\n refState.mountCallbacks.add(callback);\n \n // 이미 마운트된 상태라면 즉시 실행\n if (refState.isMounted && refState.target) {\n callback(refState.target);\n }\n \n // cleanup 함수 반환\n return () => {\n refState.mountCallbacks.delete(callback);\n };\n }, [refState]);\n\n return {\n waitForMount,\n onMount,\n isMounted: refState.isMounted,\n isWaitingForMount: !refState.isMounted && refState.mountPromise !== null\n };\n}","/**\n * @fileoverview Focused hook for ref operations\n * \n * Separated from useRefHandler for better maintainability and testing\n */\n\nimport { useCallback } from 'react';\nimport type { RefOperation, RefOperationOptions, RefOperationResult, RefTarget } from '../types';\nimport type { InternalRefState } from './useRefMount';\n\n/**\n * Hook for handling ref operations\n */\nexport function useRefOperation<T>(\n refState: InternalRefState<T>\n) {\n const withTarget = useCallback(async <Result>(\n operation: RefOperation<T & RefTarget, Result>,\n options?: RefOperationOptions\n ): Promise<RefOperationResult<Result>> => {\n try {\n // 마운트 대기\n const target = await (async () => {\n if (refState.target && refState.isMounted) {\n return refState.target;\n }\n \n if (refState.mountPromise) {\n return refState.mountPromise;\n }\n \n refState.mountPromise = new Promise<T>((resolve, reject) => {\n refState.mountResolvers.add(resolve);\n refState.mountRejectors.add(reject);\n });\n \n return refState.mountPromise;\n })();\n \n // 순차 실행 보장\n while (refState.operationInProgress) {\n await new Promise(resolve => setTimeout(resolve, 10));\n }\n \n refState.operationInProgress = true;\n const startTime = Date.now();\n \n try {\n // AbortSignal 체크\n if (options?.signal?.aborted) {\n throw new Error('Operation aborted');\n }\n \n // 타임아웃 설정\n const timeoutPromise = options?.timeout\n ? new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Operation timed out')), options.timeout);\n })\n : null;\n \n // 작업 실행\n const operationPromise = operation(target as T & RefTarget, options);\n \n const result = timeoutPromise\n ? await Promise.race([operationPromise, timeoutPromise])\n : await operationPromise;\n \n return {\n success: true,\n result,\n duration: Date.now() - startTime,\n timestamp: Date.now()\n };\n } catch (error) {\n return {\n success: false,\n error: error as Error,\n duration: Date.now() - startTime,\n timestamp: Date.now()\n };\n } finally {\n refState.operationInProgress = false;\n }\n } catch (error) {\n return {\n success: false,\n error: error as Error,\n timestamp: Date.now()\n };\n }\n }, [refState]);\n\n const executeIfMounted = useCallback(<Result>(\n operation: (target: T & RefTarget) => Result\n ): Result | null => {\n if (refState.target && refState.isMounted) {\n try {\n return operation(refState.target);\n } catch (error) {\n console.error('Error in executeIfMounted:', error);\n return null;\n }\n }\n return null;\n }, [refState]);\n\n return {\n withTarget,\n executeIfMounted\n };\n}","/**\n * @fileoverview Focused hook for ref polling functionality\n * \n * Separated from useRefHandler for better maintainability and testing\n */\n\nimport { useCallback } from 'react';\nimport type { InternalRefState } from './useRefMount';\n\nexport interface RefPollingOptions {\n interval?: number;\n timeout?: number;\n onTick?: (elapsed: number, isMounted: boolean) => void;\n onTimeout?: (elapsed: number) => void;\n onSuccess?: (elapsed: number, target: any) => void;\n}\n\nexport interface RefPollingReturn<T> {\n promise: Promise<T>;\n cancel: () => void;\n isMounted: () => boolean;\n}\n\n/**\n * Hook for ref polling functionality\n */\nexport function useRefPolling() {\n const createPolling = useCallback(<T>(\n refState: InternalRefState<T>,\n refName: string,\n options: RefPollingOptions = {}\n ): RefPollingReturn<T> => {\n const {\n interval = 100,\n timeout,\n onTick,\n onTimeout,\n onSuccess\n } = options;\n\n let cancelled = false;\n let intervalId: ReturnType<typeof setInterval> | null = null;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n \n const startTime = Date.now();\n\n const promise = new Promise<T>((resolve, reject) => {\n const cleanup = () => {\n if (intervalId) {\n clearInterval(intervalId);\n intervalId = null;\n }\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n const check = () => {\n if (cancelled) {\n cleanup();\n reject(new Error('Polling cancelled'));\n return;\n }\n\n const elapsed = Date.now() - startTime;\n const isMounted = refState.isMounted && refState.target !== null;\n\n // onTick 콜백 실행\n if (onTick) {\n try {\n onTick(elapsed, isMounted);\n } catch (error) {\n console.error('Error in polling onTick callback:', error);\n }\n }\n\n if (isMounted && refState.target) {\n cleanup();\n // onSuccess 콜백 실행\n if (onSuccess) {\n try {\n onSuccess(elapsed, refState.target);\n } catch (error) {\n console.error('Error in polling onSuccess callback:', error);\n }\n }\n resolve(refState.target);\n return;\n }\n };\n\n // 타임아웃 설정\n if (timeout && timeout > 0) {\n timeoutId = setTimeout(() => {\n cleanup();\n const elapsed = Date.now() - startTime;\n // onTimeout 콜백 실행\n if (onTimeout) {\n try {\n onTimeout(elapsed);\n } catch (error) {\n console.error('Error in polling onTimeout callback:', error);\n }\n }\n reject(new Error(`Polling timeout after ${timeout}ms for ref '${refName}'`));\n }, timeout);\n }\n\n // 초기 체크\n check();\n\n // 주기적 체크\n intervalId = setInterval(check, interval);\n });\n\n const cancel = () => {\n cancelled = true;\n };\n\n const isMounted = () => {\n return refState.isMounted && refState.target !== null;\n };\n\n return {\n promise,\n cancel,\n isMounted\n };\n }, []);\n\n return createPolling;\n}","/**\n * @fileoverview Hook for subscribing to ref mount state changes\n * \n * Provides reactive subscription to isMounted state changes using useSyncExternalStore\n */\n\nimport { useEffect, useSyncExternalStore, useCallback, useRef } from 'react';\nimport type { InternalRefState } from './useRefMount';\n\n/**\n * Hook that subscribes to ref mount state changes using useSyncExternalStore\n * Returns reactive isMounted state that triggers re-renders\n */\nexport function useRefMountState<T>(refState: InternalRefState<T>): {\n isMounted: boolean;\n isWaitingForMount: boolean;\n mountedTarget: T | null;\n} {\n // Subscribe function for useSyncExternalStore\n const subscribe = useCallback((callback: () => void) => {\n if (!refState) return () => {};\n \n // Add listener to refState\n refState.listeners.add(callback);\n \n // Return cleanup function\n return () => {\n refState.listeners.delete(callback);\n };\n }, [refState]);\n \n // Cached snapshot reference - React 18 compatibility\n const cachedSnapshotRef = useRef<{\n isMounted: boolean;\n isWaitingForMount: boolean;\n mountedTarget: T | null;\n }>();\n\n // Get snapshot function for current state with caching\n const getSnapshot = useCallback(() => {\n if (!refState) {\n const snapshot = {\n isMounted: false,\n isWaitingForMount: false,\n mountedTarget: null as T | null\n };\n cachedSnapshotRef.current = snapshot;\n return snapshot;\n }\n \n const isWaitingForMount = !refState.isMounted && refState.mountPromise !== null;\n \n const newSnapshot = {\n isMounted: refState.isMounted,\n isWaitingForMount,\n mountedTarget: refState.isMounted ? refState.target : null as T | null\n };\n \n // Cache comparison to prevent infinite loops\n if (cachedSnapshotRef.current &&\n cachedSnapshotRef.current.isMounted === newSnapshot.isMounted &&\n cachedSnapshotRef.current.isWaitingForMount === newSnapshot.isWaitingForMount &&\n cachedSnapshotRef.current.mountedTarget === newSnapshot.mountedTarget) {\n return cachedSnapshotRef.current;\n }\n \n cachedSnapshotRef.current = newSnapshot;\n return newSnapshot;\n }, [refState]);\n \n // Server snapshot (for SSR) - cached static reference\n const serverSnapshotRef = useRef({\n isMounted: false,\n isWaitingForMount: false,\n mountedTarget: null as T | null\n });\n \n const getServerSnapshot = useCallback(() => {\n return serverSnapshotRef.current;\n }, []);\n \n // Use React's useSyncExternalStore for reactive subscriptions\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\n/**\n * Hook that provides a callback when mount state changes\n * Uses useSyncExternalStore internally for consistent behavior\n */\nexport function useOnMountStateChange<T>(\n refState: InternalRefState<T>,\n callback: (mounted: boolean, target: T | null) => void\n): void {\n // Get the current mount state using our reactive hook\n const { isMounted, mountedTarget } = useRefMountState(refState);\n \n // Use a stable callback to avoid unnecessary re-subscriptions\n const stableCallback = useCallback(callback, [callback]);\n \n // Call the callback when mount state changes\n useEffect(() => {\n stableCallback(isMounted, mountedTarget);\n }, [isMounted, mountedTarget, stableCallback]);\n}\n\n/**\n * Hook that returns a stable function to check current mount state\n * Useful for event handlers and callbacks\n */\nexport function useRefMountChecker<T>(refState: InternalRefState<T>) {\n return useCallback(() => {\n return {\n isMounted: refState.isMounted,\n isWaitingForMount: !refState.isMounted && refState.mountPromise !== null,\n target: refState.target\n };\n }, [refState]);\n}","/**\n * @fileoverview Simplified Reference Context V2\n * \n * useRef 기반의 간소화된 참조 관리 시스템\n * RefStore 클래스 없이 직접 상태 관리\n */\n\nimport React, { createContext, useContext, useMemo, useRef, useCallback, ReactNode, useState, useEffect } from 'react';\nimport type { \n RefTarget, \n RefOperation, \n RefOperationOptions, \n RefOperationResult,\n RefDefinitions,\n InferRefTypes\n} from './types';\nimport { useRefMount, useRefOperation, useRefPolling as useRefPollingHook, useRefMountState, useOnMountStateChange, useRefMountChecker, type InternalRefState, type RefPollingOptions } from './hooks';\nimport { ErrorHandlers } from '../stores/utils/error-handling';\n\n// InternalRefState is now imported from ./hooks\n\n/**\n * RefContext 반환 타입 - 향상된 타입 추론 지원\n */\nexport interface RefContextReturn<T> {\n Provider: React.FC<{ children: ReactNode }>;\n \n useRefHandler: <K extends keyof T>(refName: K) => {\n setRef: (target: T[K] | null) => void;\n target: T[K] | null;\n waitForMount: () => Promise<T[K]>;\n withTarget: <Result>(\n operation: RefOperation<T[K] & RefTarget, Result>,\n options?: RefOperationOptions\n ) => Promise<RefOperationResult<Result>>;\n isMounted: boolean;\n isWaitingForMount: boolean;\n onMount: (callback: (target: T[K]) => void) => () => void;\n executeIfMounted: <Result>(\n operation: (target: T[K] & RefTarget) => Result\n ) => Result | null;\n };\n \n useWaitForRefs: () => {\n <K extends keyof T>(...refNames: K[]): Promise<Pick<T, K>>;\n <K extends keyof T>(timeout: number, ...refNames: K[]): Promise<Pick<T, K>>;\n };\n useGetAllRefs: () => () => Partial<T>;\n useRefPolling: () => <K extends keyof T>(\n refName: K,\n options?: RefPollingOptions\n ) => {\n promise: Promise<T[K]>;\n cancel: () => void;\n isMounted: () => boolean;\n };\n \n useRefMountState: <K extends keyof T>(refName: K) => {\n isMounted: boolean;\n isWaitingForMount: boolean;\n mountedTarget: T[K] | null;\n };\n \n useOnMountStateChange: <K extends keyof T>(\n refName: K,\n callback: (mounted: boolean, target: T[K] | null) => void\n ) => void;\n \n useRefMountChecker: <K extends keyof T>(refName: K) => () => {\n isMounted: boolean;\n isWaitingForMount: boolean;\n target: T[K] | null;\n };\n \n contextName: string;\n refDefinitions?: T extends RefDefinitions ? T : undefined;\n}\n\n/**\n * createRefContext 옵션\n */\nexport interface CreateRefContextOptions {\n /** 글로벌 마운트 타임아웃 (ms). undefined면 타임아웃 없음 */\n defaultMountTimeout?: number;\n \n /** 개별 ref의 타임아웃 설정을 무시하고 타임아웃을 비활성화 */\n disableTimeout?: boolean;\n}\n\n/**\n * 간소화된 참조 컨텍스트 생성 함수 - 향상된 타입 추론\n */\nexport function createRefContext<T extends Record<string, any>>(\n contextName: string,\n options?: CreateRefContextOptions\n): RefContextReturn<T>;\n\nexport function createRefContext<T extends RefDefinitions>(\n contextName: string,\n refDefinitions: T,\n options?: CreateRefContextOptions\n): RefContextReturn<InferRefTypes<T>>;\n\nexport function createRefContext<T extends Record<string, any> | RefDefinitions>(\n contextName: string,\n refDefinitionsOrOptions?: T extends RefDefinitions ? T : CreateRefContextOptions,\n optionsWhenDefs?: CreateRefContextOptions\n): T extends RefDefinitions \n ? RefContextReturn<InferRefTypes<T>>\n : RefContextReturn<T> {\n \n // 파라미터 정규화 - 더 안전한 타입 처리\n const refDefinitions = (typeof refDefinitionsOrOptions === 'object' && \n refDefinitionsOrOptions !== null &&\n Object.values(refDefinitionsOrOptions as any).some(\n (value: any) => value && typeof value === 'object' && 'name' in value\n )) ? (refDefinitionsOrOptions as unknown) as T extends RefDefinitions ? T : undefined : undefined;\n \n const options = refDefinitions ? optionsWhenDefs : refDefinitionsOrOptions as CreateRefContextOptions | undefined;\n \n const hasDefinitions = Boolean(refDefinitions);\n \n // Context 타입\n interface RefContextValue {\n refsMapRef: React.MutableRefObject<Map<string, InternalRefState<any>>>;\n definitionsRef: React.MutableRefObject<T extends RefDefinitions ? T : undefined>;\n optionsRef: React.MutableRefObject<CreateRefContextOptions | undefined>;\n subscribeToRef: (refName: string, listener: () => void) => () => void;\n getRefState: (refName: string) => InternalRefState<any>;\n setRefTarget: (refName: string, target: any) => void;\n }\n \n // Context 생성\n const RefContext = createContext<RefContextValue | null>(null);\n \n // Provider 컴포넌트\n const Provider: React.FC<{ children: ReactNode }> = ({ children }) => {\n // 모든 ref 상태를 하나의 Map으로 관리\n const refsMapRef = useRef<Map<string, InternalRefState<any>>>(null!);\n \n // 초기화\n if (!refsMapRef.current) {\n const map = new Map<string, InternalRefState<any>>();\n \n // RefDefinitions가 있으면 미리 초기화\n if (hasDefinitions && refDefinitions) {\n Object.keys(refDefinitions).forEach((refName) => {\n map.set(refName, createInitialRefState());\n });\n }\n \n refsMapRef.current = map;\n }\n \n const definitionsRef = useRef<T extends RefDefinitions ? T : undefined>(\n refDefinitions as T extends RefDefinitions ? T : undefined\n );\n \n const optionsRef = useRef<CreateRefContextOptions | undefined>(options);\n \n // Provider 언마운트 시 모든 리소스 정리\n useEffect(() => {\n return () => {\n // 모든 ref 상태 정리\n if (refsMapRef.current) {\n refsMapRef.current.forEach((refState) => {\n // 진행 중인 Promise들 정리\n refState.mountRejectors.forEach(reject => {\n reject(new Error('Context provider unmounted'));\n });\n refState.mountResolvers.clear();\n refState.mountRejectors.clear();\n refState.mountPromise = null;\n \n // 콜백과 리스너 정리\n refState.mountCallbacks.clear();\n refState.listeners.clear();\n \n // 상태 초기화\n refState.target = null;\n refState.isMounted = false;\n refState.operationInProgress = false;\n });\n refsMapRef.current.clear();\n }\n };\n }, []);\n \n // ref 상태 구독 함수\n const subscribeToRef = useCallback((refName: string, listener: () => void) => {\n const refState = getOrCreateRefState(refsMapRef.current, refName);\n refState.listeners.add(listener);\n \n return () => {\n refState.listeners.delete(listener);\n };\n }, []);\n \n // ref 상태 가져오기\n const getRefState = useCallback((refName: string) => {\n return getOrCreateRefState(refsMapRef.current, refName);\n }, []);\n \n // ref target 설정\n const setRefTarget = useCallback((refName: string, target: any) => {\n const refState = getOrCreateRefState(refsMapRef.current, refName);\n \n if (target === null) {\n // Unmount\n refState.target = null;\n refState.isMounted = false;\n refState.mountPromise = null;\n \n // 알림\n refState.listeners.forEach(listener => listener());\n } else {\n // Mount\n refState.target = target;\n refState.isMounted = true;\n \n // 대기 중인 resolver들 실행\n refState.mountResolvers.forEach(resolve => resolve(target));\n refState.mountResolvers.clear();\n refState.mountRejectors.clear();\n refState.mountPromise = null;\n \n // 마운트 콜백들 실행\n refState.mountCallbacks.forEach(callback => {\n try {\n callback(target);\n } catch (error) {\n // Use standardized error handling (static import)\n ErrorHandlers.ref(\n 'Error in mount callback',\n { \n refName: String(refName),\n targetType: typeof target\n },\n error instanceof Error ? error : undefined\n );\n }\n });\n \n // 알림\n refState.listeners.forEach(listener => listener());\n }\n }, []);\n \n const contextValue = useMemo<RefContextValue>(() => ({\n refsMapRef,\n definitionsRef,\n optionsRef,\n subscribeToRef,\n getRefState,\n setRefTarget\n }), [subscribeToRef, getRefState, setRefTarget]);\n \n return React.createElement(\n RefContext.Provider,\n { value: contextValue },\n children\n );\n };\n \n // Enhanced context hook with disposal checking\n const useRefContext = () => {\n const context = useContext(RefContext);\n if (!context) {\n throw new Error(\n `useRefHandler must be used within ${contextName}.Provider. ` +\n `Wrap your component with <${contextName}.Provider>`\n );\n }\n \n // Disposal check would go here when implemented\n \n return context;\n };\n\n\n \n // 개별 ref 사용 hook - 리팩터링된 버전 (분리된 hooks 사용)\n const useRefHandler = <K extends keyof T>(refName: K) => {\n const { subscribeToRef, getRefState, setRefTarget, definitionsRef, optionsRef } = useRefContext();\n const refNameStr = String(refName);\n \n // 상태 변경 구독\n const [, forceUpdate] = useState({});\n \n useEffect(() => {\n const unsubscribe = subscribeToRef(refNameStr, () => {\n forceUpdate({});\n });\n return unsubscribe;\n }, [refNameStr, subscribeToRef]);\n \n // 현재 상태\n const refState = getRefState(refNameStr);\n \n // 분리된 hooks 사용\n const { waitForMount, onMount, isMounted, isWaitingForMount } = useRefMount(\n refState, \n refNameStr, \n optionsRef, \n definitionsRef\n );\n \n const { withTarget, executeIfMounted } = useRefOperation(refState);\n \n return useMemo(() => ({\n setRef: (target: T[K] | null) => {\n setRefTarget(refNameStr, target);\n },\n get target(): T[K] | null {\n return refState.target;\n },\n waitForMount: () => waitForMount() as Promise<T[K]>,\n withTarget: withTarget as <Result>(\n operation: RefOperation<T[K] & RefTarget, Result>,\n options?: RefOperationOptions\n ) => Promise<RefOperationResult<Result>>,\n isMounted,\n isWaitingForMount,\n onMount: (callback: (target: T[K]) => void) => onMount(callback as (target: any) => void),\n executeIfMounted: executeIfMounted as <Result>(\n operation: (target: T[K] & RefTarget) => Result\n ) => Result | null\n }), [refState, setRefTarget, refNameStr, waitForMount, withTarget, executeIfMounted, onMount, isMounted, isWaitingForMount]);\n };\n \n // 여러 ref 동시 대기 hook\n const useWaitForRefs = () => {\n const { getRefState } = useRefContext();\n \n return useCallback(async <K extends keyof T>(...args: [number, ...K[]] | K[]): Promise<Pick<T, K>> => {\n // 첫 번째 인수가 숫자인지 확인하여 timeout과 refNames 분리\n let timeout: number | undefined;\n let refNames: K[];\n \n if (typeof args[0] === 'number') {\n timeout = args[0];\n refNames = args.slice(1) as K[];\n } else {\n timeout = 1000; // 기본 1초 타임아웃\n refNames = args as K[];\n }\n const promises = refNames.map(async (refName) => {\n const refNameStr = String(refName);\n const refState = getRefState(refNameStr);\n \n // 마운트 대기\n if (refState.target && refState.isMounted) {\n return [refName, refState.target] as const;\n }\n \n if (!refState.mountPromise) {\n refState.mountPromise = new Promise<any>((resolve, reject) => {\n refState.mountResolvers.add(resolve);\n refState.mountRejectors.add(reject);\n });\n }\n \n // 타임아웃 처리 (항상 적용됨)\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Mount timeout after ${timeout}ms for ref '${refNameStr}'`));\n }, timeout);\n });\n \n const target = await Promise.race([refState.mountPromise, timeoutPromise]);\n return [refName, target] as const;\n });\n \n const results = await Promise.all(promises);\n return Object.fromEntries(results) as Pick<T, K>;\n }, [getRefState]);\n };\n \n // 모든 ref 상태 가져오기 hook\n const useGetAllRefs = () => {\n const { refsMapRef } = useRefContext();\n \n return useCallback((): Partial<T> => {\n const result: Partial<T> = {} as Partial<T>;\n \n refsMapRef.current.forEach((refState, refName) => {\n if (refState.target !== null && refState.isMounted) {\n (result as any)[refName] = refState.target;\n }\n });\n \n return result;\n }, [refsMapRef]);\n };\n \n // ref 폴링 유틸리티 hook - 리팩터링된 버전 (분리된 hook 사용)\n const useRefPolling = () => {\n const { getRefState } = useRefContext();\n const createPolling = useRefPollingHook();\n \n return useCallback(<K extends keyof T>(\n refName: K,\n options: RefPollingOptions = {}\n ) => {\n const refNameStr = String(refName);\n const refState = getRefState(refNameStr);\n \n return createPolling(refState, refNameStr, options) as {\n promise: Promise<T[K]>;\n cancel: () => void;\n isMounted: () => boolean;\n };\n }, [getRefState, createPolling]);\n };\n \n // 새로운 mount state subscription hooks\n const useRefMountStateHook = <K extends keyof T>(refName: K) => {\n const { getRefState } = useRefContext();\n const refState = getRefState(String(refName));\n return useRefMountState(refState) as {\n isMounted: boolean;\n isWaitingForMount: boolean;\n mountedTarget: T[K] | null;\n };\n };\n \n const useOnMountStateChangeHook = <K extends keyof T>(\n refName: K,\n callback: (mounted: boolean, target: T[K] | null) => void\n ) => {\n const { getRefState } = useRefContext();\n const refState = getRefState(String(refName));\n useOnMountStateChange(refState, callback);\n };\n \n const useRefMountCheckerHook = <K extends keyof T>(refName: K) => {\n const { getRefState } = useRefContext();\n const refState = getRefState(String(refName));\n return useRefMountChecker(refState) as () => {\n isMounted: boolean;\n isWaitingForMount: boolean;\n target: T[K] | null;\n };\n };\n\n return {\n Provider,\n useRefHandler,\n useWaitForRefs,\n useGetAllRefs,\n useRefPolling,\n useRefMountState: useRefMountStateHook,\n useOnMountStateChange: useOnMountStateChangeHook,\n useRefMountChecker: useRefMountCheckerHook,\n contextName,\n refDefinitions\n } as T extends RefDefinitions \n ? RefContextReturn<InferRefTypes<T>>\n : RefContextReturn<T>;\n}\n\n// 헬퍼 함수: 초기 ref 상태 생성\nfunction createInitialRefState<T>(): InternalRefState<T> {\n return {\n target: null,\n isMounted: false,\n mountPromise: null,\n mountResolvers: new Set(),\n mountRejectors: new Set(),\n operationInProgress: false,\n listeners: new Set(),\n mountCallbacks: new Set()\n };\n}\n\n// 헬퍼 함수: ref 상태 가져오기 또는 생성\nfunction getOrCreateRefState<T>(\n refsMap: Map<string, InternalRefState<T>>,\n refName: string\n): InternalRefState<T> {\n if (!refsMap.has(refName)) {\n refsMap.set(refName, createInitialRefState());\n }\n return refsMap.get(refName)!;\n}"],"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?: any) => 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: any) => 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 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-BWXLgYbF.d.cts.map |
| {"version":3,"file":"Store-BWXLgYbF.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?: any) => 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: any) => 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 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-Cdy48kLP.d.ts.map |
| {"version":3,"file":"Store-Cdy48kLP.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 { Store } from "./Store-BWXLgYbF.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 = any>(value: any): 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: any) => config is StoreInitConfig<T>; | ||
| readonly validateStore: <T>(store: any) => 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-BATcgK15.d.cts.map |
| {"version":3,"file":"utils-BATcgK15.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-Cdy48kLP.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 = any>(value: any): 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: any) => config is StoreInitConfig<T>; | ||
| readonly validateStore: <T>(store: any) => 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-cwvrN0GD.d.ts.map |
| {"version":3,"file":"utils-cwvrN0GD.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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"} |
| import { ErrorHandlers } from "./error-handling-CY0aBmPl.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" && typeof config.name === "string" && config.name.length > 0 && "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-DbcmrXN-.js.map |
| {"version":3,"file":"utils-DbcmrXN-.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 = any>(value: any): 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: any): config is StoreInitConfig<T> {\n return (\n config != null &&\n typeof config === 'object' &&\n typeof config.name === 'string' &&\n config.name.length > 0 &&\n 'initialValue' in config\n );\n },\n\n /**\n * Validate store instance\n */\n validateStore<T>(store: any): 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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"} |
| const require_error_handling = require('./error-handling-V4WsOwLB.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" && typeof config.name === "string" && config.name.length > 0 && "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; | ||
| } | ||
| }); |
| import { ComparisonOptions, ComparisonStrategy, CustomComparator, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store-BWXLgYbF.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-BATcgK15.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 { ComparisonOptions, ComparisonStrategy, CustomComparator, compareValues, getGlobalComparisonOptions, setGlobalComparisonOptions } from "./Store-Cdy48kLP.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-cwvrN0GD.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 }; |
+48
-18
@@ -1,5 +0,6 @@ | ||
| import { StoreErrorBoundary, StoreRegistry, createActionContext, createStore, createStoreErrorBoundary, defaultEqualityFn, useSafeStoreSubscription, withStoreErrorBoundary } from "./ActionContext-ag1IM87q.cjs"; | ||
| import { ContextActionError, ContextActionErrorType, ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getGlobalComparisonOptions, handleError, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions } from "./error-handling-BigSDMxi.cjs"; | ||
| import { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager } from "./utils-CzFwEht4.cjs"; | ||
| import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react"; | ||
| const require_error_handling = require('./error-handling-V4WsOwLB.cjs'); | ||
| const require_ActionContext = require('./ActionContext-DCVN9UaU.cjs'); | ||
| const require_utils = require('./utils-DsKdZNcV.cjs'); | ||
| let react = require("react"); | ||
| react = require_error_handling.__toESM(react); | ||
@@ -28,12 +29,12 @@ //#region src/stores/hooks/useComputedStore.ts | ||
| function useComputedStore(store, compute, config = {}) { | ||
| const { equalityFn = defaultEqualityFn, debug = false, name = "computed", onError, debounceMs, enableCache = false, cacheSize = 10, initialValue } = config; | ||
| const computeRef = useRef(compute); | ||
| const cacheRef = useRef(/* @__PURE__ */ new Map()); | ||
| const lastComputedRef = useRef(); | ||
| const lastInputRef = useRef(); | ||
| const { equalityFn = require_ActionContext.defaultEqualityFn, debug = false, name = "computed", onError, debounceMs, enableCache = false, cacheSize = 10, initialValue } = config; | ||
| const computeRef = (0, react.useRef)(compute); | ||
| const cacheRef = (0, react.useRef)(/* @__PURE__ */ new Map()); | ||
| const lastComputedRef = (0, react.useRef)(); | ||
| const lastInputRef = (0, react.useRef)(); | ||
| computeRef.current = compute; | ||
| const getCachedValue = useCallback((input) => { | ||
| const getCachedValue = (0, react.useCallback)((input) => { | ||
| if (!enableCache) return void 0; | ||
| if (lastInputRef.current === input && lastComputedRef.current !== void 0) return lastComputedRef.current; | ||
| for (const [cachedInput, cachedOutput] of cacheRef.current) if (defaultEqualityFn(cachedInput, input)) { | ||
| for (const [cachedInput, cachedOutput] of cacheRef.current) if (require_ActionContext.defaultEqualityFn(cachedInput, input)) { | ||
| if (debug) console.debug(`useComputedStore [${name}]: Using cached value`); | ||
@@ -47,3 +48,3 @@ return cachedOutput; | ||
| ]); | ||
| const setCachedValue = useCallback((input, output) => { | ||
| const setCachedValue = (0, react.useCallback)((input, output) => { | ||
| if (!enableCache) return; | ||
@@ -68,3 +69,3 @@ lastInputRef.current = input; | ||
| ]); | ||
| const computeSelector = useCallback((value) => { | ||
| const computeSelector = (0, react.useCallback)((value) => { | ||
| try { | ||
@@ -101,3 +102,3 @@ const cached = getCachedValue(value); | ||
| ]); | ||
| return useSafeStoreSubscription(store, computeSelector, { | ||
| return require_ActionContext.useSafeStoreSubscription(store, computeSelector, { | ||
| equalityFn, | ||
@@ -154,3 +155,3 @@ debounce: debounceMs, | ||
| const selectedGetSnapshot = selector ? () => selector(getSnapshot()) : getSnapshot; | ||
| return useSyncExternalStore(store?.subscribe ?? CONSTANTS.EMPTY_SUBSCRIBE, selectedGetSnapshot); | ||
| return (0, react.useSyncExternalStore)(store?.subscribe ?? CONSTANTS.EMPTY_SUBSCRIBE, selectedGetSnapshot); | ||
| } | ||
@@ -162,6 +163,6 @@ | ||
| function useLocalStore(initialValue, name) { | ||
| const storeRef = useRef(null); | ||
| const storeRef = (0, react.useRef)(null); | ||
| if (!storeRef.current) { | ||
| const storeName = name || `localStore_${++localStoreCounter}`; | ||
| storeRef.current = createStore(storeName, initialValue); | ||
| storeRef.current = require_ActionContext.createStore(storeName, initialValue); | ||
| } | ||
@@ -175,2 +176,31 @@ return { | ||
| //#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 }; | ||
| exports.ContextActionError = require_error_handling.ContextActionError; | ||
| exports.ContextActionErrorType = require_error_handling.ContextActionErrorType; | ||
| exports.ImmerUtils = require_error_handling.ImmerUtils; | ||
| 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.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; | ||
| exports.useComputedStore = useComputedStore; | ||
| exports.useLocalStore = useLocalStore; | ||
| exports.useSubscriptionManager = require_utils.useSubscriptionManager; | ||
| exports.withStoreErrorBoundary = require_ActionContext.withStoreErrorBoundary; |
+170
-1
@@ -1,1 +0,170 @@ | ||
| import{StoreErrorBoundary as e,StoreRegistry as t,createActionContext as n,createStore as r,createStoreErrorBoundary as i,defaultEqualityFn as a,useSafeStoreSubscription as o,withStoreErrorBoundary as s}from"./ActionContext-BYwfDgkQ.js";import{ContextActionError as c,ContextActionErrorType as l,ImmerUtils as u,compareValues as d,deepClone as f,deepCloneWithImmer as p,getGlobalComparisonOptions as m,handleError as h,preloadImmer as g,produce as _,safeGet as v,safeSet as y,setGlobalComparisonOptions as b}from"./error-handling-CWVo5dVS.js";import{SubscriptionManager as x,TypeUtils as S,composeProviders as C,createSafeEqualityFn as w,createStoreConfig as T,extractStoreValue as E,extractStoreValues as D,isStore as O,isValidStoreValue as k,useSubscriptionManager as A}from"./utils-CTHB2d2K.js";import{useCallback as j,useEffect as M,useMemo as N,useRef as P,useState as F,useSyncExternalStore as I}from"react";function L(e,t,n={}){let{equalityFn:r=a,debug:i=!1,name:s=`computed`,onError:c,debounceMs:l,enableCache:u=!1,cacheSize:d=10,initialValue:f}=n,p=P(t),m=P(new Map),h=P(),g=P();p.current=t;let _=j(e=>{if(u){if(g.current===e&&h.current!==void 0)return h.current;for(let[t,n]of m.current)if(a(t,e))return i&&console.debug(`useComputedStore [${s}]: Using cached value`),n}},[u,i,s]),v=j((e,t)=>{if(u){if(g.current=e,h.current=t,m.current.set(e,t),m.current.size>d){let e=m.current.keys().next().value;e!==void 0&&m.current.delete(e)}i&&console.debug(`useComputedStore [${s}]: Cache updated`,{cacheSize:m.current.size,input:e,output:t})}},[u,d,i,s]),y=j(e=>{try{let t=_(e);if(t!==void 0)return t;let n=i?performance.now():0,r=p.current(e);if(i){let t=performance.now()-n;console.debug(`useComputedStore [${s}]: Computed in ${t.toFixed(2)}ms`,{input:e,result:r})}return v(e,r),h.current=r,r}catch(e){if(c)return c(e),h.current===void 0?f:h.current;throw i&&console.error(`useComputedStore [${s}]: Error in computation:`,e),e}},[_,v,i,s,c,f]);return o(e,y,{equalityFn:r,debounce:l,debug:i,name:`computed-${s}`,initialValue:f})}const R={EMPTY_SUBSCRIBE:()=>()=>{},EMPTY_SNAPSHOT:()=>({value:void 0,name:`empty`,lastUpdate:0})};function z(e,t){let{defaultValue:n,selector:r}=t??{},i=e?.getSnapshot??(()=>({...R.EMPTY_SNAPSHOT(),...n!==void 0&&{value:n}})),a=r?()=>r(i()):i;return I(e?.subscribe??R.EMPTY_SUBSCRIBE,a)}let B=0;function V(e,t){let n=P(null);if(!n.current){let i=t||`localStore_${++B}`;n.current=r(i,e)}return{...z(n.current),store:n.current}}export{c as ContextActionError,l as ContextActionErrorType,u as ImmerUtils,e as StoreErrorBoundary,t as StoreRegistry,x as SubscriptionManager,S as TypeUtils,d as compareValues,C as composeProviders,n as createActionContext,w as createSafeEqualityFn,T as createStoreConfig,i as createStoreErrorBoundary,f as deepClone,p as deepCloneWithImmer,E as extractStoreValue,D as extractStoreValues,m as getGlobalComparisonOptions,h as handleContextActionError,O as isStore,k as isValidStoreValue,g as preloadImmer,_ as produce,v as safeGet,y as safeSet,b as setGlobalComparisonOptions,L as useComputedStore,V as useLocalStore,A as useSubscriptionManager,s as withStoreErrorBoundary}; | ||
| import { StoreErrorBoundary, StoreRegistry, createActionContext, createStore, createStoreErrorBoundary, defaultEqualityFn, useSafeStoreSubscription, withStoreErrorBoundary } from "./ActionContext-BzNYMKTH.js"; | ||
| import { ContextActionError, ContextActionErrorType, ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getGlobalComparisonOptions, handleError, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions } from "./error-handling-CY0aBmPl.js"; | ||
| import { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager } from "./utils-DbcmrXN-.js"; | ||
| import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react"; | ||
| //#region src/stores/hooks/useComputedStore.ts | ||
| /** | ||
| * Hook for computed store based on a single source store | ||
| * | ||
| * Creates a derived value that automatically recalculates when the source store changes. | ||
| * Includes performance optimizations like caching, debouncing, and intelligent re-computation | ||
| * to prevent unnecessary work. Perfect for derived state patterns. | ||
| * | ||
| * @template T - Type of the source store value | ||
| * @template R - Type of the computed result | ||
| * | ||
| * @param store - Source store to derive from | ||
| * @param compute - Function to compute derived value from store value | ||
| * @param config - Optional configuration for performance and debugging | ||
| * | ||
| * @returns The computed value that updates when source store changes | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usecomputedstore-patterns | ||
| * | ||
| * @public | ||
| */ | ||
| function useComputedStore(store, compute, config = {}) { | ||
| const { equalityFn = defaultEqualityFn, debug = false, name = "computed", onError, debounceMs, enableCache = false, cacheSize = 10, initialValue } = config; | ||
| const computeRef = useRef(compute); | ||
| const cacheRef = useRef(/* @__PURE__ */ new Map()); | ||
| const lastComputedRef = useRef(); | ||
| const lastInputRef = useRef(); | ||
| computeRef.current = compute; | ||
| const getCachedValue = useCallback((input) => { | ||
| if (!enableCache) return void 0; | ||
| if (lastInputRef.current === input && lastComputedRef.current !== void 0) return lastComputedRef.current; | ||
| for (const [cachedInput, cachedOutput] of cacheRef.current) if (defaultEqualityFn(cachedInput, input)) { | ||
| if (debug) console.debug(`useComputedStore [${name}]: Using cached value`); | ||
| return cachedOutput; | ||
| } | ||
| }, [ | ||
| enableCache, | ||
| debug, | ||
| name | ||
| ]); | ||
| const setCachedValue = useCallback((input, output) => { | ||
| if (!enableCache) return; | ||
| lastInputRef.current = input; | ||
| lastComputedRef.current = output; | ||
| cacheRef.current.set(input, output); | ||
| if (cacheRef.current.size > cacheSize) { | ||
| const firstKey = cacheRef.current.keys().next().value; | ||
| if (firstKey !== void 0) cacheRef.current.delete(firstKey); | ||
| } | ||
| if (debug) console.debug(`useComputedStore [${name}]: Cache updated`, { | ||
| cacheSize: cacheRef.current.size, | ||
| input, | ||
| output | ||
| }); | ||
| }, [ | ||
| enableCache, | ||
| cacheSize, | ||
| debug, | ||
| name | ||
| ]); | ||
| const computeSelector = useCallback((value) => { | ||
| try { | ||
| const cached = getCachedValue(value); | ||
| if (cached !== void 0) return cached; | ||
| const startTime = debug ? performance.now() : 0; | ||
| const result = computeRef.current(value); | ||
| if (debug) { | ||
| const duration = performance.now() - startTime; | ||
| console.debug(`useComputedStore [${name}]: Computed in ${duration.toFixed(2)}ms`, { | ||
| input: value, | ||
| result | ||
| }); | ||
| } | ||
| setCachedValue(value, result); | ||
| lastComputedRef.current = result; | ||
| return result; | ||
| } catch (error) { | ||
| if (onError) { | ||
| onError(error); | ||
| return lastComputedRef.current !== void 0 ? lastComputedRef.current : initialValue; | ||
| } | ||
| if (debug) console.error(`useComputedStore [${name}]: Error in computation:`, error); | ||
| throw error; | ||
| } | ||
| }, [ | ||
| getCachedValue, | ||
| setCachedValue, | ||
| debug, | ||
| name, | ||
| onError, | ||
| initialValue | ||
| ]); | ||
| return useSafeStoreSubscription(store, computeSelector, { | ||
| equalityFn, | ||
| debounce: debounceMs, | ||
| debug, | ||
| name: `computed-${name}`, | ||
| initialValue | ||
| }); | ||
| } | ||
| //#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 | ||
| let localStoreCounter = 0; | ||
| function useLocalStore(initialValue, name) { | ||
| const storeRef = useRef(null); | ||
| if (!storeRef.current) { | ||
| const storeName = name || `localStore_${++localStoreCounter}`; | ||
| storeRef.current = createStore(storeName, initialValue); | ||
| } | ||
| return { | ||
| ...useStoreSelector(storeRef.current), | ||
| store: storeRef.current | ||
| }; | ||
| } | ||
| //#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 }; | ||
| //# sourceMappingURL=advanced.js.map |
+78
-52
@@ -1,5 +0,9 @@ | ||
| import { ActionRegister, Store, StoreErrorBoundary, StoreRegistry, createActionContext, createStore, defaultEqualityFn, useSafeStoreSubscription, useStoreSelector } from "./ActionContext-ag1IM87q.cjs"; | ||
| import { ErrorHandlers } from "./error-handling-BigSDMxi.cjs"; | ||
| import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react"; | ||
| import { jsx } from "react/jsx-runtime"; | ||
| const require_error_handling = require('./error-handling-V4WsOwLB.cjs'); | ||
| const require_ActionContext = require('./ActionContext-DCVN9UaU.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); | ||
@@ -9,3 +13,3 @@ //#region src/stores/hooks/useStoreValue.ts | ||
| 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) || {}; | ||
| const { equalityFn = require_ActionContext.defaultEqualityFn, condition, debounce, throttle, initialValue, debug = false, name = store?.name || "unknown" } = (typeof selectorOrOptions === "function" ? options : selectorOrOptions) || {}; | ||
| const subscriptionOptions = { | ||
@@ -20,3 +24,3 @@ debug, | ||
| }; | ||
| return useSafeStoreSubscription(store, selector, subscriptionOptions); | ||
| return require_ActionContext.useSafeStoreSubscription(store, selector, subscriptionOptions); | ||
| } | ||
@@ -41,3 +45,3 @@ | ||
| this.stores = /* @__PURE__ */ new Map(); | ||
| this.registry = new StoreRegistry(name); | ||
| this.registry = new require_ActionContext.StoreRegistry(name); | ||
| this.initialStores = initialStores; | ||
@@ -82,3 +86,3 @@ } | ||
| } | ||
| const store = createStore(String(storeName), initialValue); | ||
| const store = require_ActionContext.createStore(String(storeName), initialValue); | ||
| const finalComparisonOptions = { | ||
@@ -97,2 +101,10 @@ strategy, | ||
| this.registry.register(String(storeName), store, metadata); | ||
| if (debug && process.env.NODE_ENV === "development") console.log(`🏪 Store context store created: ${String(storeName)}`, { | ||
| strategy, | ||
| tags, | ||
| version, | ||
| description, | ||
| hasCustomComparison: !!comparisonOptions?.customComparator, | ||
| ignoreKeys: comparisonOptions?.ignoreKeys | ||
| }); | ||
| this.stores.set(storeName, store); | ||
@@ -131,3 +143,3 @@ return store; | ||
| function createStoreContextImpl(contextName, initialStores) { | ||
| const StoreContext = createContext(null); | ||
| const StoreContext = (0, react.createContext)(null); | ||
| /** | ||
@@ -138,5 +150,5 @@ * Provider component with optional registry isolation | ||
| const effectiveRegistryId = registryId || contextName; | ||
| const managerRef = useRef(null); | ||
| const managerRef = (0, react.useRef)(null); | ||
| if (!managerRef.current) managerRef.current = new StoreManager(effectiveRegistryId, initialStores); | ||
| return /* @__PURE__ */ jsx(StoreContext.Provider, { | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreContext.Provider, { | ||
| value: { managerRef }, | ||
@@ -151,5 +163,5 @@ children | ||
| function useStore(storeName) { | ||
| const context = useContext(StoreContext); | ||
| const context = (0, react.useContext)(StoreContext); | ||
| if (!context || !context.managerRef.current) throw new Error(`useStore must be used within ${contextName}.Provider. Wrap your component with <${contextName}.Provider>`); | ||
| return useMemo(() => { | ||
| return (0, react.useMemo)(() => { | ||
| return context.managerRef.current.getStore(storeName); | ||
@@ -162,3 +174,3 @@ }, [context.managerRef, storeName]); | ||
| function useStoreManager() { | ||
| const context = useContext(StoreContext); | ||
| const context = (0, react.useContext)(StoreContext); | ||
| if (!context || !context.managerRef.current) throw new Error(`useStoreManager must be used within ${contextName}.Provider`); | ||
@@ -180,13 +192,13 @@ return context.managerRef.current; | ||
| */ | ||
| function withProvider(Component$1, config) { | ||
| function withProvider(Component, config) { | ||
| const registryId = config?.registryId || contextName; | ||
| const WithStoreProvider = (props) => { | ||
| const managerRef = useRef(null); | ||
| const managerRef = (0, react.useRef)(null); | ||
| if (!managerRef.current) managerRef.current = new StoreManager(registryId, initialStores); | ||
| return /* @__PURE__ */ jsx(StoreContext.Provider, { | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreContext.Provider, { | ||
| value: { managerRef }, | ||
| children: /* @__PURE__ */ jsx(Component$1, { ...props }) | ||
| children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { ...props }) | ||
| }); | ||
| }; | ||
| WithStoreProvider.displayName = config?.displayName || `with${contextName}Provider(${Component$1.displayName || Component$1.name})`; | ||
| WithStoreProvider.displayName = config?.displayName || `with${contextName}Provider(${Component.displayName || Component.name})`; | ||
| return WithStoreProvider; | ||
@@ -212,3 +224,3 @@ } | ||
| function useRefMount(refState, refNameStr, optionsRef, definitionsRef) { | ||
| const waitForMount = useCallback(async () => { | ||
| const waitForMount = (0, react.useCallback)(async () => { | ||
| if (refState.target && refState.isMounted) return refState.target; | ||
@@ -256,3 +268,3 @@ if (refState.mountPromise) return refState.mountPromise; | ||
| ]); | ||
| const onMount = useCallback((callback) => { | ||
| const onMount = (0, react.useCallback)((callback) => { | ||
| refState.mountCallbacks.add(callback); | ||
@@ -278,3 +290,3 @@ if (refState.isMounted && refState.target) callback(refState.target); | ||
| function useRefOperation(refState) { | ||
| const withTarget = useCallback(async (operation, options) => { | ||
| const withTarget = (0, react.useCallback)(async (operation, options) => { | ||
| try { | ||
@@ -323,3 +335,3 @@ const target = await (async () => { | ||
| }, [refState]); | ||
| const executeIfMounted = useCallback((operation) => { | ||
| const executeIfMounted = (0, react.useCallback)((operation) => { | ||
| if (refState.target && refState.isMounted) try { | ||
@@ -345,3 +357,3 @@ return operation(refState.target); | ||
| function useRefPolling() { | ||
| return useCallback((refState, refName, options = {}) => { | ||
| return (0, react.useCallback)((refState, refName, options = {}) => { | ||
| const { interval = 100, timeout, onTick, onTimeout, onSuccess } = options; | ||
@@ -421,3 +433,3 @@ let cancelled = false; | ||
| function useRefMountState(refState) { | ||
| const subscribe = useCallback((callback) => { | ||
| const subscribe = (0, react.useCallback)((callback) => { | ||
| if (!refState) return () => {}; | ||
@@ -429,4 +441,4 @@ refState.listeners.add(callback); | ||
| }, [refState]); | ||
| const cachedSnapshotRef = useRef(); | ||
| const getSnapshot = useCallback(() => { | ||
| const cachedSnapshotRef = (0, react.useRef)(); | ||
| const getSnapshot = (0, react.useCallback)(() => { | ||
| if (!refState) { | ||
@@ -451,3 +463,3 @@ const snapshot = { | ||
| }, [refState]); | ||
| const serverSnapshotRef = useRef({ | ||
| const serverSnapshotRef = (0, react.useRef)({ | ||
| isMounted: false, | ||
@@ -457,6 +469,6 @@ isWaitingForMount: false, | ||
| }); | ||
| const getServerSnapshot = useCallback(() => { | ||
| const getServerSnapshot = (0, react.useCallback)(() => { | ||
| return serverSnapshotRef.current; | ||
| }, []); | ||
| return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); | ||
| return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getServerSnapshot); | ||
| } | ||
@@ -469,4 +481,4 @@ /** | ||
| const { isMounted, mountedTarget } = useRefMountState(refState); | ||
| const stableCallback = useCallback(callback, [callback]); | ||
| useEffect(() => { | ||
| const stableCallback = (0, react.useCallback)(callback, [callback]); | ||
| (0, react.useEffect)(() => { | ||
| stableCallback(isMounted, mountedTarget); | ||
@@ -484,3 +496,3 @@ }, [ | ||
| function useRefMountChecker(refState) { | ||
| return useCallback(() => { | ||
| return (0, react.useCallback)(() => { | ||
| return { | ||
@@ -500,5 +512,5 @@ isMounted: refState.isMounted, | ||
| const hasDefinitions = Boolean(refDefinitions); | ||
| const RefContext = createContext(null); | ||
| const RefContext = (0, react.createContext)(null); | ||
| const Provider = ({ children }) => { | ||
| const refsMapRef = useRef(null); | ||
| const refsMapRef = (0, react.useRef)(null); | ||
| if (!refsMapRef.current) { | ||
@@ -511,5 +523,5 @@ const map = /* @__PURE__ */ new Map(); | ||
| } | ||
| const definitionsRef = useRef(refDefinitions); | ||
| const optionsRef = useRef(options); | ||
| useEffect(() => { | ||
| const definitionsRef = (0, react.useRef)(refDefinitions); | ||
| const optionsRef = (0, react.useRef)(options); | ||
| (0, react.useEffect)(() => { | ||
| return () => { | ||
@@ -534,3 +546,3 @@ if (refsMapRef.current) { | ||
| }, []); | ||
| const subscribeToRef = useCallback((refName, listener) => { | ||
| const subscribeToRef = (0, react.useCallback)((refName, listener) => { | ||
| const refState = getOrCreateRefState(refsMapRef.current, refName); | ||
@@ -542,6 +554,6 @@ refState.listeners.add(listener); | ||
| }, []); | ||
| const getRefState = useCallback((refName) => { | ||
| const getRefState = (0, react.useCallback)((refName) => { | ||
| return getOrCreateRefState(refsMapRef.current, refName); | ||
| }, []); | ||
| const setRefTarget = useCallback((refName, target) => { | ||
| const setRefTarget = (0, react.useCallback)((refName, target) => { | ||
| const refState = getOrCreateRefState(refsMapRef.current, refName); | ||
@@ -564,3 +576,3 @@ if (target === null) { | ||
| } catch (error) { | ||
| ErrorHandlers.ref("Error in mount callback", { | ||
| require_error_handling.ErrorHandlers.ref("Error in mount callback", { | ||
| refName: String(refName), | ||
@@ -574,3 +586,3 @@ targetType: typeof target | ||
| }, []); | ||
| const contextValue = useMemo(() => ({ | ||
| const contextValue = (0, react.useMemo)(() => ({ | ||
| refsMapRef, | ||
@@ -587,6 +599,6 @@ definitionsRef, | ||
| ]); | ||
| return React.createElement(RefContext.Provider, { value: contextValue }, children); | ||
| return react.default.createElement(RefContext.Provider, { value: contextValue }, children); | ||
| }; | ||
| const useRefContext = () => { | ||
| const context = useContext(RefContext); | ||
| const context = (0, react.useContext)(RefContext); | ||
| if (!context) throw new Error(`useRefHandler must be used within ${contextName}.Provider. Wrap your component with <${contextName}.Provider>`); | ||
@@ -598,4 +610,4 @@ return context; | ||
| const refNameStr = String(refName); | ||
| const [, forceUpdate] = useState({}); | ||
| useEffect(() => { | ||
| const [, forceUpdate] = (0, react.useState)({}); | ||
| (0, react.useEffect)(() => { | ||
| return subscribeToRef(refNameStr, () => { | ||
@@ -608,3 +620,3 @@ forceUpdate({}); | ||
| const { withTarget, executeIfMounted } = useRefOperation(refState); | ||
| return useMemo(() => ({ | ||
| return (0, react.useMemo)(() => ({ | ||
| setRef: (target) => { | ||
@@ -636,3 +648,3 @@ setRefTarget(refNameStr, target); | ||
| const { getRefState } = useRefContext(); | ||
| return useCallback(async (...args) => { | ||
| return (0, react.useCallback)(async (...args) => { | ||
| let timeout; | ||
@@ -669,3 +681,3 @@ let refNames; | ||
| const { refsMapRef } = useRefContext(); | ||
| return useCallback(() => { | ||
| return (0, react.useCallback)(() => { | ||
| const result = {}; | ||
@@ -681,3 +693,3 @@ refsMapRef.current.forEach((refState, refName) => { | ||
| const createPolling = useRefPolling(); | ||
| return useCallback((refName, options$1 = {}) => { | ||
| return (0, react.useCallback)((refName, options$1 = {}) => { | ||
| const refNameStr = String(refName); | ||
@@ -734,2 +746,16 @@ const refState = getRefState(refNameStr); | ||
| //#endregion | ||
| export { ActionRegister, Store, StoreErrorBoundary, StoreManager, createActionContext, createRefContext, createStore, createStoreContext, useStoreSelector, useStoreValue }; | ||
| Object.defineProperty(exports, 'ActionRegister', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __context_action_core.ActionRegister; | ||
| } | ||
| }); | ||
| exports.Store = require_ActionContext.Store; | ||
| exports.StoreErrorBoundary = require_ActionContext.StoreErrorBoundary; | ||
| exports.StoreManager = StoreManager; | ||
| exports.createActionContext = require_ActionContext.createActionContext; | ||
| exports.createRefContext = createRefContext; | ||
| exports.createStore = require_ActionContext.createStore; | ||
| exports.createStoreContext = createStoreContext; | ||
| exports.useStoreSelector = require_ActionContext.useStoreSelector; | ||
| exports.useStoreValue = useStoreValue; |
+711
-1
@@ -1,1 +0,711 @@ | ||
| import{ActionRegister as e,Store as t,StoreErrorBoundary as n,StoreRegistry as r,createActionContext as i,createStore as a,defaultEqualityFn as o,useSafeStoreSubscription as s,useStoreSelector as c}from"./ActionContext-BYwfDgkQ.js";import{ErrorHandlers as l}from"./error-handling-CWVo5dVS.js";import u,{createContext as d,useCallback as f,useContext as p,useEffect as m,useMemo as h,useRef as g,useState as _,useSyncExternalStore as v}from"react";import{jsx as y}from"react/jsx-runtime";function b(e,t,n){let r=typeof t==`function`?t:void 0,{equalityFn:i=o,condition:a,debounce:c,throttle:l,initialValue:u,debug:d=!1,name:f=e?.name||`unknown`}=(typeof t==`function`?n:t)||{},p={debug:d,name:f,equalityFn:i,initialValue:u,...c!==void 0&&{debounce:c},...l!==void 0&&{throttle:l},...a&&{condition:a}};return s(e,r,p)}var x=class{constructor(e,t){this.name=e,this.stores=new Map,this.registry=new r(e),this.initialStores=t}getStore(e){let t=this.stores.get(e);if(t)return t;let n=this.initialStores[e],r,i=`reference`,o,s=!1,c=[`declarative`],l,u;if(n&&typeof n==`object`&&`initialValue`in n){let e=n;r=e.initialValue,i=e.strategy||`reference`,o=e.description,s=e.debug||!1,c=e.tags?[`declarative`,...e.tags]:[`declarative`,i],l=e.version,u=e.comparisonOptions}else r=n,c=[`declarative`,i];let d=a(String(e),r),f={strategy:i,...u};d.setComparisonOptions(f);let p={name:String(e),tags:c,description:o||`Store: ${String(e)}`,debug:s,...l!==void 0&&{version:l}};return this.registry.register(String(e),d,p),this.stores.set(e,d),d}clear(){this.registry.clear(),this.stores.clear()}getInfo(){return{name:this.name,storeCount:this.stores.size,availableStores:Object.keys(this.initialStores)}}};function S(e,t){return C(e,t)}function C(e,t){let n=d(null);function r({children:r,registryId:i}){let a=i||e,o=g(null);return o.current||=new x(a,t),y(n.Provider,{value:{managerRef:o},children:r})}function i(t){let r=p(n);if(!r||!r.managerRef.current)throw Error(`useStore must be used within ${e}.Provider. Wrap your component with <${e}.Provider>`);return h(()=>r.managerRef.current.getStore(t),[r.managerRef,t])}function a(){let t=p(n);if(!t||!t.managerRef.current)throw Error(`useStoreManager must be used within ${e}.Provider`);return t.managerRef.current}function o(){return a().getInfo()}function s(){let e=a();return()=>e.clear()}function c(r,i){let a=i?.registryId||e,o=e=>{let i=g(null);return i.current||=new x(a,t),y(n.Provider,{value:{managerRef:i},children:y(r,{...e})})};return o.displayName=i?.displayName||`with${e}Provider(${r.displayName||r.name})`,o}return{Provider:r,useStore:i,useStoreManager:a,useStoreInfo:o,useStoreClear:s,withProvider:c,contextName:e,initialStores:t}}function w(e,t,n,r){let i=f(async()=>{if(e.target&&e.isMounted)return e.target;if(e.mountPromise)return e.mountPromise;let i=n.current,a=r.current?.[t],o;return i?.disableTimeout?o=void 0:a?.mountTimeout===void 0?i?.defaultMountTimeout!==void 0&&(o=i.defaultMountTimeout):o=a.mountTimeout,e.mountPromise=new Promise((n,r)=>{if(e.mountResolvers.add(n),e.mountRejectors.add(r),o!==void 0&&o>0){let i=setTimeout(()=>{let n=Error(`Mount timeout after ${o}ms for ref '${t}'`);e.mountRejectors.forEach(e=>e(n)),e.mountRejectors.clear(),e.mountResolvers.clear(),e.mountPromise=null},o),a=n,s=r;e.mountResolvers.delete(n),e.mountRejectors.delete(r),e.mountResolvers.add(e=>{clearTimeout(i),a(e)}),e.mountRejectors.add(e=>{clearTimeout(i),s(e)})}}),e.mountPromise},[e,t,n,r]),a=f(t=>(e.mountCallbacks.add(t),e.isMounted&&e.target&&t(e.target),()=>{e.mountCallbacks.delete(t)}),[e]);return{waitForMount:i,onMount:a,isMounted:e.isMounted,isWaitingForMount:!e.isMounted&&e.mountPromise!==null}}function T(e){let t=f(async(t,n)=>{try{let r=await(async()=>e.target&&e.isMounted?e.target:(e.mountPromise||=new Promise((t,n)=>{e.mountResolvers.add(t),e.mountRejectors.add(n)}),e.mountPromise))();for(;e.operationInProgress;)await new Promise(e=>setTimeout(e,10));e.operationInProgress=!0;let i=Date.now();try{if(n?.signal?.aborted)throw Error(`Operation aborted`);let e=n?.timeout?new Promise((e,t)=>{setTimeout(()=>t(Error(`Operation timed out`)),n.timeout)}):null,a=t(r,n);return{success:!0,result:e?await Promise.race([a,e]):await a,duration:Date.now()-i,timestamp:Date.now()}}catch(e){return{success:!1,error:e,duration:Date.now()-i,timestamp:Date.now()}}finally{e.operationInProgress=!1}}catch(e){return{success:!1,error:e,timestamp:Date.now()}}},[e]),n=f(t=>{if(e.target&&e.isMounted)try{return t(e.target)}catch(e){return console.error(`Error in executeIfMounted:`,e),null}return null},[e]);return{withTarget:t,executeIfMounted:n}}function E(){return f((e,t,n={})=>{let{interval:r=100,timeout:i,onTick:a,onTimeout:o,onSuccess:s}=n,c=!1,l=null,u=null,d=Date.now();return{promise:new Promise((n,f)=>{let p=()=>{l&&=(clearInterval(l),null),u&&=(clearTimeout(u),null)},m=()=>{if(c){p(),f(Error(`Polling cancelled`));return}let t=Date.now()-d,r=e.isMounted&&e.target!==null;if(a)try{a(t,r)}catch(e){console.error(`Error in polling onTick callback:`,e)}if(r&&e.target){if(p(),s)try{s(t,e.target)}catch(e){console.error(`Error in polling onSuccess callback:`,e)}n(e.target);return}};i&&i>0&&(u=setTimeout(()=>{p();let e=Date.now()-d;if(o)try{o(e)}catch(e){console.error(`Error in polling onTimeout callback:`,e)}f(Error(`Polling timeout after ${i}ms for ref '${t}'`))},i)),m(),l=setInterval(m,r)}),cancel:()=>{c=!0},isMounted:()=>e.isMounted&&e.target!==null}},[])}function D(e){let t=f(t=>e?(e.listeners.add(t),()=>{e.listeners.delete(t)}):()=>{},[e]),n=g(),r=f(()=>{if(!e){let e={isMounted:!1,isWaitingForMount:!1,mountedTarget:null};return n.current=e,e}let t=!e.isMounted&&e.mountPromise!==null,r={isMounted:e.isMounted,isWaitingForMount:t,mountedTarget:e.isMounted?e.target:null};return n.current&&n.current.isMounted===r.isMounted&&n.current.isWaitingForMount===r.isWaitingForMount&&n.current.mountedTarget===r.mountedTarget?n.current:(n.current=r,r)},[e]),i=g({isMounted:!1,isWaitingForMount:!1,mountedTarget:null}),a=f(()=>i.current,[]);return v(t,r,a)}function O(e,t){let{isMounted:n,mountedTarget:r}=D(e),i=f(t,[t]);m(()=>{i(n,r)},[n,r,i])}function k(e){return f(()=>({isMounted:e.isMounted,isWaitingForMount:!e.isMounted&&e.mountPromise!==null,target:e.target}),[e])}function A(e,t,n){let r=typeof t==`object`&&t&&Object.values(t).some(e=>e&&typeof e==`object`&&`name`in e)?t:void 0,i=r?n:t,a=!!r,o=d(null),s=({children:e})=>{let t=g(null);if(!t.current){let e=new Map;a&&r&&Object.keys(r).forEach(t=>{e.set(t,j())}),t.current=e}let n=g(r),s=g(i);m(()=>()=>{t.current&&(t.current.forEach(e=>{e.mountRejectors.forEach(e=>{e(Error(`Context provider unmounted`))}),e.mountResolvers.clear(),e.mountRejectors.clear(),e.mountPromise=null,e.mountCallbacks.clear(),e.listeners.clear(),e.target=null,e.isMounted=!1,e.operationInProgress=!1}),t.current.clear())},[]);let c=f((e,n)=>{let r=M(t.current,e);return r.listeners.add(n),()=>{r.listeners.delete(n)}},[]),d=f(e=>M(t.current,e),[]),p=f((e,n)=>{let r=M(t.current,e);n===null?(r.target=null,r.isMounted=!1,r.mountPromise=null,r.listeners.forEach(e=>e())):(r.target=n,r.isMounted=!0,r.mountResolvers.forEach(e=>e(n)),r.mountResolvers.clear(),r.mountRejectors.clear(),r.mountPromise=null,r.mountCallbacks.forEach(t=>{try{t(n)}catch(t){l.ref(`Error in mount callback`,{refName:String(e),targetType:typeof n},t instanceof Error?t:void 0)}}),r.listeners.forEach(e=>e()))},[]),_=h(()=>({refsMapRef:t,definitionsRef:n,optionsRef:s,subscribeToRef:c,getRefState:d,setRefTarget:p}),[c,d,p]);return u.createElement(o.Provider,{value:_},e)},c=()=>{let t=p(o);if(!t)throw Error(`useRefHandler must be used within ${e}.Provider. Wrap your component with <${e}.Provider>`);return t};return{Provider:s,useRefHandler:e=>{let{subscribeToRef:t,getRefState:n,setRefTarget:r,definitionsRef:i,optionsRef:a}=c(),o=String(e),[,s]=_({});m(()=>t(o,()=>{s({})}),[o,t]);let l=n(o),{waitForMount:u,onMount:d,isMounted:f,isWaitingForMount:p}=w(l,o,a,i),{withTarget:g,executeIfMounted:v}=T(l);return h(()=>({setRef:e=>{r(o,e)},get target(){return l.target},waitForMount:()=>u(),withTarget:g,isMounted:f,isWaitingForMount:p,onMount:e=>d(e),executeIfMounted:v}),[l,r,o,u,g,v,d,f,p])},useWaitForRefs:()=>{let{getRefState:e}=c();return f(async(...t)=>{let n,r;typeof t[0]==`number`?(n=t[0],r=t.slice(1)):(n=1e3,r=t);let i=r.map(async t=>{let r=String(t),i=e(r);if(i.target&&i.isMounted)return[t,i.target];i.mountPromise||=new Promise((e,t)=>{i.mountResolvers.add(e),i.mountRejectors.add(t)});let a=new Promise((e,t)=>{setTimeout(()=>{t(Error(`Mount timeout after ${n}ms for ref '${r}'`))},n)}),o=await Promise.race([i.mountPromise,a]);return[t,o]}),a=await Promise.all(i);return Object.fromEntries(a)},[e])},useGetAllRefs:()=>{let{refsMapRef:e}=c();return f(()=>{let t={};return e.current.forEach((e,n)=>{e.target!==null&&e.isMounted&&(t[n]=e.target)}),t},[e])},useRefPolling:()=>{let{getRefState:e}=c(),t=E();return f((n,r={})=>{let i=String(n),a=e(i);return t(a,i,r)},[e,t])},useRefMountState:e=>{let{getRefState:t}=c(),n=t(String(e));return D(n)},useOnMountStateChange:(e,t)=>{let{getRefState:n}=c(),r=n(String(e));O(r,t)},useRefMountChecker:e=>{let{getRefState:t}=c(),n=t(String(e));return k(n)},contextName:e,refDefinitions:r}}function j(){return{target:null,isMounted:!1,mountPromise:null,mountResolvers:new Set,mountRejectors:new Set,operationInProgress:!1,listeners:new Set,mountCallbacks:new Set}}function M(e,t){return e.has(t)||e.set(t,j()),e.get(t)}export{e as ActionRegister,t as Store,n as StoreErrorBoundary,x as StoreManager,i as createActionContext,A as createRefContext,a as createStore,S as createStoreContext,c as useStoreSelector,b as useStoreValue}; | ||
| import { Store, StoreErrorBoundary, StoreRegistry, createActionContext, createStore, defaultEqualityFn, useSafeStoreSubscription, useStoreSelector } from "./ActionContext-BzNYMKTH.js"; | ||
| import { ErrorHandlers } from "./error-handling-CY0aBmPl.js"; | ||
| import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react"; | ||
| import { jsx } from "react/jsx-runtime"; | ||
| import { ActionRegister } from "@context-action/core"; | ||
| //#region src/stores/hooks/useStoreValue.ts | ||
| function useStoreValue(store, selectorOrOptions, options) { | ||
| 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) || {}; | ||
| const subscriptionOptions = { | ||
| debug, | ||
| name, | ||
| equalityFn, | ||
| initialValue, | ||
| ...debounce !== void 0 && { debounce }, | ||
| ...throttle !== void 0 && { throttle }, | ||
| ...condition && { condition } | ||
| }; | ||
| return useSafeStoreSubscription(store, selector, subscriptionOptions); | ||
| } | ||
| //#endregion | ||
| //#region src/stores/patterns/declarative-store-pattern-v2.tsx | ||
| /** | ||
| * Internal store registry manager | ||
| * | ||
| * Manages store creation, caching, and registry coordination for the | ||
| * store context pattern. Handles store lifecycle and provides | ||
| * type-safe access to individual stores. | ||
| * | ||
| * @template T - Record of store names to their value types | ||
| * | ||
| * @public | ||
| */ | ||
| var StoreManager = class { | ||
| constructor(name, initialStores) { | ||
| this.name = name; | ||
| this.stores = /* @__PURE__ */ new Map(); | ||
| this.registry = new StoreRegistry(name); | ||
| this.initialStores = initialStores; | ||
| } | ||
| /** | ||
| * Get or create a store with type-safe inference | ||
| * | ||
| * Retrieves an existing store or creates a new one based on the initial | ||
| * configuration. Provides excellent type inference and caches stores | ||
| * for performance. | ||
| * | ||
| * @template K - Store name key | ||
| * @param storeName - Name of the store to retrieve or create | ||
| * @returns Typed store instance | ||
| * | ||
| * @internal | ||
| */ | ||
| getStore(storeName) { | ||
| const existing = this.stores.get(storeName); | ||
| if (existing) return existing; | ||
| const storeConfig = this.initialStores[storeName]; | ||
| let initialValue; | ||
| let strategy = "reference"; | ||
| let description; | ||
| let debug = false; | ||
| let tags = ["declarative"]; | ||
| let version; | ||
| let comparisonOptions; | ||
| if (storeConfig && typeof storeConfig === "object" && "initialValue" in storeConfig) { | ||
| const config = storeConfig; | ||
| initialValue = config.initialValue; | ||
| strategy = config.strategy || "reference"; | ||
| description = config.description; | ||
| debug = config.debug || false; | ||
| tags = config.tags ? ["declarative", ...config.tags] : ["declarative", strategy]; | ||
| version = config.version; | ||
| comparisonOptions = config.comparisonOptions; | ||
| } else { | ||
| initialValue = storeConfig; | ||
| tags = ["declarative", strategy]; | ||
| } | ||
| const store = createStore(String(storeName), initialValue); | ||
| const finalComparisonOptions = { | ||
| strategy, | ||
| ...comparisonOptions | ||
| }; | ||
| store.setComparisonOptions(finalComparisonOptions); | ||
| const metadata = { | ||
| name: String(storeName), | ||
| tags, | ||
| description: description || `Store: ${String(storeName)}`, | ||
| debug, | ||
| ...version !== void 0 && { version } | ||
| }; | ||
| this.registry.register(String(storeName), store, metadata); | ||
| if (debug && true) console.log(`🏪 Store context store created: ${String(storeName)}`, { | ||
| strategy, | ||
| tags, | ||
| version, | ||
| description, | ||
| hasCustomComparison: !!comparisonOptions?.customComparator, | ||
| ignoreKeys: comparisonOptions?.ignoreKeys | ||
| }); | ||
| this.stores.set(storeName, store); | ||
| return store; | ||
| } | ||
| /** | ||
| * Clear all stores | ||
| */ | ||
| clear() { | ||
| this.registry.clear(); | ||
| this.stores.clear(); | ||
| } | ||
| /** | ||
| * Get registry info | ||
| */ | ||
| getInfo() { | ||
| return { | ||
| name: this.name, | ||
| storeCount: this.stores.size, | ||
| availableStores: Object.keys(this.initialStores) | ||
| }; | ||
| } | ||
| }; | ||
| /** | ||
| * Implementation function that handles both overloads | ||
| */ | ||
| function createStoreContext(contextName, initialStores) { | ||
| return createStoreContextImpl(contextName, initialStores); | ||
| } | ||
| /** | ||
| * Main implementation function - Simplified and focused on store management | ||
| * | ||
| * @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage | ||
| */ | ||
| function createStoreContextImpl(contextName, initialStores) { | ||
| const StoreContext = createContext(null); | ||
| /** | ||
| * Provider component with optional registry isolation | ||
| */ | ||
| function Provider({ children, registryId }) { | ||
| const effectiveRegistryId = registryId || contextName; | ||
| const managerRef = useRef(null); | ||
| if (!managerRef.current) managerRef.current = new StoreManager(effectiveRegistryId, initialStores); | ||
| return /* @__PURE__ */ jsx(StoreContext.Provider, { | ||
| value: { managerRef }, | ||
| children | ||
| }); | ||
| } | ||
| /** | ||
| * Core hook - Get typed store by name | ||
| * This is the primary API for accessing stores | ||
| */ | ||
| function useStore(storeName) { | ||
| const context = useContext(StoreContext); | ||
| if (!context || !context.managerRef.current) throw new Error(`useStore must be used within ${contextName}.Provider. Wrap your component with <${contextName}.Provider>`); | ||
| return useMemo(() => { | ||
| return context.managerRef.current.getStore(storeName); | ||
| }, [context.managerRef, storeName]); | ||
| } | ||
| /** | ||
| * Get the store manager (for advanced use cases) | ||
| */ | ||
| function useStoreManager() { | ||
| const context = useContext(StoreContext); | ||
| if (!context || !context.managerRef.current) throw new Error(`useStoreManager must be used within ${contextName}.Provider`); | ||
| return context.managerRef.current; | ||
| } | ||
| /** | ||
| * Utility hooks | ||
| */ | ||
| function useStoreInfo() { | ||
| return useStoreManager().getInfo(); | ||
| } | ||
| function useStoreClear() { | ||
| const manager = useStoreManager(); | ||
| return () => manager.clear(); | ||
| } | ||
| /** | ||
| * HOC for automatic provider wrapping with optional configuration | ||
| */ | ||
| function withProvider(Component$1, config) { | ||
| const registryId = config?.registryId || contextName; | ||
| const WithStoreProvider = (props) => { | ||
| const managerRef = useRef(null); | ||
| if (!managerRef.current) managerRef.current = new StoreManager(registryId, initialStores); | ||
| return /* @__PURE__ */ jsx(StoreContext.Provider, { | ||
| value: { managerRef }, | ||
| children: /* @__PURE__ */ jsx(Component$1, { ...props }) | ||
| }); | ||
| }; | ||
| WithStoreProvider.displayName = config?.displayName || `with${contextName}Provider(${Component$1.displayName || Component$1.name})`; | ||
| return WithStoreProvider; | ||
| } | ||
| return { | ||
| Provider, | ||
| useStore, | ||
| useStoreManager, | ||
| useStoreInfo, | ||
| useStoreClear, | ||
| withProvider, | ||
| contextName, | ||
| initialStores | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/refs/hooks/useRefMount.ts | ||
| /** | ||
| * Hook for handling ref mounting logic | ||
| */ | ||
| function useRefMount(refState, refNameStr, optionsRef, definitionsRef) { | ||
| const waitForMount = useCallback(async () => { | ||
| if (refState.target && refState.isMounted) return refState.target; | ||
| if (refState.mountPromise) return refState.mountPromise; | ||
| const globalOptions = optionsRef.current; | ||
| const refConfig = definitionsRef.current?.[refNameStr]; | ||
| let timeoutMs; | ||
| if (globalOptions?.disableTimeout) timeoutMs = void 0; | ||
| else if (refConfig?.mountTimeout !== void 0) timeoutMs = refConfig.mountTimeout; | ||
| else if (globalOptions?.defaultMountTimeout !== void 0) timeoutMs = globalOptions.defaultMountTimeout; | ||
| refState.mountPromise = new Promise((resolve, reject) => { | ||
| refState.mountResolvers.add(resolve); | ||
| refState.mountRejectors.add(reject); | ||
| if (timeoutMs !== void 0 && timeoutMs > 0) { | ||
| const timeoutId = setTimeout(() => { | ||
| const error = /* @__PURE__ */ new Error(`Mount timeout after ${timeoutMs}ms for ref '${refNameStr}'`); | ||
| refState.mountRejectors.forEach((rejector) => rejector(error)); | ||
| refState.mountRejectors.clear(); | ||
| refState.mountResolvers.clear(); | ||
| refState.mountPromise = null; | ||
| }, timeoutMs); | ||
| const originalResolve = resolve; | ||
| const originalReject = reject; | ||
| const cleanupResolve = (value) => { | ||
| clearTimeout(timeoutId); | ||
| originalResolve(value); | ||
| }; | ||
| const cleanupReject = (error) => { | ||
| clearTimeout(timeoutId); | ||
| originalReject(error); | ||
| }; | ||
| refState.mountResolvers.delete(resolve); | ||
| refState.mountRejectors.delete(reject); | ||
| refState.mountResolvers.add(cleanupResolve); | ||
| refState.mountRejectors.add(cleanupReject); | ||
| } | ||
| }); | ||
| return refState.mountPromise; | ||
| }, [ | ||
| refState, | ||
| refNameStr, | ||
| optionsRef, | ||
| definitionsRef | ||
| ]); | ||
| const onMount = useCallback((callback) => { | ||
| refState.mountCallbacks.add(callback); | ||
| if (refState.isMounted && refState.target) callback(refState.target); | ||
| return () => { | ||
| refState.mountCallbacks.delete(callback); | ||
| }; | ||
| }, [refState]); | ||
| return { | ||
| waitForMount, | ||
| onMount, | ||
| isMounted: refState.isMounted, | ||
| isWaitingForMount: !refState.isMounted && refState.mountPromise !== null | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/refs/hooks/useRefOperation.ts | ||
| /** | ||
| * Hook for handling ref operations | ||
| */ | ||
| function useRefOperation(refState) { | ||
| const withTarget = useCallback(async (operation, options) => { | ||
| try { | ||
| const target = await (async () => { | ||
| if (refState.target && refState.isMounted) return refState.target; | ||
| if (refState.mountPromise) return refState.mountPromise; | ||
| refState.mountPromise = new Promise((resolve, reject) => { | ||
| refState.mountResolvers.add(resolve); | ||
| refState.mountRejectors.add(reject); | ||
| }); | ||
| return refState.mountPromise; | ||
| })(); | ||
| while (refState.operationInProgress) await new Promise((resolve) => setTimeout(resolve, 10)); | ||
| refState.operationInProgress = true; | ||
| const startTime = Date.now(); | ||
| try { | ||
| if (options?.signal?.aborted) throw new Error("Operation aborted"); | ||
| const timeoutPromise = options?.timeout ? new Promise((_, reject) => { | ||
| setTimeout(() => reject(/* @__PURE__ */ new Error("Operation timed out")), options.timeout); | ||
| }) : null; | ||
| const operationPromise = operation(target, options); | ||
| return { | ||
| success: true, | ||
| result: timeoutPromise ? await Promise.race([operationPromise, timeoutPromise]) : await operationPromise, | ||
| duration: Date.now() - startTime, | ||
| timestamp: Date.now() | ||
| }; | ||
| } catch (error) { | ||
| return { | ||
| success: false, | ||
| error, | ||
| duration: Date.now() - startTime, | ||
| timestamp: Date.now() | ||
| }; | ||
| } finally { | ||
| refState.operationInProgress = false; | ||
| } | ||
| } catch (error) { | ||
| return { | ||
| success: false, | ||
| error, | ||
| timestamp: Date.now() | ||
| }; | ||
| } | ||
| }, [refState]); | ||
| const executeIfMounted = useCallback((operation) => { | ||
| if (refState.target && refState.isMounted) try { | ||
| return operation(refState.target); | ||
| } catch (error) { | ||
| console.error("Error in executeIfMounted:", error); | ||
| return null; | ||
| } | ||
| return null; | ||
| }, [refState]); | ||
| return { | ||
| withTarget, | ||
| executeIfMounted | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/refs/hooks/useRefPolling.ts | ||
| /** | ||
| * Hook for ref polling functionality | ||
| */ | ||
| function useRefPolling() { | ||
| return useCallback((refState, refName, options = {}) => { | ||
| const { interval = 100, timeout, onTick, onTimeout, onSuccess } = options; | ||
| let cancelled = false; | ||
| let intervalId = null; | ||
| let timeoutId = null; | ||
| const startTime = Date.now(); | ||
| const promise = new Promise((resolve, reject) => { | ||
| const cleanup = () => { | ||
| if (intervalId) { | ||
| clearInterval(intervalId); | ||
| intervalId = null; | ||
| } | ||
| if (timeoutId) { | ||
| clearTimeout(timeoutId); | ||
| timeoutId = null; | ||
| } | ||
| }; | ||
| const check = () => { | ||
| if (cancelled) { | ||
| cleanup(); | ||
| reject(/* @__PURE__ */ new Error("Polling cancelled")); | ||
| return; | ||
| } | ||
| const elapsed = Date.now() - startTime; | ||
| const isMounted$1 = refState.isMounted && refState.target !== null; | ||
| if (onTick) try { | ||
| onTick(elapsed, isMounted$1); | ||
| } catch (error) { | ||
| console.error("Error in polling onTick callback:", error); | ||
| } | ||
| if (isMounted$1 && refState.target) { | ||
| cleanup(); | ||
| if (onSuccess) try { | ||
| onSuccess(elapsed, refState.target); | ||
| } catch (error) { | ||
| console.error("Error in polling onSuccess callback:", error); | ||
| } | ||
| resolve(refState.target); | ||
| return; | ||
| } | ||
| }; | ||
| if (timeout && timeout > 0) timeoutId = setTimeout(() => { | ||
| cleanup(); | ||
| const elapsed = Date.now() - startTime; | ||
| if (onTimeout) try { | ||
| onTimeout(elapsed); | ||
| } catch (error) { | ||
| console.error("Error in polling onTimeout callback:", error); | ||
| } | ||
| reject(/* @__PURE__ */ new Error(`Polling timeout after ${timeout}ms for ref '${refName}'`)); | ||
| }, timeout); | ||
| check(); | ||
| intervalId = setInterval(check, interval); | ||
| }); | ||
| const cancel = () => { | ||
| cancelled = true; | ||
| }; | ||
| const isMounted = () => { | ||
| return refState.isMounted && refState.target !== null; | ||
| }; | ||
| return { | ||
| promise, | ||
| cancel, | ||
| isMounted | ||
| }; | ||
| }, []); | ||
| } | ||
| //#endregion | ||
| //#region src/refs/hooks/useRefMountState.ts | ||
| /** | ||
| * Hook that subscribes to ref mount state changes using useSyncExternalStore | ||
| * Returns reactive isMounted state that triggers re-renders | ||
| */ | ||
| function useRefMountState(refState) { | ||
| const subscribe = useCallback((callback) => { | ||
| if (!refState) return () => {}; | ||
| refState.listeners.add(callback); | ||
| return () => { | ||
| refState.listeners.delete(callback); | ||
| }; | ||
| }, [refState]); | ||
| const cachedSnapshotRef = useRef(); | ||
| const getSnapshot = useCallback(() => { | ||
| if (!refState) { | ||
| const snapshot = { | ||
| isMounted: false, | ||
| isWaitingForMount: false, | ||
| mountedTarget: null | ||
| }; | ||
| cachedSnapshotRef.current = snapshot; | ||
| return snapshot; | ||
| } | ||
| const isWaitingForMount = !refState.isMounted && refState.mountPromise !== null; | ||
| const newSnapshot = { | ||
| isMounted: refState.isMounted, | ||
| isWaitingForMount, | ||
| mountedTarget: refState.isMounted ? refState.target : null | ||
| }; | ||
| if (cachedSnapshotRef.current && cachedSnapshotRef.current.isMounted === newSnapshot.isMounted && cachedSnapshotRef.current.isWaitingForMount === newSnapshot.isWaitingForMount && cachedSnapshotRef.current.mountedTarget === newSnapshot.mountedTarget) return cachedSnapshotRef.current; | ||
| cachedSnapshotRef.current = newSnapshot; | ||
| return newSnapshot; | ||
| }, [refState]); | ||
| const serverSnapshotRef = useRef({ | ||
| isMounted: false, | ||
| isWaitingForMount: false, | ||
| mountedTarget: null | ||
| }); | ||
| const getServerSnapshot = useCallback(() => { | ||
| return serverSnapshotRef.current; | ||
| }, []); | ||
| return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); | ||
| } | ||
| /** | ||
| * Hook that provides a callback when mount state changes | ||
| * Uses useSyncExternalStore internally for consistent behavior | ||
| */ | ||
| function useOnMountStateChange(refState, callback) { | ||
| const { isMounted, mountedTarget } = useRefMountState(refState); | ||
| const stableCallback = useCallback(callback, [callback]); | ||
| useEffect(() => { | ||
| stableCallback(isMounted, mountedTarget); | ||
| }, [ | ||
| isMounted, | ||
| mountedTarget, | ||
| stableCallback | ||
| ]); | ||
| } | ||
| /** | ||
| * Hook that returns a stable function to check current mount state | ||
| * Useful for event handlers and callbacks | ||
| */ | ||
| function useRefMountChecker(refState) { | ||
| return useCallback(() => { | ||
| return { | ||
| isMounted: refState.isMounted, | ||
| isWaitingForMount: !refState.isMounted && refState.mountPromise !== null, | ||
| target: refState.target | ||
| }; | ||
| }, [refState]); | ||
| } | ||
| //#endregion | ||
| //#region src/refs/createRefContext.ts | ||
| function createRefContext(contextName, refDefinitionsOrOptions, optionsWhenDefs) { | ||
| const refDefinitions = typeof refDefinitionsOrOptions === "object" && refDefinitionsOrOptions !== null && Object.values(refDefinitionsOrOptions).some((value) => value && typeof value === "object" && "name" in value) ? refDefinitionsOrOptions : void 0; | ||
| const options = refDefinitions ? optionsWhenDefs : refDefinitionsOrOptions; | ||
| const hasDefinitions = Boolean(refDefinitions); | ||
| const RefContext = createContext(null); | ||
| const Provider = ({ children }) => { | ||
| const refsMapRef = useRef(null); | ||
| if (!refsMapRef.current) { | ||
| const map = /* @__PURE__ */ new Map(); | ||
| if (hasDefinitions && refDefinitions) Object.keys(refDefinitions).forEach((refName) => { | ||
| map.set(refName, createInitialRefState()); | ||
| }); | ||
| refsMapRef.current = map; | ||
| } | ||
| const definitionsRef = useRef(refDefinitions); | ||
| const optionsRef = useRef(options); | ||
| useEffect(() => { | ||
| return () => { | ||
| if (refsMapRef.current) { | ||
| refsMapRef.current.forEach((refState) => { | ||
| refState.mountRejectors.forEach((reject) => { | ||
| reject(/* @__PURE__ */ new Error("Context provider unmounted")); | ||
| }); | ||
| refState.mountResolvers.clear(); | ||
| refState.mountRejectors.clear(); | ||
| refState.mountPromise = null; | ||
| refState.mountCallbacks.clear(); | ||
| refState.listeners.clear(); | ||
| refState.target = null; | ||
| refState.isMounted = false; | ||
| refState.operationInProgress = false; | ||
| }); | ||
| refsMapRef.current.clear(); | ||
| } | ||
| }; | ||
| }, []); | ||
| const subscribeToRef = useCallback((refName, listener) => { | ||
| const refState = getOrCreateRefState(refsMapRef.current, refName); | ||
| refState.listeners.add(listener); | ||
| return () => { | ||
| refState.listeners.delete(listener); | ||
| }; | ||
| }, []); | ||
| const getRefState = useCallback((refName) => { | ||
| return getOrCreateRefState(refsMapRef.current, refName); | ||
| }, []); | ||
| const setRefTarget = useCallback((refName, target) => { | ||
| const refState = getOrCreateRefState(refsMapRef.current, refName); | ||
| if (target === null) { | ||
| refState.target = null; | ||
| refState.isMounted = false; | ||
| refState.mountPromise = null; | ||
| refState.listeners.forEach((listener) => listener()); | ||
| } else { | ||
| refState.target = target; | ||
| refState.isMounted = true; | ||
| refState.mountResolvers.forEach((resolve) => resolve(target)); | ||
| refState.mountResolvers.clear(); | ||
| refState.mountRejectors.clear(); | ||
| refState.mountPromise = null; | ||
| refState.mountCallbacks.forEach((callback) => { | ||
| try { | ||
| callback(target); | ||
| } catch (error) { | ||
| ErrorHandlers.ref("Error in mount callback", { | ||
| refName: String(refName), | ||
| targetType: typeof target | ||
| }, error instanceof Error ? error : void 0); | ||
| } | ||
| }); | ||
| refState.listeners.forEach((listener) => listener()); | ||
| } | ||
| }, []); | ||
| const contextValue = useMemo(() => ({ | ||
| refsMapRef, | ||
| definitionsRef, | ||
| optionsRef, | ||
| subscribeToRef, | ||
| getRefState, | ||
| setRefTarget | ||
| }), [ | ||
| subscribeToRef, | ||
| getRefState, | ||
| setRefTarget | ||
| ]); | ||
| return React.createElement(RefContext.Provider, { value: contextValue }, children); | ||
| }; | ||
| const useRefContext = () => { | ||
| const context = useContext(RefContext); | ||
| if (!context) throw new Error(`useRefHandler must be used within ${contextName}.Provider. Wrap your component with <${contextName}.Provider>`); | ||
| return context; | ||
| }; | ||
| const useRefHandler = (refName) => { | ||
| const { subscribeToRef, getRefState, setRefTarget, definitionsRef, optionsRef } = useRefContext(); | ||
| const refNameStr = String(refName); | ||
| const [, forceUpdate] = useState({}); | ||
| useEffect(() => { | ||
| return subscribeToRef(refNameStr, () => { | ||
| forceUpdate({}); | ||
| }); | ||
| }, [refNameStr, subscribeToRef]); | ||
| const refState = getRefState(refNameStr); | ||
| const { waitForMount, onMount, isMounted, isWaitingForMount } = useRefMount(refState, refNameStr, optionsRef, definitionsRef); | ||
| const { withTarget, executeIfMounted } = useRefOperation(refState); | ||
| return useMemo(() => ({ | ||
| setRef: (target) => { | ||
| setRefTarget(refNameStr, target); | ||
| }, | ||
| get target() { | ||
| return refState.target; | ||
| }, | ||
| waitForMount: () => waitForMount(), | ||
| withTarget, | ||
| isMounted, | ||
| isWaitingForMount, | ||
| onMount: (callback) => onMount(callback), | ||
| executeIfMounted | ||
| }), [ | ||
| refState, | ||
| setRefTarget, | ||
| refNameStr, | ||
| waitForMount, | ||
| withTarget, | ||
| executeIfMounted, | ||
| onMount, | ||
| isMounted, | ||
| isWaitingForMount | ||
| ]); | ||
| }; | ||
| const useWaitForRefs = () => { | ||
| const { getRefState } = useRefContext(); | ||
| return useCallback(async (...args) => { | ||
| let timeout; | ||
| let refNames; | ||
| if (typeof args[0] === "number") { | ||
| timeout = args[0]; | ||
| refNames = args.slice(1); | ||
| } else { | ||
| timeout = 1e3; | ||
| refNames = args; | ||
| } | ||
| const promises = refNames.map(async (refName) => { | ||
| const refNameStr = String(refName); | ||
| const refState = getRefState(refNameStr); | ||
| if (refState.target && refState.isMounted) return [refName, refState.target]; | ||
| if (!refState.mountPromise) refState.mountPromise = new Promise((resolve, reject) => { | ||
| refState.mountResolvers.add(resolve); | ||
| refState.mountRejectors.add(reject); | ||
| }); | ||
| const timeoutPromise = new Promise((_, reject) => { | ||
| setTimeout(() => { | ||
| reject(/* @__PURE__ */ new Error(`Mount timeout after ${timeout}ms for ref '${refNameStr}'`)); | ||
| }, timeout); | ||
| }); | ||
| const target = await Promise.race([refState.mountPromise, timeoutPromise]); | ||
| return [refName, target]; | ||
| }); | ||
| const results = await Promise.all(promises); | ||
| return Object.fromEntries(results); | ||
| }, [getRefState]); | ||
| }; | ||
| const useGetAllRefs = () => { | ||
| const { refsMapRef } = useRefContext(); | ||
| return useCallback(() => { | ||
| const result = {}; | ||
| refsMapRef.current.forEach((refState, refName) => { | ||
| if (refState.target !== null && refState.isMounted) result[refName] = refState.target; | ||
| }); | ||
| return result; | ||
| }, [refsMapRef]); | ||
| }; | ||
| const useRefPolling$1 = () => { | ||
| const { getRefState } = useRefContext(); | ||
| const createPolling = useRefPolling(); | ||
| return useCallback((refName, options$1 = {}) => { | ||
| const refNameStr = String(refName); | ||
| const refState = getRefState(refNameStr); | ||
| return createPolling(refState, refNameStr, options$1); | ||
| }, [getRefState, createPolling]); | ||
| }; | ||
| const useRefMountStateHook = (refName) => { | ||
| const { getRefState } = useRefContext(); | ||
| const refState = getRefState(String(refName)); | ||
| return useRefMountState(refState); | ||
| }; | ||
| const useOnMountStateChangeHook = (refName, callback) => { | ||
| const { getRefState } = useRefContext(); | ||
| const refState = getRefState(String(refName)); | ||
| useOnMountStateChange(refState, callback); | ||
| }; | ||
| const useRefMountCheckerHook = (refName) => { | ||
| const { getRefState } = useRefContext(); | ||
| const refState = getRefState(String(refName)); | ||
| return useRefMountChecker(refState); | ||
| }; | ||
| return { | ||
| Provider, | ||
| useRefHandler, | ||
| useWaitForRefs, | ||
| useGetAllRefs, | ||
| useRefPolling: useRefPolling$1, | ||
| useRefMountState: useRefMountStateHook, | ||
| useOnMountStateChange: useOnMountStateChangeHook, | ||
| useRefMountChecker: useRefMountCheckerHook, | ||
| contextName, | ||
| refDefinitions | ||
| }; | ||
| } | ||
| function createInitialRefState() { | ||
| return { | ||
| target: null, | ||
| isMounted: false, | ||
| mountPromise: null, | ||
| mountResolvers: /* @__PURE__ */ new Set(), | ||
| mountRejectors: /* @__PURE__ */ new Set(), | ||
| operationInProgress: false, | ||
| listeners: /* @__PURE__ */ new Set(), | ||
| mountCallbacks: /* @__PURE__ */ new Set() | ||
| }; | ||
| } | ||
| function getOrCreateRefState(refsMap, refName) { | ||
| if (!refsMap.has(refName)) refsMap.set(refName, createInitialRefState()); | ||
| return refsMap.get(refName); | ||
| } | ||
| //#endregion | ||
| export { ActionRegister, Store, StoreErrorBoundary, StoreManager, createActionContext, createRefContext, createStore, createStoreContext, useStoreSelector, useStoreValue }; | ||
| //# sourceMappingURL=index.js.map |
+22
-3
@@ -1,4 +0,23 @@ | ||
| import { ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getGlobalComparisonOptions, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions } from "./error-handling-BigSDMxi.cjs"; | ||
| import { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager } from "./utils-CzFwEht4.cjs"; | ||
| const require_error_handling = require('./error-handling-V4WsOwLB.cjs'); | ||
| const require_utils = require('./utils-DsKdZNcV.cjs'); | ||
| export { ImmerUtils, SubscriptionManager, TypeUtils, compareValues, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useSubscriptionManager }; | ||
| exports.ImmerUtils = require_error_handling.ImmerUtils; | ||
| exports.SubscriptionManager = require_utils.SubscriptionManager; | ||
| exports.TypeUtils = require_utils.TypeUtils; | ||
| exports.compareValues = require_error_handling.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; |
+4
-1
@@ -1,1 +0,4 @@ | ||
| import{ImmerUtils as e,compareValues as t,deepClone as n,deepCloneWithImmer as r,getGlobalComparisonOptions as i,preloadImmer as a,produce as o,safeGet as s,safeSet as c,setGlobalComparisonOptions as l}from"./error-handling-CWVo5dVS.js";import{SubscriptionManager as u,TypeUtils as d,composeProviders as f,createSafeEqualityFn as p,createStoreConfig as m,extractStoreValue as h,extractStoreValues as g,isStore as _,isValidStoreValue as v,useSubscriptionManager as y}from"./utils-CTHB2d2K.js";export{e as ImmerUtils,u as SubscriptionManager,d as TypeUtils,t as compareValues,f as composeProviders,p as createSafeEqualityFn,m as createStoreConfig,n as deepClone,r as deepCloneWithImmer,h as extractStoreValue,g as extractStoreValues,i as getGlobalComparisonOptions,_ as isStore,v as isValidStoreValue,a as preloadImmer,o as produce,s as safeGet,c as safeSet,l as setGlobalComparisonOptions,y as useSubscriptionManager}; | ||
| import { ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getGlobalComparisonOptions, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions } from "./error-handling-CY0aBmPl.js"; | ||
| import { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager } from "./utils-DbcmrXN-.js"; | ||
| export { ImmerUtils, SubscriptionManager, TypeUtils, compareValues, composeProviders, createSafeEqualityFn, createStoreConfig, deepClone, deepCloneWithImmer, extractStoreValue, extractStoreValues, getGlobalComparisonOptions, isStore, isValidStoreValue, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions, useSubscriptionManager }; |
+3
-4
| { | ||
| "name": "@context-action/react", | ||
| "version": "0.7.6", | ||
| "version": "0.7.7", | ||
| "type": "module", | ||
@@ -88,3 +88,3 @@ "description": "React integration for @context-action/core - Context and hooks for type-safe action management", | ||
| "dependencies": { | ||
| "@context-action/core": "0.7.6", | ||
| "@context-action/core": "workspace:*", | ||
| "immer": "10.1.1" | ||
@@ -131,4 +131,3 @@ }, | ||
| "not ie 11" | ||
| ], | ||
| "gitHead": "911a89b580e8a560331a826936090b67c25e0e56" | ||
| ] | ||
| } |
Sorry, the diff of this file is too big to display
| const e=require(`./error-handling-C48VsCLN.cjs`);let t=require(`react`);t=e.__toESM(t);let n=require(`react/jsx-runtime`);n=e.__toESM(n);var r=class{constructor(e=`default`){this.stores=new Map,this.metadata=new WeakMap,this.listeners=new Set,this._snapshot=[],this.name=e}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}register(e,t,n){this.stores.has(e)&&this.stores.get(e),this.stores.set(e,t),n&&this.metadata.set(t,{registeredAt:Date.now(),name:e,...n}),this._updateSnapshot(),this._notifyListeners()}unregister(e){return this.stores.get(e)?(this.stores.delete(e),this._updateSnapshot(),this._notifyListeners(),!0):!1}getStore(e){return this.stores.get(e)}hasStore(e){return this.stores.has(e)}getStoreNames(){return Array.from(this.stores.keys())}getAllStores(){return new Map(this.stores)}getStoreMetadata(e){let t=typeof e==`string`?this.stores.get(e):e;return t?this.metadata.get(t):void 0}updateStoreMetadata(e,t){let n=typeof e==`string`?this.stores.get(e):e;if(!n)return!1;let r=this.metadata.get(n);return this.metadata.set(n,{registeredAt:Date.now(),name:typeof e==`string`?e:r?.name||`unknown`,...r,...t}),!0}getSnapshot(){return this._snapshot}clear(){this.stores.clear(),this._updateSnapshot(),this._notifyListeners()}dispose(){this.clear(),this.listeners.clear()}getStoreCount(){return this.stores.size}forEach(e){this.stores.forEach((t,n)=>{e(t,n)})}getStats(){return{totalStores:this.stores.size,storeNames:this.getStoreNames(),registryName:this.name}}_updateSnapshot(){this._snapshot=Array.from(this.stores.entries())}_notifyListeners(){this.listeners.forEach(e=>{try{e()}catch(e){console.error(`Error in registry listener:`,e)}})}};const i=new r(`global`);function a(e){return typeof e==`object`&&!!e&&`target`in e&&`isReady`in e&&`isMounted`in e&&`mountPromise`in e&&typeof e.isReady==`boolean`&&typeof e.isMounted==`boolean`}function o(e){return e instanceof Event}function s(e){return typeof e==`object`&&!!e&&typeof e.preventDefault==`function`}function c(e){return typeof e==`object`&&!!e&&`target`in e}function l(e){return e instanceof Element}function u(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function d(e,t=!0){if(!u(e)||a(e))return!1;if(f(e))return!0;if(t){for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t)){let n=e[t];if(f(n))return!0}}return!1}function f(e){if(!u(e))return!1;let t=c(e),n=s(e),r=o(e),i=`type`in e&&typeof e.type==`string`&&(t||n),a=`nativeEvent`in e||`persist`in e||`$$typeof`in e||`_reactInternalFiber`in e||`_owner`in e,l=e?.constructor?.name,d=l?l.includes(`Event`)||l===`SyntheticEvent`||l.includes(`MouseEvent`)||l.includes(`KeyboardEvent`)||l.includes(`TouchEvent`)||l.includes(`FocusEvent`)||l.includes(`SubmitEvent`):!1;return r||i||a||d}function p(e){if(!u(e))return[];let t=[];for(let n in e)if(Object.prototype.hasOwnProperty.call(e,n)){let r=e[n];(l(r)||o(r)||u(r)&&c(r))&&t.push(n)}return t}const m={isRefState:a,isDOMEvent:o,isEventLike:s,hasTargetProperty:c,isDOMElement:l,isObject:u,isSuspiciousEventObject:d,findProblematicProperties:p};var h=class{constructor(e,t){this.listeners=new Set,this._lastClonedValue=null,this._lastClonedVersion=0,this._version=0,this.isUpdating=!1,this.updateQueue=[],this.notificationMode=`batched`,this.pendingNotification=!1,this.animationFrameId=null,this.pendingUpdatesCount=0,this.cleanupTasks=new Set,this.isDisposed=!1,this.errorCount=0,this.lastErrorTime=0,this.MAX_ERROR_COUNT=5,this.ERROR_RESET_TIME=6e4,this.subscriptionRegistry=new WeakMap,this.cloningEnabled=!0,this.subscribe=e=>{if(this.isDisposed)return console.warn(`Cannot subscribe to disposed store "${this.name}"`),()=>{};let t=()=>{if(!this.isDisposed)try{e(),this.errorCount>0&&(this.errorCount=0)}catch(t){this._handleListenerError(t,e)}};return this.subscriptionRegistry.set(e,{subscribedAt:Date.now(),errorCount:0,enhancedListener:t}),this.listeners.add(t),()=>{this.listeners.delete(t),this.subscriptionRegistry.delete(e)}},this.getSnapshot=()=>this._snapshot,this.name=e,this._value=t,this._snapshot=this._createSnapshot()}getValue(){return this.cloningEnabled?this._lastClonedVersion===this._version&&this._lastClonedValue!==null?this._lastClonedValue:(this._lastClonedValue=e.safeGet(this._value,this.cloningEnabled),this._lastClonedVersion=this._version,this._lastClonedValue):this._value}setValue(t,n){if(m.isObject(t)&&!m.isRefState(t)&&m.isSuspiciousEventObject(t)){let r=n?.eventHandling||`block`,i=m.hasTargetProperty(t),a=m.isEventLike(t),o=m.isDOMEvent(t);switch(r){case`allow`:break;case`transform`:if(n?.eventTransform)try{t=n.eventTransform(t)}catch(n){e.ErrorHandlers.store(`Event transformation failed in Store.setValue`,{storeName:this.name,valueType:typeof t,error:n instanceof Error?n.message:String(n)});return}else{e.ErrorHandlers.store(`Event transformation requested but no transform function provided`,{storeName:this.name,valueType:typeof t});return}break;case`block`:default:e.ErrorHandlers.store(`Event object detected in Store.setValue - this may cause memory leaks`,{storeName:this.name,valueType:typeof t,constructorName:t?.constructor?.name,isEvent:o,hasTargetProperty:i,hasPreventDefault:a,problematicProperties:m.findProblematicProperties(t)});return}}let r=n?.skipClone?t:e.safeSet(t,this.cloningEnabled),i=!0;n?.skipComparison||(i=this._compareValues(this._value,r)),i&&(this._value=r,this._version++,this._snapshot=this._createSnapshot(),this._scheduleNotification())}update(t){if(this.isUpdating){this.updateQueue.push(()=>this.update(t));return}try{this.isUpdating=!0;let n;try{n=e.produce(this._value,e=>{let n=t(e);return n===void 0?e:n})}catch{let r=e.safeGet(this._value,this.cloningEnabled);try{n=e.produce(r,e=>{let n=t(e);return n===void 0?e:n})}catch{n=t(r)}}if(m.isObject(n)&&!m.isRefState(n)&&m.isSuspiciousEventObject(n)){let t=m.hasTargetProperty(n),r=m.isEventLike(n),i=m.isDOMEvent(n);e.ErrorHandlers.store(`Event object detected in Store.update result - this may cause memory leaks`,{storeName:this.name,updatedValueType:typeof n,constructorName:n?.constructor?.name,isEvent:i,hasTargetProperty:t,hasPreventDefault:r,problematicProperties:m.findProblematicProperties(n)});return}this.setValue(n)}finally{if(this.isUpdating=!1,this.updateQueue.length>0){let e=this.updateQueue.shift();e&&Promise.resolve().then(e)}}}getListenerCount(){return this.listeners.size}clearListeners(){this.listeners.clear()}registerCleanup(e){return this.isDisposed?(console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`),()=>{}):(this.cleanupTasks.add(e),()=>this.cleanupTasks.delete(e))}dispose(){if(!this.isDisposed){this.isDisposed=!0;try{this.cleanupTasks.forEach(t=>{try{t()}catch(t){e.ErrorHandlers.store(`Error during cleanup task execution`,{storeName:this.name},t instanceof Error?t:void 0)}}),this.cleanupTasks.clear(),this.subscriptionRegistry=new WeakMap,this.clearListeners(),this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.pendingNotification=!1,this.updateQueue.length=0}catch(t){e.ErrorHandlers.store(`Critical error during store disposal`,{storeName:this.name},t instanceof Error?t:void 0)}}}isStoreDisposed(){return this.isDisposed}setCustomComparator(e){this.customComparator=e}setComparisonOptions(e){this.comparisonOptions=e}setCloningEnabled(e){this.cloningEnabled=e}isCloningEnabled(){return this.cloningEnabled}_compareValues(t,n){let r;try{r=this.customComparator?!this.customComparator(t,n):this.comparisonOptions?!e.compareValues(t,n,this.comparisonOptions):!e.compareValues(t,n,{strategy:`reference`})}catch(i){e.ErrorHandlers.store(`Error during value comparison, falling back to reference comparison`,{storeName:this.name},i instanceof Error?i:void 0),r=!Object.is(t,n)}return r}_createSnapshot(){return{value:e.safeGet(this._value,this.cloningEnabled),name:this.name,lastUpdate:Date.now()}}_scheduleNotification(){this.notificationMode===`immediate`?this._notifyListeners():this._scheduleWithRAF()}_scheduleWithRAF(){this.pendingUpdatesCount++,this.pendingNotification||(this.pendingNotification=!0,this.animationFrameId=requestAnimationFrame(()=>{this._executeNotification()}))}_executeNotification(){this.pendingNotification=!1,this.animationFrameId=null,this.pendingUpdatesCount,this.pendingUpdatesCount=0,this._notifyListeners()}_handleListenerError(t,n){let r=Date.now();r-this.lastErrorTime>this.ERROR_RESET_TIME&&(this.errorCount=0),this.errorCount++,this.lastErrorTime=r;let i=this.subscriptionRegistry.get(n);i&&i.errorCount++,e.ErrorHandlers.store(`Error in store listener execution`,{storeName:this.name,listenerCount:this.listeners.size,errorCount:this.errorCount,subscriptionAge:i?r-i.subscribedAt:`unknown`},t instanceof Error?t:void 0),i&&i.errorCount>=3&&(console.warn(`Removing problematic listener from store "${this.name}" after ${i.errorCount} errors`),this.listeners.delete(i.enhancedListener),this.subscriptionRegistry.delete(n)),this.errorCount>=this.MAX_ERROR_COUNT&&(console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`),this.clearListeners())}_notifyListeners(){this.isDisposed||this.listeners.forEach(e=>{this.isDisposed||e()})}};function g(e,t){return new h(e,t)}function _(e,t={}){let{debounce:n,throttle:r,condition:i,debug:a,name:o=`unknown`}=t;return t=>{if(!e)return()=>{};let s=null,c=null,l=0,u=e.subscribe(()=>{if(i&&!i()){a&&console.debug(`[${o}] Subscription suspended due to condition`);return}let e=performance.now();if(r&&r>0){if(e-l<r){c&&clearTimeout(c),c=setTimeout(()=>{l=performance.now(),t()},r-(e-l));return}l=e}if(n&&n>0){s&&clearTimeout(s),s=setTimeout(()=>{t(),a&&console.debug(`[${o}] Debounced callback executed after ${n}ms`)},n);return}t()});return()=>{s&&clearTimeout(s),c&&clearTimeout(c),u()}}}function v(e,n,r={}){let{initialValue:i,equalityFn:a,...o}=r,s=(0,t.useCallback)(t=>e?o.debounce||o.throttle||o.condition?_(e,o)(t):e.subscribe(t):()=>{},[e,o]),c=(0,t.useCallback)(()=>{if(!e)return i;let t=e.getSnapshot();return n?n(t.value):t.value},[e,n,i]),l=(0,t.useRef)(),u=(0,t.useCallback)(()=>{let e=c();return a&&l.current!==void 0&&a(l.current,e)?l.current:(l.current=e,e)},[c,a]),d=(0,t.useCallback)(()=>i,[i]);return(0,t.useSyncExternalStore)(s,a?u:c,d)}const y={reference:(e,t)=>Object.is(e,t),shallow:(e,t)=>{if(Object.is(e,t))return!0;if(typeof e!=`object`||!e||typeof t!=`object`||!t)return!1;let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(!Object.prototype.hasOwnProperty.call(t,r)||!Object.is(e[r],t[r]))return!1;return!0},deep:(e,t)=>{if(Object.is(e,t))return!0;if(typeof e!=`object`||!e||typeof t!=`object`||!t||Array.isArray(e)!==Array.isArray(t))return!1;let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(!Object.prototype.hasOwnProperty.call(t,r)||!y.deep(e[r],t[r]))return!1;return!0},smart:(e,t)=>Object.is(e,t)?!0:typeof e!=`object`||!e||typeof t!=`object`||!t?!1:Array.isArray(e)&&Array.isArray(t)?e.length===t.length?e.every((e,n)=>{let r=t[n];return typeof e==`object`&&e&&typeof r==`object`&&r?y.shallow(e,r):Object.is(e,r)}):!1:y.shallow(e,t)},b=y.smart,x=y.shallow,S=y.deep,C=y.smart;function w(e,n,r=b){let i=(0,t.useCallback)(n,[n]),a=(0,t.useCallback)(r,[r]);(0,t.useRef)(!1);let o=(0,t.useRef)(),s=(0,t.useCallback)(t=>e.subscribe(t),[e]),c=(0,t.useCallback)(()=>{try{let t=e.getValue(),n=i(t);return o.current!==void 0&&a(o.current,n)?o.current:(o.current=n,n)}catch(e){throw e}},[e,i,a]);return(0,t.useSyncExternalStore)(s,c,c)}var T=class extends t.Component{constructor(e){super(e),this.resetTimeoutId=null,this.resetErrorBoundary=()=>{this.resetTimeoutId&&clearTimeout(this.resetTimeoutId),this.setState({hasError:!1,error:null,errorInfo:null,errorId:null})},this.state={hasError:!1,error:null,errorInfo:null,errorId:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e instanceof Error&&e.name===`ContextActionError`?e:null,errorId:`error_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}}componentDidCatch(t,n){if(t.name===`ContextActionError`){let e=t;this.setState({errorInfo:n}),this.props.onError?.(e,n)}else{let r=e.ErrorHandlers.store(`Unhandled error in Store component: ${t.message}`,{component:`StoreErrorBoundary`,stack:t.stack,componentStack:n.componentStack},t);this.setState({error:r,errorInfo:n}),this.props.onError?.(r,n)}}componentDidUpdate(e){let{hasError:t}=this.state,{resetOnPropsChange:n,resetKeys:r}=this.props;t&&n&&(r?r.some(t=>{let n=e[t],r=this.props[t];return n!==r})&&this.resetErrorBoundary():e!==this.props&&this.resetErrorBoundary())}componentWillUnmount(){this.resetTimeoutId&&clearTimeout(this.resetTimeoutId)}render(){let{hasError:e,error:t,errorInfo:n}=this.state,{children:r,fallback:i}=this.props;return e?i?typeof i==`function`?i(t,n):i:this.renderDefaultFallback():r}renderDefaultFallback(){return this.renderProductionFallback()}renderDevelopmentFallback(){let{error:t,errorInfo:r,errorId:i}=this.state,a=e.getErrorStatistics();return(0,n.jsxs)(`div`,{style:{padding:`20px`,margin:`20px`,border:`2px solid #ff6b6b`,borderRadius:`8px`,backgroundColor:`#ffe0e0`,fontFamily:`monospace`},children:[(0,n.jsx)(`h2`,{style:{color:`#d63031`,margin:`0 0 10px 0`},children:`🚨 Store Error Boundary`}),(0,n.jsxs)(`div`,{style:{marginBottom:`15px`},children:[(0,n.jsx)(`strong`,{children:`Error ID:`}),` `,i]}),t&&(0,n.jsxs)(`div`,{style:{marginBottom:`15px`},children:[(0,n.jsx)(`strong`,{children:`Error Type:`}),` `,t.type,(0,n.jsx)(`br`,{}),(0,n.jsx)(`strong`,{children:`Message:`}),` `,t.message,(0,n.jsx)(`br`,{}),(0,n.jsx)(`strong`,{children:`Timestamp:`}),` `,new Date(t.timestamp).toISOString()]}),t?.context&&(0,n.jsxs)(`div`,{style:{marginBottom:`15px`},children:[(0,n.jsx)(`strong`,{children:`Context:`}),(0,n.jsx)(`pre`,{style:{background:`#f8f9fa`,padding:`10px`,borderRadius:`4px`,overflow:`auto`,fontSize:`12px`},children:JSON.stringify(t.context,null,2)})]}),(0,n.jsxs)(`div`,{style:{marginBottom:`15px`},children:[(0,n.jsx)(`strong`,{children:`Error Statistics:`}),(0,n.jsx)(`br`,{}),`Total Errors: `,a.totalErrors,(0,n.jsx)(`br`,{}),`Recent Errors: `,a.recentErrors.length]}),r&&(0,n.jsxs)(`details`,{style:{marginBottom:`15px`},children:[(0,n.jsx)(`summary`,{style:{cursor:`pointer`,fontWeight:`bold`},children:`Component Stack`}),(0,n.jsx)(`pre`,{style:{background:`#f8f9fa`,padding:`10px`,borderRadius:`4px`,overflow:`auto`,fontSize:`11px`,whiteSpace:`pre-wrap`},children:r.componentStack})]}),(0,n.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(0,n.jsxs)(`div`,{style:{padding:`20px`,textAlign:`center`,backgroundColor:`#f8f9fa`,border:`1px solid #dee2e6`,borderRadius:`8px`,margin:`20px 0`},children:[(0,n.jsx)(`h3`,{style:{color:`#6c757d`,margin:`0 0 10px 0`},children:`Something went wrong`}),(0,n.jsx)(`p`,{style:{color:`#6c757d`,margin:`0 0 15px 0`},children:`We're sorry, but something unexpected happened. Please try again.`}),(0,n.jsx)(`button`,{onClick:this.resetErrorBoundary,style:{padding:`8px 16px`,backgroundColor:`#007bff`,color:`white`,border:`none`,borderRadius:`4px`,cursor:`pointer`},children:`Try Again`})]})}};function E(e,t){let r=r=>(0,n.jsx)(T,{...t,children:(0,n.jsx)(e,{...r})});return r.displayName=`withStoreErrorBoundary(${e.displayName||e.name})`,r}function D(e,t){return({children:r})=>(0,n.jsx)(T,{fallback:t,onError:(t,n)=>{console.group(`Store Error in ${e}`),console.error(`Error:`,t),console.error(`Component Stack:`,n.componentStack),console.groupEnd()},resetKeys:[e],children:r})}function O(e,t){let n=e instanceof Error?e:Error(String(e));return{handlerId:t.id,error:n,timestamp:Date.now(),severity:t.config.blocking?`blocking`:`non-blocking`}}async function k(e,t){let n=0,r=[],i=[];for(;n<e.handlers.length&&!(e.aborted||e.terminated);){let a=e.handlers[n];if(!a)continue;e.currentIndex=n;let o=t(a,n);try{if(e.aborted)break;if(a.config.condition)try{if(!a.config.condition(e.payload)){n++;continue}}catch{n++;continue}let t=a.handler(e.payload,o);if(a.config.blocking){let n=t instanceof Promise?await t:t;n!==void 0&&!e.terminated&&e.results.push(n)}else if(t instanceof Promise){let n=t.then(t=>(t!==void 0&&!e.terminated&&e.results.push(t),t)).catch(e=>{let t=O(e,a);i.push({handlerId:t.handlerId,error:t.error,timestamp:t.timestamp,severity:`non-blocking`})});r.push(n)}else t!==void 0&&!e.terminated&&e.results.push(t);if(e.terminated)break;if(e.jumpToPriority!==void 0){if(e.jumpCount=(e.jumpCount||0)+1,e.jumpCount>(e.maxJumps||10)){console.error(`[ActionRegister] ERROR: Maximum jump limit (${e.maxJumps||10}) exceeded. Aborting to prevent infinite loop. Check your jumpToPriority logic and conditions.`),e.aborted=!0,e.abortReason=`Maximum jump limit exceeded (${e.jumpCount} jumps)`,e.jumpToPriority=void 0;break}let t=e.handlers.findIndex(t=>(t.config.priority||0)<=e.jumpToPriority);if(t!==-1&&t!==n){if(t<n){let n=e.handlers[t];n&&!n.config.condition&&console.warn(`[ActionRegister] WARNING: Backward jumpToPriority to handler '${n.config.id||`unnamed`}' without condition. This may cause infinite loops! Consider adding a condition to prevent re-execution. Jump count: ${e.jumpCount}/${e.maxJumps||10}`)}n=t,e.jumpToPriority=void 0;continue}else e.jumpToPriority=void 0,n++}else n++}catch(e){let t=O(e,a);if(i.push(t),a.config.blocking)throw t.error;n++}}r.length>0&&await Promise.allSettled(r),i.length>0&&(e.collectedErrors=i.map(e=>({handlerId:e.handlerId,error:e.error,timestamp:e.timestamp,severity:`non-blocking`})))}async function A(e,t){let n=e.handlers,r=n.map(async(n,r)=>{let i=t(n,r);try{if(n.config.condition)try{if(!n.config.condition(e.payload))return{success:!0,handlerId:n.id,result:void 0,terminated:!1,skipped:!0}}catch{return{success:!0,handlerId:n.id,result:void 0,terminated:!1,skipped:!0}}let t=n.handler(e.payload,i),r;return r=t instanceof Promise?await t:t,r!==void 0&&!e.terminated&&e.results.push(r),{success:!0,handlerId:n.id,result:r,terminated:e.terminated}}catch(e){let t=O(e,n);if(t.severity===`blocking`)throw t.error;return{success:!1,handlerId:n.id,error:t.error}}}),i=await Promise.allSettled(r),a=i.filter((e,t)=>e.status===`rejected`?n[t]?.config.blocking??!1:!1);if(a.length>0)throw a[0].reason;let o=i.filter(e=>e.status===`fulfilled`&&e.value.terminated);o.length>0&&(e.terminated=!0,e.terminationResult=o[0].value.result)}async function j(e,t){let n=e.handlers;if(n.length===0)return;let r=n.map(async(n,r)=>{let i=t(n,r);try{if(n.config.condition)try{if(!n.config.condition(e.payload))return{success:!0,handlerId:n.id,registration:n,result:void 0,terminated:!1,skipped:!0}}catch{return{success:!0,handlerId:n.id,registration:n,result:void 0,terminated:!1,skipped:!0}}let t=n.handler(e.payload,i),r;return r=t instanceof Promise?await t:t,{success:!0,handlerId:n.id,registration:n,result:r,terminated:e.terminated}}catch(e){let t=O(e,n);return{success:!1,handlerId:n.id,error:t.error,registration:n}}}),i=await Promise.race(r);if(!i.success&&i.registration?.config.blocking)throw i.error;i.success&&i.result!==void 0&&e.results.push(i.result),i.success&&i.terminated&&(e.terminated=!0,e.terminationResult=i.result)}var M=class{constructor(e=!0){this.guards=new Map,this.maxIdleTime=6e4,this.cleanupIntervalMs=3e4,e&&this.startAutoCleanup()}startAutoCleanup(){this.cleanupInterval=setInterval(()=>{let e=Date.now(),t=[];this.guards.forEach((n,r)=>{let i=e-n.lastExecuted>this.maxIdleTime,a=n.debounceTimer||n.throttleTimer;i&&!a&&t.push(r)}),t.length>0&&(t.forEach(e=>this.guards.delete(e)),typeof process<`u`&&process.env?.DEBUG_CONTEXT_ACTION&&console.debug(`[ActionGuard] Cleaned up ${t.length} idle guards`))},this.cleanupIntervalMs)}async debounce(e,t){let n=this.guards.get(e);return n||(n={lastExecuted:0,isThrottled:!1,debounceTimer:void 0,throttleTimer:void 0,debouncePromise:void 0,debounceResolve:void 0},this.guards.set(e,n)),n.debounceTimer&&(clearTimeout(n.debounceTimer),n.debounceResolve&&=(n.debounceResolve(!1),void 0)),new Promise(e=>{n.debounceResolve=e,n.debounceTimer=setTimeout(()=>{n.debounceTimer=void 0,n.debounceResolve=void 0,n.lastExecuted=Date.now(),e(!0)},t)})}throttle(e,t){let n=this.guards.get(e);n||(n={lastExecuted:0,isThrottled:!1,debounceTimer:void 0,throttleTimer:void 0,debouncePromise:void 0,debounceResolve:void 0},this.guards.set(e,n));let r=Date.now(),i=r-n.lastExecuted;if(i>=t)return n.lastExecuted=r,n.isThrottled=!1,!0;if(n.isThrottled)return!1;n.isThrottled=!0;let a=t-i;return n.throttleTimer=setTimeout(()=>{n.isThrottled=!1,n.throttleTimer=void 0},a),!1}clearGuards(e){let t=this.guards.get(e);t&&(t.debounceTimer&&=(clearTimeout(t.debounceTimer),t.debounceResolve&&=(t.debounceResolve(!1),void 0),void 0),t.throttleTimer&&=(clearTimeout(t.throttleTimer),void 0),this.guards.delete(e))}clearAll(){this.guards.forEach(e=>{e.debounceTimer&&(clearTimeout(e.debounceTimer),e.debounceResolve&&e.debounceResolve(!1)),e.throttleTimer&&clearTimeout(e.throttleTimer)}),this.guards.clear()}getGuardState(e){return this.guards.get(e)}getAllGuardStates(){return new Map(this.guards)}destroy(){this.cleanupInterval&&=(clearInterval(this.cleanupInterval),void 0),this.clearAll()}getStats(){let e=0;return this.guards.forEach(t=>{(t.debounceTimer||t.throttleTimer)&&e++}),{activeGuards:this.guards.size,withTimers:e}}},N=class{constructor(e=`OperationQueue`,t=1){this.name=e,this.queue=[],this.processingPromise=null,this.operationCounter=0,this.activeOperations=0,this.pendingResolvers=[],this.maxConcurrency=Math.max(1,t)}enqueue(e,t=0){return new Promise((n,r)=>{let i={id:`${this.name}-${++this.operationCounter}`,operation:e,resolve:n,reject:r,priority:t,timestamp:Date.now()},a=this.queue.length;for(let e=0;e<this.queue.length;e++){let n=this.queue[e];if(n&&(n.priority||0)<t){a=e;break}}this.queue.splice(a,0,i),this.processingPromise&&this.notifyNewOperation(),this.processQueue()})}async processQueue(){if(this.processingPromise)return this.processingPromise;this.processingPromise=this._doProcess();try{await this.processingPromise}finally{this.processingPromise=null}}async _doProcess(){for(;this.queue.length>0||this.activeOperations>0;){for(;this.queue.length>0&&this.activeOperations<this.maxConcurrency;){let e=this.queue.shift();this.startOperation(e)}this.activeOperations>0&&await this.waitForAnyOperation()}}startOperation(e){this.activeOperations++,this.executeOperation(e).finally(()=>{this.activeOperations--,this.notifyOperationComplete()})}waitForAnyOperation(){return new Promise(e=>{this.pendingResolvers.push(e)})}notifyOperationComplete(){this.pendingResolvers.splice(0).forEach(e=>e())}notifyNewOperation(){this.notifyOperationComplete()}async executeOperation(e){try{let t=await Promise.resolve(e.operation());e.resolve(t)}catch(t){e.reject(t)}}getQueueInfo(){return{name:this.name,queueLength:this.queue.length,isProcessing:!!this.processingPromise,activeOperations:this.activeOperations,maxConcurrency:this.maxConcurrency,operations:this.queue.map(e=>({id:e.id,priority:e.priority,timestamp:e.timestamp}))}}getConcurrencyInfo(){return{maxConcurrency:this.maxConcurrency,activeOperations:this.activeOperations,availableSlots:this.maxConcurrency-this.activeOperations,queuedOperations:this.queue.length,efficiency:this.activeOperations/this.maxConcurrency}}clear(){this.queue.forEach(e=>{e.reject(Error(`Queue cleared`))}),this.queue=[],this.processingPromise=null,this.pendingResolvers.splice(0).forEach(e=>e())}get size(){return this.queue.length}get processing(){return!!this.processingPromise}},P=class{constructor(e={}){this.pipelines=new Map,this.executionMode=`sequential`,this.actionExecutionModes=new Map,this.unregisterFunctions=new Map,this.lastRegisteredTimestamps=new Map,this.filterCacheDisabled=!0,this.handlerIdCounter=0,this.controllerPool=[],this.maxControllerPoolSize=10,this.name=e.name||`ActionRegister`,this.registryConfig=e.registry,this.maxHandlersPerAction=e.registry?.maxHandlersPerAction??1e3,this.isDebugMode=!!this.registryConfig?.debug,this.actionGuard=new M(this.registryConfig?.autoCleanup!==!1),e.registry?.useConcurrencyQueue!==!1&&(this.dispatchQueue=new N(`${this.name}-Dispatch`)),this.registryConfig?.defaultExecutionMode&&(this.executionMode=this.registryConfig.defaultExecutionMode),this.log(`ActionRegister initialized`,{defaultExecutionMode:this.executionMode,autoCleanup:this.registryConfig?.autoCleanup!==!1,concurrencyQueue:!!this.dispatchQueue,debugMode:this.isDebugMode})}register(e,t,n={}){let r=n.id||this.generateHandlerId(e);return this._performRegistrationSync(e,t,n,r)}log(e,t,n=`log`){if(this.isDebugMode){let r=new Date().toISOString();console[n](`🎯 [${r}] [${this.name}] ${e}`,t||``)}}generateHandlerId(e){return`${String(e)}_${this.name}_${++this.handlerIdCounter}`}createAbortSignal(e){let t=[],n=[],r;if(e?.signal&&t.push(e.signal),e?.autoAbort?.enabled&&(r=new AbortController,t.push(r.signal)),t.length===0)return[void 0,r,()=>{}];if(t.length===1)return[t[0],r,()=>n.forEach(e=>e())];let i;if(typeof AbortSignal.any==`function`)i=AbortSignal.any(t);else{let e=new AbortController;i=e.signal,t.forEach(t=>{if(t.aborted)e.abort();else{let r=()=>e.abort();t.addEventListener(`abort`,r,{once:!0}),n.push(()=>t.removeEventListener(`abort`,r))}})}return[i,r,()=>{n.forEach(e=>{try{e()}catch(e){this.log(`Cleanup error during AbortSignal cleanup`,e,`warn`)}})}]}_performRegistrationSync(e,t,n,r){let i={handler:t,config:{priority:n.priority??0,id:r,blocking:n.blocking??!1,once:n.once??!1,debounce:n.debounce??void 0,throttle:n.throttle??void 0,replaceExisting:n.replaceExisting??!0,cleanup:n.cleanup,condition:n.condition},id:r};this.pipelines.has(e)||this.pipelines.set(e,[]);let a=this.pipelines.get(e);if(a.length>=this.maxHandlersPerAction)return console.warn(`Handler limit (${this.maxHandlersPerAction}) reached for action "${String(e)}". Registration ignored.`),()=>{};let o=a.findIndex(e=>e.id===r);if(o!==-1){let t=a[o],s=this.unregisterFunctions.get(r);if(i.config.replaceExisting){if(t&&t.config.cleanup&&typeof t.config.cleanup==`function`)try{t.config.cleanup()}catch(t){this.log(`Cleanup error for replaced handler: ${String(e)}`,t,`warn`)}s&&this.unregisterFunctions.delete(r),a[o]=i,a.sort((e,t)=>t.config.priority-e.config.priority),this.lastRegisteredTimestamps.set(e,new Date);let c=this.createUnregisterFunction(e,r,i);return this.unregisterFunctions.set(r,c),this.log(`Handler replaced: ${String(e)}`,{handlerId:r,priority:n.priority,totalHandlers:a.length,hadExistingUnregister:!!s}),c}else{if(!t)throw Error(`Internal error: existing handler should be defined in duplicate handler block`);if(this.log(`Handler duplicate ignored, returning existing unregister: ${String(e)}`,{handlerId:r,existingPriority:t.config.priority,newPriority:n.priority,existingBlocking:t.config.blocking,newBlocking:n.blocking,note:`Use replaceExisting:true to replace`},`warn`),s)return s;{let n=this.createUnregisterFunction(e,r,t);return this.unregisterFunctions.set(r,n),n}}}a.push(i),a.sort((e,t)=>t.config.priority-e.config.priority),this.lastRegisteredTimestamps.set(e,new Date);let s=this.createUnregisterFunction(e,r,i);return this.unregisterFunctions.set(r,s),this.log(`Handler registered: ${String(e)}`,{handlerId:r,priority:n.priority,totalHandlers:a.length}),s}async dispatch(e,t,n){return n?.immediate||!this.dispatchQueue?this._performDispatch(e,t,n):this.dispatchQueue.enqueue(async()=>this._performDispatch(e,t,n))}async _performDispatch(e,t,n){this.log(`Starting dispatch for action '${String(e)}'`,{hasPayload:t!==void 0,payloadType:t?.constructor?.name||typeof t,options:n?Object.keys(n):`none`,timestamp:new Date().toISOString()}),t instanceof Event&&console.warn(`Event object passed to action "${String(e)}"`,t.type);let[r,i,a]=this.createAbortSignal(n);if(n?.autoAbort?.onControllerCreated&&i&&n.autoAbort.onControllerCreated(i),r?.aborted){this.log(`Dispatch aborted before execution for '${String(e)}'`);return}let o=this.pipelines.get(e);if(this.log(`Pipeline lookup for '${String(e)}'`,{pipelineExists:!!o,handlersCount:o?.length||0,allRegisteredActions:Array.from(this.pipelines.keys()),pipelineMap:Object.fromEntries(Array.from(this.pipelines.entries()).map(([e,t])=>[e,t.length]))}),!o||o.length===0){this.log(`No handlers found for action '${String(e)}', dispatch cancelled`,{},`warn`);return}let s=n?.filter?this.filterHandlers(o,n.filter):o,c=String(e),l,u;if(n?.throttle!==void 0)l=n.throttle;else if(s.length>0){for(let e of s)if(e.config.throttle!==void 0){l=e.config.throttle;break}}if(n?.debounce!==void 0)u=n.debounce;else if(s.length>0){for(let e of s)if(e.config.debounce!==void 0){u=e.config.debounce;break}}if(u!==void 0&&!await this.actionGuard.debounce(c,u)||l!==void 0&&!this.actionGuard.throttle(c,l))return;let d=n?.executionMode||this.actionExecutionModes.get(e)||this.executionMode,f={action:String(e),payload:t,handlers:s,aborted:!1,abortReason:void 0,currentIndex:0,jumpToPriority:void 0,jumpCount:0,maxJumps:10,executionMode:d,results:[],terminated:!1,terminationResult:void 0},p=r?()=>{f.aborted=!0,f.abortReason=`Action dispatch aborted by signal`}:void 0;r&&p&&r.addEventListener(`abort`,p);try{await this.executePipeline(f,i,n?.autoAbort),this.log(`Pipeline execution succeeded for ${String(e)}`)}catch(t){throw this.log(`Pipeline execution failed for ${String(e)}`,t,`error`),t}finally{a()}}async dispatchWithResult(e,t,n){let r=Date.now(),[i,a,o]=this.createAbortSignal(n);if(n?.autoAbort?.onControllerCreated&&a&&n.autoAbort.onControllerCreated(a),i?.aborted)return{success:!1,aborted:!0,abortReason:`Action dispatch aborted by signal`,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:0,handlersExecuted:0,handlersSkipped:0,handlersFailed:0,startTime:r,endTime:r},handlers:[],errors:[]};let s=this.pipelines.get(e);if(!s||s.length===0)return{success:!0,aborted:!1,abortReason:void 0,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:0,handlersExecuted:0,handlersSkipped:0,handlersFailed:0,startTime:r,endTime:r},handlers:[],errors:[]};let c=n?.filter?this.filterHandlers(s,n.filter):s,l=String(e),u=await this.applyActionGuardControlsWithResult(l,c,n,r,s.length);if(u)return u;let d=n?.executionMode||this.actionExecutionModes.get(e)||this.executionMode,f={action:String(e),payload:t,handlers:c,aborted:!1,abortReason:void 0,currentIndex:0,jumpToPriority:void 0,jumpCount:0,maxJumps:10,executionMode:d,results:[],terminated:!1,terminationResult:void 0},p,m=[];c.forEach(e=>{m.push({id:e.config.id,executed:!1,duration:void 0,result:void 0,error:void 0,metadata:void 0})});let h=i?()=>{f.aborted=!0,f.abortReason=`Action dispatch aborted by signal`}:void 0;i&&h&&i.addEventListener(`abort`,h);let g=[];try{await this.executePipeline(f,a,n?.autoAbort),g=f.collectedErrors||[];let e=Math.min(f.currentIndex+(f.aborted?0:1),c.length);for(let t=0;t<e;t++){let e=c[t];if(!e)continue;let n=m.find(t=>t.id===e.config.id);n&&(n.executed=!0)}}catch(e){g=f.collectedErrors||[],p=e instanceof Error?e:Error(String(e)),g.push({handlerId:`pipeline`,error:p,timestamp:Date.now(),severity:`blocking`});let t=Math.min(f.currentIndex+1,c.length);for(let e=0;e<t;e++){let t=c[e];if(!t)continue;let n=m.find(e=>e.id===t.config.id);n&&(n.executed=!0)}}finally{o()}let _=Date.now(),v=this.processResults(f,n?.result),y=f.results.filter(e=>e!==void 0),b=g.map(e=>({handlerId:e.handlerId,error:e.error,expectedType:typeof v})),x={success:!p&&!f.aborted,aborted:f.aborted,abortReason:f.abortReason,terminated:f.terminated,result:v,successResults:y,results:f.results,failedResults:b,execution:{duration:_-r,handlersExecuted:c.length===0?0:f.currentIndex+(f.aborted?0:1),handlersSkipped:Math.max(0,c.length-(f.currentIndex+1)),handlersFailed:g.length,startTime:r,endTime:_},handlers:m,errors:g.map(e=>({handlerId:e.handlerId,error:e.error,timestamp:e.timestamp,severity:`non-blocking`}))};return this.cleanupOneTimeHandlers(e,f.handlers),x}async applyActionGuardControlsWithResult(e,t,n,r,i){let a,o;if(n?.throttle!==void 0)a=n.throttle;else if(t.length>0){for(let e of t)if(e.config.throttle!==void 0){a=e.config.throttle;break}}if(n?.debounce!==void 0)o=n.debounce;else if(t.length>0){for(let e of t)if(e.config.debounce!==void 0){o=e.config.debounce;break}}return o!==void 0&&!await this.actionGuard.debounce(e,o)?{success:!1,aborted:!0,abortReason:`Debounced execution`,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:Date.now()-r,handlersExecuted:0,handlersSkipped:i,handlersFailed:0,startTime:r,endTime:Date.now()},handlers:[],errors:[]}:a!==void 0&&!this.actionGuard.throttle(e,a)?{success:!1,aborted:!0,abortReason:`Throttled execution`,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:Date.now()-r,handlersExecuted:0,handlersSkipped:i,handlersFailed:0,startTime:r,endTime:Date.now()},handlers:[],errors:[]}:null}generateFilterCacheKey(e){if(!e)return`no-filter`;let t=[];if(e.handlerIds?.length&&t.push(`h:${e.handlerIds.slice().sort().join(`,`)}`),e.excludeHandlerIds?.length&&t.push(`e:${e.excludeHandlerIds.slice().sort().join(`,`)}`),e.priority){let{min:n,max:r}=e.priority;(n!==void 0||r!==void 0)&&t.push(`p:${n??`*`}-${r??`*`}`)}return e.custom?`custom-`+Date.now()+Math.random():t.length>0?t.join(`|`):`no-filter`}getControllerFromPool(e,t,n){let r=this.controllerPool.pop();return r||={},r.abort=r=>{e.aborted=!0,e.abortReason=r,t&&n?.allowHandlerAbort&&t.abort(r)},r.modifyPayload=t=>{try{e.payload=t(e.payload)}catch(e){this.log(`Payload modification error`,e,`warn`)}},r.getPayload=()=>e.payload,r.jumpToPriority=t=>{e.jumpToPriority=t},r.return=t=>{e.terminated=!0,e.terminationResult=t},r.setResult=t=>{e.results.push(t)},r.getResults=()=>[...e.results],r.mergeResult=t=>{let n=e.results[e.results.length-1],r=e.results.slice(0,-1),i=t(r,n);e.results[e.results.length-1]=i},r}returnControllerToPool(e){this.controllerPool.length<this.maxControllerPoolSize&&this.controllerPool.push(e)}filterHandlers(e,t){if(!t)return e;let n=t.handlerIds?new Set(t.handlerIds):null,r=t.excludeHandlerIds?new Set(t.excludeHandlerIds):null;return e.filter(e=>{let i=e.config;if(n&&!n.has(i.id)||r&&r.has(i.id))return!1;if(t.priority){let e=i.priority;if(t.priority.min!==void 0&&e<t.priority.min||t.priority.max!==void 0&&e>t.priority.max)return!1}return!(t.custom&&!t.custom(i))})}processResults(e,t){let n=e.results;if(e.terminated&&e.terminationResult!==void 0)return e.terminationResult;if(!t)return n.length>0?n[n.length-1]:void 0;if(!t.collect&&!t.strategy)return;let r=t.maxResults?n.slice(0,t.maxResults):n;if(r.length!==0)switch(t.strategy){case`first`:return r[0];case`last`:return r[r.length-1];case`all`:return r;case`merge`:return t.merger?t.merger(r):r[r.length-1];case`custom`:if(t.merger)return t.merger(r);throw Error(`Custom result strategy requires a merger function`);default:return t.collect?r:r[r.length-1]}}async executePipeline(e,t,n){let r=(r,i)=>this.getControllerFromPool(e,t,n);switch(e.executionMode){case`sequential`:await k(e,r);break;case`parallel`:await A(e,r);break;case`race`:await j(e,r);break;default:throw Error(`Unknown execution mode: ${e.executionMode}`)}this.cleanupOneTimeHandlers(e.action,e.handlers)}cleanupOneTimeHandlers(e,t){let n=this.pipelines.get(e);if(!n)return;let r=t.filter(e=>e.config.once);r.length!==0&&(r.forEach(t=>{let r=n.findIndex(e=>e.id===t.id);r!==-1&&(n.splice(r,1),this.registryConfig?.debug&&console.log(`🎯 One-time handler removed: ${String(e)}`,{handlerId:t.id,remainingHandlers:n.length,registry:this.name}))}),n.length===0&&(this.pipelines.delete(e),this.lastRegisteredTimestamps.delete(e)))}getHandlerCount(e){let t=this.pipelines.get(e);return t?t.length:0}hasHandlers(e){return this.getHandlerCount(e)>0}getRegisteredActions(){return Array.from(this.pipelines.keys())}clearAction(e){this.pipelines.delete(e),this.lastRegisteredTimestamps.delete(e)}clearAll(){this.pipelines.clear(),this.lastRegisteredTimestamps.clear()}getName(){return this.name}getRegistryInfo(){let e=Array.from(this.pipelines.values()).reduce((e,t)=>e+t.length,0);return{name:this.name,totalActions:this.pipelines.size,totalHandlers:e,registeredActions:Array.from(this.pipelines.keys()),actionExecutionModes:new Map(this.actionExecutionModes),defaultExecutionMode:this.executionMode}}getActionStats(e){let t=this.pipelines.get(e);if(!t)return null;let n=new Map;t.forEach(e=>{n.has(e.config.priority)||n.set(e.config.priority,[]),n.get(e.config.priority).push(e)});let r=Array.from(n.entries()).sort(([e],[t])=>t-e).map(([e,t])=>({priority:e,handlers:t.map(e=>({id:e.config.id}))}));return{action:e,handlerCount:t.length,totalHandlers:t.length,handlersByPriority:r,executionStats:void 0,lastRegistered:this.lastRegisteredTimestamps.get(e)}}getAllActionStats(){return Array.from(this.pipelines.keys()).map(e=>this.getActionStats(e)).filter(e=>e!==null)}setExecutionMode(e){this.executionMode=e,this.registryConfig?.debug&&console.log(`🎯 Global execution mode set to: ${e}`)}setActionExecutionMode(e,t){this.actionExecutionModes.set(e,t),this.registryConfig?.debug&&console.log(`🎯 Execution mode set for action '${String(e)}': ${t}`)}getActionExecutionMode(e){return this.actionExecutionModes.get(e)||this.executionMode}removeActionExecutionMode(e){this.actionExecutionModes.delete(e),this.registryConfig?.debug&&console.log(`🎯 Execution mode reset for action '${String(e)}' to default: ${this.executionMode}`)}getRegistryConfig(){return this.registryConfig}isDebugEnabled(){return this.isDebugMode}createUnregisterFunction(e,t,n){return()=>{let r=this.pipelines.get(e);if(!r)return;let i=r.findIndex(e=>e.id===t&&e===n);if(i!==-1){if(r.splice(i,1),this.unregisterFunctions.delete(t),r.length===0&&(this.pipelines.delete(e),this.lastRegisteredTimestamps.delete(e)),n.config.cleanup&&typeof n.config.cleanup==`function`)try{n.config.cleanup()}catch(t){this.log(`Cleanup error during unregister: ${String(e)}`,t,`warn`)}this.log(`Handler unregistered: ${String(e)}`,{handlerId:t,remainingHandlers:r.length,actionRemoved:r.length===0})}}}getUnregisterFunctionCount(){return this.unregisterFunctions.size}hasUnregisterFunction(e){return this.unregisterFunctions.has(e)}destroy(){this.unregisterFunctions.clear();for(let[e,t]of this.pipelines.entries())for(let n of t)if(n.config.cleanup&&typeof n.config.cleanup==`function`)try{n.config.cleanup()}catch(t){this.log(`Cleanup error for handler during destroy: ${String(e)}`,t,`warn`)}this.pipelines.clear(),this.lastRegisteredTimestamps.clear(),this.actionGuard.destroy(),this.dispatchQueue?.clear?.(),this.actionExecutionModes.clear(),this.controllerPool.length=0,this.log(`ActionRegister destroyed`)}};function F(e={},r){let i,a;typeof e==`string`?(a=e,i={...r,name:r?.name||a}):(i=e,a=i.name||`ActionContext`);let o=(0,t.createContext)(null),s=({children:e})=>{let r=(0,t.useRef)(new P(i)),a=(0,t.useMemo)(()=>({actionRegisterRef:r}),[]);return(0,n.jsx)(o.Provider,{value:a,children:e})},c=()=>{let e=(0,t.useContext)(o);if(!e)throw Error(`useFactoryActionContext must be used within a factory ActionContext Provider`);return e},l=()=>{let{actionRegisterRef:e}=c(),n=(0,t.useCallback)((t,n,r)=>{let i=e.current;if(!i)throw Error(`ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up.`);let a={...r,...r?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0}}};return i.dispatch(t,n,a)},[e]),r=(0,t.useCallback)((t,n,r)=>{let i=e.current;if(!i)throw Error(`ActionRegister not initialized`);let a={...r,...r?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0}}};return i.dispatchWithResult(t,n,a)},[e]);return{dispatch:n,dispatchWithResult:r}};return{Provider:s,useActionContext:c,useActionDispatch:()=>{let{dispatch:e}=l();return e},useActionHandler:(e,n,r)=>{let{actionRegisterRef:i}=c(),a=(0,t.useId)(),o=(0,t.useRef)(n);o.current=n;let s=r?.priority??0,l=r?.id||`react_${String(e)}_${a}`,u=r?.blocking??!1,d=r?.once??!1,f=r?.debounce,p=r?.throttle,m=(0,t.useMemo)(()=>({priority:s,id:l,blocking:u,once:d,replaceExisting:!0,...f!==void 0&&{debounce:f},...p!==void 0&&{throttle:p}}),[s,l,u,d,f,p]);(0,t.useEffect)(()=>{let t=i.current;return t?t.register(e,(e,t)=>o.current(e,t),m):void 0},[e,i,m])},useActionRegister:()=>c().actionRegisterRef.current,useActionDispatchWithResult:()=>{let e=c(),n=(0,t.useRef)(new Set),r=(0,t.useCallback)((t,r,i)=>{let a=e.actionRegisterRef.current;if(!a)throw Error(`ActionRegister not initialized`);let o={...i,...i?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0,onControllerCreated:e=>{n.current.add(e)}}}};return a.dispatch(t,r,o)},[e.actionRegisterRef]),i=(0,t.useCallback)((t,r,i)=>{let a=e.actionRegisterRef.current;if(!a)throw Error(`ActionRegister not initialized`);let o={...i,...i?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0,onControllerCreated:e=>{n.current.add(e)}}}};return a.dispatchWithResult(t,r,o)},[e.actionRegisterRef]),a=(0,t.useCallback)(()=>{n.current.forEach(e=>{e.signal.aborted||e.abort()}),n.current.clear()},[]),o=(0,t.useCallback)(()=>{a()},[a]);return(0,t.useEffect)(()=>{let e=n;return()=>{e.current.forEach(e=>{e.signal.aborted||e.abort()}),e.current.clear()}},[]),{dispatch:r,dispatchWithResult:i,abortAll:a,resetAbortScope:o}},context:o}}Object.defineProperty(exports,`ActionRegister`,{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,`Store`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`StoreErrorBoundary`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`StoreRegistry`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`createActionContext`,{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,`createStore`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`createStoreErrorBoundary`,{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,`defaultEqualityFn`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`useSafeStoreSubscription`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`useStoreSelector`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`withStoreErrorBoundary`,{enumerable:!0,get:function(){return E}}); |
| import{ErrorHandlers as e,compareValues as t,getErrorStatistics as n,produce as r,safeGet as i,safeSet as a}from"./error-handling-CWVo5dVS.js";import o,{Component as s,createContext as c,useCallback as l,useContext as u,useEffect as d,useId as f,useMemo as p,useRef as m,useSyncExternalStore as h}from"react";import{jsx as g,jsxs as _}from"react/jsx-runtime";var v=class{constructor(e=`default`){this.stores=new Map,this.metadata=new WeakMap,this.listeners=new Set,this._snapshot=[],this.name=e}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}register(e,t,n){this.stores.has(e)&&this.stores.get(e),this.stores.set(e,t),n&&this.metadata.set(t,{registeredAt:Date.now(),name:e,...n}),this._updateSnapshot(),this._notifyListeners()}unregister(e){return this.stores.get(e)?(this.stores.delete(e),this._updateSnapshot(),this._notifyListeners(),!0):!1}getStore(e){return this.stores.get(e)}hasStore(e){return this.stores.has(e)}getStoreNames(){return Array.from(this.stores.keys())}getAllStores(){return new Map(this.stores)}getStoreMetadata(e){let t=typeof e==`string`?this.stores.get(e):e;return t?this.metadata.get(t):void 0}updateStoreMetadata(e,t){let n=typeof e==`string`?this.stores.get(e):e;if(!n)return!1;let r=this.metadata.get(n);return this.metadata.set(n,{registeredAt:Date.now(),name:typeof e==`string`?e:r?.name||`unknown`,...r,...t}),!0}getSnapshot(){return this._snapshot}clear(){this.stores.clear(),this._updateSnapshot(),this._notifyListeners()}dispose(){this.clear(),this.listeners.clear()}getStoreCount(){return this.stores.size}forEach(e){this.stores.forEach((t,n)=>{e(t,n)})}getStats(){return{totalStores:this.stores.size,storeNames:this.getStoreNames(),registryName:this.name}}_updateSnapshot(){this._snapshot=Array.from(this.stores.entries())}_notifyListeners(){this.listeners.forEach(e=>{try{e()}catch(e){console.error(`Error in registry listener:`,e)}})}};new v(`global`);function y(e){return typeof e==`object`&&!!e&&`target`in e&&`isReady`in e&&`isMounted`in e&&`mountPromise`in e&&typeof e.isReady==`boolean`&&typeof e.isMounted==`boolean`}function b(e){return e instanceof Event}function x(e){return typeof e==`object`&&!!e&&typeof e.preventDefault==`function`}function S(e){return typeof e==`object`&&!!e&&`target`in e}function C(e){return e instanceof Element}function w(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function T(e,t=!0){if(!w(e)||y(e))return!1;if(E(e))return!0;if(t){for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t)){let n=e[t];if(E(n))return!0}}return!1}function E(e){if(!w(e))return!1;let t=S(e),n=x(e),r=b(e),i=`type`in e&&typeof e.type==`string`&&(t||n),a=`nativeEvent`in e||`persist`in e||`$$typeof`in e||`_reactInternalFiber`in e||`_owner`in e,o=e?.constructor?.name,s=o?o.includes(`Event`)||o===`SyntheticEvent`||o.includes(`MouseEvent`)||o.includes(`KeyboardEvent`)||o.includes(`TouchEvent`)||o.includes(`FocusEvent`)||o.includes(`SubmitEvent`):!1;return r||i||a||s}function D(e){if(!w(e))return[];let t=[];for(let n in e)if(Object.prototype.hasOwnProperty.call(e,n)){let r=e[n];(C(r)||b(r)||w(r)&&S(r))&&t.push(n)}return t}const O={isRefState:y,isDOMEvent:b,isEventLike:x,hasTargetProperty:S,isDOMElement:C,isObject:w,isSuspiciousEventObject:T,findProblematicProperties:D};var k=class{constructor(e,t){this.listeners=new Set,this._lastClonedValue=null,this._lastClonedVersion=0,this._version=0,this.isUpdating=!1,this.updateQueue=[],this.notificationMode=`batched`,this.pendingNotification=!1,this.animationFrameId=null,this.pendingUpdatesCount=0,this.cleanupTasks=new Set,this.isDisposed=!1,this.errorCount=0,this.lastErrorTime=0,this.MAX_ERROR_COUNT=5,this.ERROR_RESET_TIME=6e4,this.subscriptionRegistry=new WeakMap,this.cloningEnabled=!0,this.subscribe=e=>{if(this.isDisposed)return console.warn(`Cannot subscribe to disposed store "${this.name}"`),()=>{};let t=()=>{if(!this.isDisposed)try{e(),this.errorCount>0&&(this.errorCount=0)}catch(t){this._handleListenerError(t,e)}};return this.subscriptionRegistry.set(e,{subscribedAt:Date.now(),errorCount:0,enhancedListener:t}),this.listeners.add(t),()=>{this.listeners.delete(t),this.subscriptionRegistry.delete(e)}},this.getSnapshot=()=>this._snapshot,this.name=e,this._value=t,this._snapshot=this._createSnapshot()}getValue(){return this.cloningEnabled?this._lastClonedVersion===this._version&&this._lastClonedValue!==null?this._lastClonedValue:(this._lastClonedValue=i(this._value,this.cloningEnabled),this._lastClonedVersion=this._version,this._lastClonedValue):this._value}setValue(t,n){if(O.isObject(t)&&!O.isRefState(t)&&O.isSuspiciousEventObject(t)){let r=n?.eventHandling||`block`,i=O.hasTargetProperty(t),a=O.isEventLike(t),o=O.isDOMEvent(t);switch(r){case`allow`:break;case`transform`:if(n?.eventTransform)try{t=n.eventTransform(t)}catch(n){e.store(`Event transformation failed in Store.setValue`,{storeName:this.name,valueType:typeof t,error:n instanceof Error?n.message:String(n)});return}else{e.store(`Event transformation requested but no transform function provided`,{storeName:this.name,valueType:typeof t});return}break;case`block`:default:e.store(`Event object detected in Store.setValue - this may cause memory leaks`,{storeName:this.name,valueType:typeof t,constructorName:t?.constructor?.name,isEvent:o,hasTargetProperty:i,hasPreventDefault:a,problematicProperties:O.findProblematicProperties(t)});return}}let r=n?.skipClone?t:a(t,this.cloningEnabled),i=!0;n?.skipComparison||(i=this._compareValues(this._value,r)),i&&(this._value=r,this._version++,this._snapshot=this._createSnapshot(),this._scheduleNotification())}update(t){if(this.isUpdating){this.updateQueue.push(()=>this.update(t));return}try{this.isUpdating=!0;let n;try{n=r(this._value,e=>{let n=t(e);return n===void 0?e:n})}catch{let e=i(this._value,this.cloningEnabled);try{n=r(e,e=>{let n=t(e);return n===void 0?e:n})}catch{n=t(e)}}if(O.isObject(n)&&!O.isRefState(n)&&O.isSuspiciousEventObject(n)){let t=O.hasTargetProperty(n),r=O.isEventLike(n),i=O.isDOMEvent(n);e.store(`Event object detected in Store.update result - this may cause memory leaks`,{storeName:this.name,updatedValueType:typeof n,constructorName:n?.constructor?.name,isEvent:i,hasTargetProperty:t,hasPreventDefault:r,problematicProperties:O.findProblematicProperties(n)});return}this.setValue(n)}finally{if(this.isUpdating=!1,this.updateQueue.length>0){let e=this.updateQueue.shift();e&&Promise.resolve().then(e)}}}getListenerCount(){return this.listeners.size}clearListeners(){this.listeners.clear()}registerCleanup(e){return this.isDisposed?(console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`),()=>{}):(this.cleanupTasks.add(e),()=>this.cleanupTasks.delete(e))}dispose(){if(!this.isDisposed){this.isDisposed=!0;try{this.cleanupTasks.forEach(t=>{try{t()}catch(t){e.store(`Error during cleanup task execution`,{storeName:this.name},t instanceof Error?t:void 0)}}),this.cleanupTasks.clear(),this.subscriptionRegistry=new WeakMap,this.clearListeners(),this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.pendingNotification=!1,this.updateQueue.length=0}catch(t){e.store(`Critical error during store disposal`,{storeName:this.name},t instanceof Error?t:void 0)}}}isStoreDisposed(){return this.isDisposed}setCustomComparator(e){this.customComparator=e}setComparisonOptions(e){this.comparisonOptions=e}setCloningEnabled(e){this.cloningEnabled=e}isCloningEnabled(){return this.cloningEnabled}_compareValues(n,r){let i;try{i=this.customComparator?!this.customComparator(n,r):this.comparisonOptions?!t(n,r,this.comparisonOptions):!t(n,r,{strategy:`reference`})}catch(t){e.store(`Error during value comparison, falling back to reference comparison`,{storeName:this.name},t instanceof Error?t:void 0),i=!Object.is(n,r)}return i}_createSnapshot(){return{value:i(this._value,this.cloningEnabled),name:this.name,lastUpdate:Date.now()}}_scheduleNotification(){this.notificationMode===`immediate`?this._notifyListeners():this._scheduleWithRAF()}_scheduleWithRAF(){this.pendingUpdatesCount++,this.pendingNotification||(this.pendingNotification=!0,this.animationFrameId=requestAnimationFrame(()=>{this._executeNotification()}))}_executeNotification(){this.pendingNotification=!1,this.animationFrameId=null,this.pendingUpdatesCount,this.pendingUpdatesCount=0,this._notifyListeners()}_handleListenerError(t,n){let r=Date.now();r-this.lastErrorTime>this.ERROR_RESET_TIME&&(this.errorCount=0),this.errorCount++,this.lastErrorTime=r;let i=this.subscriptionRegistry.get(n);i&&i.errorCount++,e.store(`Error in store listener execution`,{storeName:this.name,listenerCount:this.listeners.size,errorCount:this.errorCount,subscriptionAge:i?r-i.subscribedAt:`unknown`},t instanceof Error?t:void 0),i&&i.errorCount>=3&&(console.warn(`Removing problematic listener from store "${this.name}" after ${i.errorCount} errors`),this.listeners.delete(i.enhancedListener),this.subscriptionRegistry.delete(n)),this.errorCount>=this.MAX_ERROR_COUNT&&(console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`),this.clearListeners())}_notifyListeners(){this.isDisposed||this.listeners.forEach(e=>{this.isDisposed||e()})}};function A(e,t){return new k(e,t)}function j(e,t={}){let{debounce:n,throttle:r,condition:i,debug:a,name:o=`unknown`}=t;return t=>{if(!e)return()=>{};let s=null,c=null,l=0,u=e.subscribe(()=>{if(i&&!i()){a&&console.debug(`[${o}] Subscription suspended due to condition`);return}let e=performance.now();if(r&&r>0){if(e-l<r){c&&clearTimeout(c),c=setTimeout(()=>{l=performance.now(),t()},r-(e-l));return}l=e}if(n&&n>0){s&&clearTimeout(s),s=setTimeout(()=>{t(),a&&console.debug(`[${o}] Debounced callback executed after ${n}ms`)},n);return}t()});return()=>{s&&clearTimeout(s),c&&clearTimeout(c),u()}}}function M(e,t,n={}){let{initialValue:r,equalityFn:i,...a}=n,o=l(t=>e?a.debounce||a.throttle||a.condition?j(e,a)(t):e.subscribe(t):()=>{},[e,a]),s=l(()=>{if(!e)return r;let n=e.getSnapshot();return t?t(n.value):n.value},[e,t,r]),c=m(),u=l(()=>{let e=s();return i&&c.current!==void 0&&i(c.current,e)?c.current:(c.current=e,e)},[s,i]),d=l(()=>r,[r]);return h(o,i?u:s,d)}const N={reference:(e,t)=>Object.is(e,t),shallow:(e,t)=>{if(Object.is(e,t))return!0;if(typeof e!=`object`||!e||typeof t!=`object`||!t)return!1;let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(!Object.prototype.hasOwnProperty.call(t,r)||!Object.is(e[r],t[r]))return!1;return!0},deep:(e,t)=>{if(Object.is(e,t))return!0;if(typeof e!=`object`||!e||typeof t!=`object`||!t||Array.isArray(e)!==Array.isArray(t))return!1;let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(!Object.prototype.hasOwnProperty.call(t,r)||!N.deep(e[r],t[r]))return!1;return!0},smart:(e,t)=>Object.is(e,t)?!0:typeof e!=`object`||!e||typeof t!=`object`||!t?!1:Array.isArray(e)&&Array.isArray(t)?e.length===t.length?e.every((e,n)=>{let r=t[n];return typeof e==`object`&&e&&typeof r==`object`&&r?N.shallow(e,r):Object.is(e,r)}):!1:N.shallow(e,t)},P=N.smart;N.shallow,N.deep,N.smart;function F(e,t,n=P){let r=l(t,[t]),i=l(n,[n]);m(!1);let a=m(),o=l(t=>e.subscribe(t),[e]),s=l(()=>{try{let t=e.getValue(),n=r(t);return a.current!==void 0&&i(a.current,n)?a.current:(a.current=n,n)}catch(e){throw e}},[e,r,i]);return h(o,s,s)}var I=class extends s{constructor(e){super(e),this.resetTimeoutId=null,this.resetErrorBoundary=()=>{this.resetTimeoutId&&clearTimeout(this.resetTimeoutId),this.setState({hasError:!1,error:null,errorInfo:null,errorId:null})},this.state={hasError:!1,error:null,errorInfo:null,errorId:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e instanceof Error&&e.name===`ContextActionError`?e:null,errorId:`error_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}}componentDidCatch(t,n){if(t.name===`ContextActionError`){let e=t;this.setState({errorInfo:n}),this.props.onError?.(e,n)}else{let r=e.store(`Unhandled error in Store component: ${t.message}`,{component:`StoreErrorBoundary`,stack:t.stack,componentStack:n.componentStack},t);this.setState({error:r,errorInfo:n}),this.props.onError?.(r,n)}}componentDidUpdate(e){let{hasError:t}=this.state,{resetOnPropsChange:n,resetKeys:r}=this.props;t&&n&&(r?r.some(t=>{let n=e[t],r=this.props[t];return n!==r})&&this.resetErrorBoundary():e!==this.props&&this.resetErrorBoundary())}componentWillUnmount(){this.resetTimeoutId&&clearTimeout(this.resetTimeoutId)}render(){let{hasError:e,error:t,errorInfo:n}=this.state,{children:r,fallback:i}=this.props;return e?i?typeof i==`function`?i(t,n):i:this.renderDefaultFallback():r}renderDefaultFallback(){return this.renderProductionFallback()}renderDevelopmentFallback(){let{error:e,errorInfo:t,errorId:r}=this.state,i=n();return _(`div`,{style:{padding:`20px`,margin:`20px`,border:`2px solid #ff6b6b`,borderRadius:`8px`,backgroundColor:`#ffe0e0`,fontFamily:`monospace`},children:[g(`h2`,{style:{color:`#d63031`,margin:`0 0 10px 0`},children:`🚨 Store Error Boundary`}),_(`div`,{style:{marginBottom:`15px`},children:[g(`strong`,{children:`Error ID:`}),` `,r]}),e&&_(`div`,{style:{marginBottom:`15px`},children:[g(`strong`,{children:`Error Type:`}),` `,e.type,g(`br`,{}),g(`strong`,{children:`Message:`}),` `,e.message,g(`br`,{}),g(`strong`,{children:`Timestamp:`}),` `,new Date(e.timestamp).toISOString()]}),e?.context&&_(`div`,{style:{marginBottom:`15px`},children:[g(`strong`,{children:`Context:`}),g(`pre`,{style:{background:`#f8f9fa`,padding:`10px`,borderRadius:`4px`,overflow:`auto`,fontSize:`12px`},children:JSON.stringify(e.context,null,2)})]}),_(`div`,{style:{marginBottom:`15px`},children:[g(`strong`,{children:`Error Statistics:`}),g(`br`,{}),`Total Errors: `,i.totalErrors,g(`br`,{}),`Recent Errors: `,i.recentErrors.length]}),t&&_(`details`,{style:{marginBottom:`15px`},children:[g(`summary`,{style:{cursor:`pointer`,fontWeight:`bold`},children:`Component Stack`}),g(`pre`,{style:{background:`#f8f9fa`,padding:`10px`,borderRadius:`4px`,overflow:`auto`,fontSize:`11px`,whiteSpace:`pre-wrap`},children:t.componentStack})]}),g(`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 _(`div`,{style:{padding:`20px`,textAlign:`center`,backgroundColor:`#f8f9fa`,border:`1px solid #dee2e6`,borderRadius:`8px`,margin:`20px 0`},children:[g(`h3`,{style:{color:`#6c757d`,margin:`0 0 10px 0`},children:`Something went wrong`}),g(`p`,{style:{color:`#6c757d`,margin:`0 0 15px 0`},children:`We're sorry, but something unexpected happened. Please try again.`}),g(`button`,{onClick:this.resetErrorBoundary,style:{padding:`8px 16px`,backgroundColor:`#007bff`,color:`white`,border:`none`,borderRadius:`4px`,cursor:`pointer`},children:`Try Again`})]})}};function L(e,t){let n=n=>g(I,{...t,children:g(e,{...n})});return n.displayName=`withStoreErrorBoundary(${e.displayName||e.name})`,n}function R(e,t){return({children:n})=>g(I,{fallback:t,onError:(t,n)=>{console.group(`Store Error in ${e}`),console.error(`Error:`,t),console.error(`Component Stack:`,n.componentStack),console.groupEnd()},resetKeys:[e],children:n})}function z(e,t){let n=e instanceof Error?e:Error(String(e));return{handlerId:t.id,error:n,timestamp:Date.now(),severity:t.config.blocking?`blocking`:`non-blocking`}}async function B(e,t){let n=0,r=[],i=[];for(;n<e.handlers.length&&!(e.aborted||e.terminated);){let a=e.handlers[n];if(!a)continue;e.currentIndex=n;let o=t(a,n);try{if(e.aborted)break;if(a.config.condition)try{if(!a.config.condition(e.payload)){n++;continue}}catch{n++;continue}let t=a.handler(e.payload,o);if(a.config.blocking){let n=t instanceof Promise?await t:t;n!==void 0&&!e.terminated&&e.results.push(n)}else if(t instanceof Promise){let n=t.then(t=>(t!==void 0&&!e.terminated&&e.results.push(t),t)).catch(e=>{let t=z(e,a);i.push({handlerId:t.handlerId,error:t.error,timestamp:t.timestamp,severity:`non-blocking`})});r.push(n)}else t!==void 0&&!e.terminated&&e.results.push(t);if(e.terminated)break;if(e.jumpToPriority!==void 0){if(e.jumpCount=(e.jumpCount||0)+1,e.jumpCount>(e.maxJumps||10)){console.error(`[ActionRegister] ERROR: Maximum jump limit (${e.maxJumps||10}) exceeded. Aborting to prevent infinite loop. Check your jumpToPriority logic and conditions.`),e.aborted=!0,e.abortReason=`Maximum jump limit exceeded (${e.jumpCount} jumps)`,e.jumpToPriority=void 0;break}let t=e.handlers.findIndex(t=>(t.config.priority||0)<=e.jumpToPriority);if(t!==-1&&t!==n){if(t<n){let n=e.handlers[t];n&&!n.config.condition&&console.warn(`[ActionRegister] WARNING: Backward jumpToPriority to handler '${n.config.id||`unnamed`}' without condition. This may cause infinite loops! Consider adding a condition to prevent re-execution. Jump count: ${e.jumpCount}/${e.maxJumps||10}`)}n=t,e.jumpToPriority=void 0;continue}else e.jumpToPriority=void 0,n++}else n++}catch(e){let t=z(e,a);if(i.push(t),a.config.blocking)throw t.error;n++}}r.length>0&&await Promise.allSettled(r),i.length>0&&(e.collectedErrors=i.map(e=>({handlerId:e.handlerId,error:e.error,timestamp:e.timestamp,severity:`non-blocking`})))}async function V(e,t){let n=e.handlers,r=n.map(async(n,r)=>{let i=t(n,r);try{if(n.config.condition)try{if(!n.config.condition(e.payload))return{success:!0,handlerId:n.id,result:void 0,terminated:!1,skipped:!0}}catch{return{success:!0,handlerId:n.id,result:void 0,terminated:!1,skipped:!0}}let t=n.handler(e.payload,i),r;return r=t instanceof Promise?await t:t,r!==void 0&&!e.terminated&&e.results.push(r),{success:!0,handlerId:n.id,result:r,terminated:e.terminated}}catch(e){let t=z(e,n);if(t.severity===`blocking`)throw t.error;return{success:!1,handlerId:n.id,error:t.error}}}),i=await Promise.allSettled(r),a=i.filter((e,t)=>e.status===`rejected`?n[t]?.config.blocking??!1:!1);if(a.length>0)throw a[0].reason;let o=i.filter(e=>e.status===`fulfilled`&&e.value.terminated);o.length>0&&(e.terminated=!0,e.terminationResult=o[0].value.result)}async function H(e,t){let n=e.handlers;if(n.length===0)return;let r=n.map(async(n,r)=>{let i=t(n,r);try{if(n.config.condition)try{if(!n.config.condition(e.payload))return{success:!0,handlerId:n.id,registration:n,result:void 0,terminated:!1,skipped:!0}}catch{return{success:!0,handlerId:n.id,registration:n,result:void 0,terminated:!1,skipped:!0}}let t=n.handler(e.payload,i),r;return r=t instanceof Promise?await t:t,{success:!0,handlerId:n.id,registration:n,result:r,terminated:e.terminated}}catch(e){let t=z(e,n);return{success:!1,handlerId:n.id,error:t.error,registration:n}}}),i=await Promise.race(r);if(!i.success&&i.registration?.config.blocking)throw i.error;i.success&&i.result!==void 0&&e.results.push(i.result),i.success&&i.terminated&&(e.terminated=!0,e.terminationResult=i.result)}var U=class{constructor(e=!0){this.guards=new Map,this.maxIdleTime=6e4,this.cleanupIntervalMs=3e4,e&&this.startAutoCleanup()}startAutoCleanup(){this.cleanupInterval=setInterval(()=>{let e=Date.now(),t=[];this.guards.forEach((n,r)=>{let i=e-n.lastExecuted>this.maxIdleTime,a=n.debounceTimer||n.throttleTimer;i&&!a&&t.push(r)}),t.length>0&&(t.forEach(e=>this.guards.delete(e)),typeof process<`u`&&process.env?.DEBUG_CONTEXT_ACTION&&console.debug(`[ActionGuard] Cleaned up ${t.length} idle guards`))},this.cleanupIntervalMs)}async debounce(e,t){let n=this.guards.get(e);return n||(n={lastExecuted:0,isThrottled:!1,debounceTimer:void 0,throttleTimer:void 0,debouncePromise:void 0,debounceResolve:void 0},this.guards.set(e,n)),n.debounceTimer&&(clearTimeout(n.debounceTimer),n.debounceResolve&&=(n.debounceResolve(!1),void 0)),new Promise(e=>{n.debounceResolve=e,n.debounceTimer=setTimeout(()=>{n.debounceTimer=void 0,n.debounceResolve=void 0,n.lastExecuted=Date.now(),e(!0)},t)})}throttle(e,t){let n=this.guards.get(e);n||(n={lastExecuted:0,isThrottled:!1,debounceTimer:void 0,throttleTimer:void 0,debouncePromise:void 0,debounceResolve:void 0},this.guards.set(e,n));let r=Date.now(),i=r-n.lastExecuted;if(i>=t)return n.lastExecuted=r,n.isThrottled=!1,!0;if(n.isThrottled)return!1;n.isThrottled=!0;let a=t-i;return n.throttleTimer=setTimeout(()=>{n.isThrottled=!1,n.throttleTimer=void 0},a),!1}clearGuards(e){let t=this.guards.get(e);t&&(t.debounceTimer&&=(clearTimeout(t.debounceTimer),t.debounceResolve&&=(t.debounceResolve(!1),void 0),void 0),t.throttleTimer&&=(clearTimeout(t.throttleTimer),void 0),this.guards.delete(e))}clearAll(){this.guards.forEach(e=>{e.debounceTimer&&(clearTimeout(e.debounceTimer),e.debounceResolve&&e.debounceResolve(!1)),e.throttleTimer&&clearTimeout(e.throttleTimer)}),this.guards.clear()}getGuardState(e){return this.guards.get(e)}getAllGuardStates(){return new Map(this.guards)}destroy(){this.cleanupInterval&&=(clearInterval(this.cleanupInterval),void 0),this.clearAll()}getStats(){let e=0;return this.guards.forEach(t=>{(t.debounceTimer||t.throttleTimer)&&e++}),{activeGuards:this.guards.size,withTimers:e}}},W=class{constructor(e=`OperationQueue`,t=1){this.name=e,this.queue=[],this.processingPromise=null,this.operationCounter=0,this.activeOperations=0,this.pendingResolvers=[],this.maxConcurrency=Math.max(1,t)}enqueue(e,t=0){return new Promise((n,r)=>{let i={id:`${this.name}-${++this.operationCounter}`,operation:e,resolve:n,reject:r,priority:t,timestamp:Date.now()},a=this.queue.length;for(let e=0;e<this.queue.length;e++){let n=this.queue[e];if(n&&(n.priority||0)<t){a=e;break}}this.queue.splice(a,0,i),this.processingPromise&&this.notifyNewOperation(),this.processQueue()})}async processQueue(){if(this.processingPromise)return this.processingPromise;this.processingPromise=this._doProcess();try{await this.processingPromise}finally{this.processingPromise=null}}async _doProcess(){for(;this.queue.length>0||this.activeOperations>0;){for(;this.queue.length>0&&this.activeOperations<this.maxConcurrency;){let e=this.queue.shift();this.startOperation(e)}this.activeOperations>0&&await this.waitForAnyOperation()}}startOperation(e){this.activeOperations++,this.executeOperation(e).finally(()=>{this.activeOperations--,this.notifyOperationComplete()})}waitForAnyOperation(){return new Promise(e=>{this.pendingResolvers.push(e)})}notifyOperationComplete(){this.pendingResolvers.splice(0).forEach(e=>e())}notifyNewOperation(){this.notifyOperationComplete()}async executeOperation(e){try{let t=await Promise.resolve(e.operation());e.resolve(t)}catch(t){e.reject(t)}}getQueueInfo(){return{name:this.name,queueLength:this.queue.length,isProcessing:!!this.processingPromise,activeOperations:this.activeOperations,maxConcurrency:this.maxConcurrency,operations:this.queue.map(e=>({id:e.id,priority:e.priority,timestamp:e.timestamp}))}}getConcurrencyInfo(){return{maxConcurrency:this.maxConcurrency,activeOperations:this.activeOperations,availableSlots:this.maxConcurrency-this.activeOperations,queuedOperations:this.queue.length,efficiency:this.activeOperations/this.maxConcurrency}}clear(){this.queue.forEach(e=>{e.reject(Error(`Queue cleared`))}),this.queue=[],this.processingPromise=null,this.pendingResolvers.splice(0).forEach(e=>e())}get size(){return this.queue.length}get processing(){return!!this.processingPromise}},G=class{constructor(e={}){this.pipelines=new Map,this.executionMode=`sequential`,this.actionExecutionModes=new Map,this.unregisterFunctions=new Map,this.lastRegisteredTimestamps=new Map,this.filterCacheDisabled=!0,this.handlerIdCounter=0,this.controllerPool=[],this.maxControllerPoolSize=10,this.name=e.name||`ActionRegister`,this.registryConfig=e.registry,this.maxHandlersPerAction=e.registry?.maxHandlersPerAction??1e3,this.isDebugMode=!!this.registryConfig?.debug,this.actionGuard=new U(this.registryConfig?.autoCleanup!==!1),e.registry?.useConcurrencyQueue!==!1&&(this.dispatchQueue=new W(`${this.name}-Dispatch`)),this.registryConfig?.defaultExecutionMode&&(this.executionMode=this.registryConfig.defaultExecutionMode),this.log(`ActionRegister initialized`,{defaultExecutionMode:this.executionMode,autoCleanup:this.registryConfig?.autoCleanup!==!1,concurrencyQueue:!!this.dispatchQueue,debugMode:this.isDebugMode})}register(e,t,n={}){let r=n.id||this.generateHandlerId(e);return this._performRegistrationSync(e,t,n,r)}log(e,t,n=`log`){if(this.isDebugMode){let r=new Date().toISOString();console[n](`🎯 [${r}] [${this.name}] ${e}`,t||``)}}generateHandlerId(e){return`${String(e)}_${this.name}_${++this.handlerIdCounter}`}createAbortSignal(e){let t=[],n=[],r;if(e?.signal&&t.push(e.signal),e?.autoAbort?.enabled&&(r=new AbortController,t.push(r.signal)),t.length===0)return[void 0,r,()=>{}];if(t.length===1)return[t[0],r,()=>n.forEach(e=>e())];let i;if(typeof AbortSignal.any==`function`)i=AbortSignal.any(t);else{let e=new AbortController;i=e.signal,t.forEach(t=>{if(t.aborted)e.abort();else{let r=()=>e.abort();t.addEventListener(`abort`,r,{once:!0}),n.push(()=>t.removeEventListener(`abort`,r))}})}return[i,r,()=>{n.forEach(e=>{try{e()}catch(e){this.log(`Cleanup error during AbortSignal cleanup`,e,`warn`)}})}]}_performRegistrationSync(e,t,n,r){let i={handler:t,config:{priority:n.priority??0,id:r,blocking:n.blocking??!1,once:n.once??!1,debounce:n.debounce??void 0,throttle:n.throttle??void 0,replaceExisting:n.replaceExisting??!0,cleanup:n.cleanup,condition:n.condition},id:r};this.pipelines.has(e)||this.pipelines.set(e,[]);let a=this.pipelines.get(e);if(a.length>=this.maxHandlersPerAction)return console.warn(`Handler limit (${this.maxHandlersPerAction}) reached for action "${String(e)}". Registration ignored.`),()=>{};let o=a.findIndex(e=>e.id===r);if(o!==-1){let t=a[o],s=this.unregisterFunctions.get(r);if(i.config.replaceExisting){if(t&&t.config.cleanup&&typeof t.config.cleanup==`function`)try{t.config.cleanup()}catch(t){this.log(`Cleanup error for replaced handler: ${String(e)}`,t,`warn`)}s&&this.unregisterFunctions.delete(r),a[o]=i,a.sort((e,t)=>t.config.priority-e.config.priority),this.lastRegisteredTimestamps.set(e,new Date);let c=this.createUnregisterFunction(e,r,i);return this.unregisterFunctions.set(r,c),this.log(`Handler replaced: ${String(e)}`,{handlerId:r,priority:n.priority,totalHandlers:a.length,hadExistingUnregister:!!s}),c}else{if(!t)throw Error(`Internal error: existing handler should be defined in duplicate handler block`);if(this.log(`Handler duplicate ignored, returning existing unregister: ${String(e)}`,{handlerId:r,existingPriority:t.config.priority,newPriority:n.priority,existingBlocking:t.config.blocking,newBlocking:n.blocking,note:`Use replaceExisting:true to replace`},`warn`),s)return s;{let n=this.createUnregisterFunction(e,r,t);return this.unregisterFunctions.set(r,n),n}}}a.push(i),a.sort((e,t)=>t.config.priority-e.config.priority),this.lastRegisteredTimestamps.set(e,new Date);let s=this.createUnregisterFunction(e,r,i);return this.unregisterFunctions.set(r,s),this.log(`Handler registered: ${String(e)}`,{handlerId:r,priority:n.priority,totalHandlers:a.length}),s}async dispatch(e,t,n){return n?.immediate||!this.dispatchQueue?this._performDispatch(e,t,n):this.dispatchQueue.enqueue(async()=>this._performDispatch(e,t,n))}async _performDispatch(e,t,n){this.log(`Starting dispatch for action '${String(e)}'`,{hasPayload:t!==void 0,payloadType:t?.constructor?.name||typeof t,options:n?Object.keys(n):`none`,timestamp:new Date().toISOString()}),t instanceof Event&&console.warn(`Event object passed to action "${String(e)}"`,t.type);let[r,i,a]=this.createAbortSignal(n);if(n?.autoAbort?.onControllerCreated&&i&&n.autoAbort.onControllerCreated(i),r?.aborted){this.log(`Dispatch aborted before execution for '${String(e)}'`);return}let o=this.pipelines.get(e);if(this.log(`Pipeline lookup for '${String(e)}'`,{pipelineExists:!!o,handlersCount:o?.length||0,allRegisteredActions:Array.from(this.pipelines.keys()),pipelineMap:Object.fromEntries(Array.from(this.pipelines.entries()).map(([e,t])=>[e,t.length]))}),!o||o.length===0){this.log(`No handlers found for action '${String(e)}', dispatch cancelled`,{},`warn`);return}let s=n?.filter?this.filterHandlers(o,n.filter):o,c=String(e),l,u;if(n?.throttle!==void 0)l=n.throttle;else if(s.length>0){for(let e of s)if(e.config.throttle!==void 0){l=e.config.throttle;break}}if(n?.debounce!==void 0)u=n.debounce;else if(s.length>0){for(let e of s)if(e.config.debounce!==void 0){u=e.config.debounce;break}}if(u!==void 0&&!await this.actionGuard.debounce(c,u)||l!==void 0&&!this.actionGuard.throttle(c,l))return;let d=n?.executionMode||this.actionExecutionModes.get(e)||this.executionMode,f={action:String(e),payload:t,handlers:s,aborted:!1,abortReason:void 0,currentIndex:0,jumpToPriority:void 0,jumpCount:0,maxJumps:10,executionMode:d,results:[],terminated:!1,terminationResult:void 0},p=r?()=>{f.aborted=!0,f.abortReason=`Action dispatch aborted by signal`}:void 0;r&&p&&r.addEventListener(`abort`,p);try{await this.executePipeline(f,i,n?.autoAbort),this.log(`Pipeline execution succeeded for ${String(e)}`)}catch(t){throw this.log(`Pipeline execution failed for ${String(e)}`,t,`error`),t}finally{a()}}async dispatchWithResult(e,t,n){let r=Date.now(),[i,a,o]=this.createAbortSignal(n);if(n?.autoAbort?.onControllerCreated&&a&&n.autoAbort.onControllerCreated(a),i?.aborted)return{success:!1,aborted:!0,abortReason:`Action dispatch aborted by signal`,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:0,handlersExecuted:0,handlersSkipped:0,handlersFailed:0,startTime:r,endTime:r},handlers:[],errors:[]};let s=this.pipelines.get(e);if(!s||s.length===0)return{success:!0,aborted:!1,abortReason:void 0,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:0,handlersExecuted:0,handlersSkipped:0,handlersFailed:0,startTime:r,endTime:r},handlers:[],errors:[]};let c=n?.filter?this.filterHandlers(s,n.filter):s,l=String(e),u=await this.applyActionGuardControlsWithResult(l,c,n,r,s.length);if(u)return u;let d=n?.executionMode||this.actionExecutionModes.get(e)||this.executionMode,f={action:String(e),payload:t,handlers:c,aborted:!1,abortReason:void 0,currentIndex:0,jumpToPriority:void 0,jumpCount:0,maxJumps:10,executionMode:d,results:[],terminated:!1,terminationResult:void 0},p,m=[];c.forEach(e=>{m.push({id:e.config.id,executed:!1,duration:void 0,result:void 0,error:void 0,metadata:void 0})});let h=i?()=>{f.aborted=!0,f.abortReason=`Action dispatch aborted by signal`}:void 0;i&&h&&i.addEventListener(`abort`,h);let g=[];try{await this.executePipeline(f,a,n?.autoAbort),g=f.collectedErrors||[];let e=Math.min(f.currentIndex+(f.aborted?0:1),c.length);for(let t=0;t<e;t++){let e=c[t];if(!e)continue;let n=m.find(t=>t.id===e.config.id);n&&(n.executed=!0)}}catch(e){g=f.collectedErrors||[],p=e instanceof Error?e:Error(String(e)),g.push({handlerId:`pipeline`,error:p,timestamp:Date.now(),severity:`blocking`});let t=Math.min(f.currentIndex+1,c.length);for(let e=0;e<t;e++){let t=c[e];if(!t)continue;let n=m.find(e=>e.id===t.config.id);n&&(n.executed=!0)}}finally{o()}let _=Date.now(),v=this.processResults(f,n?.result),y=f.results.filter(e=>e!==void 0),b=g.map(e=>({handlerId:e.handlerId,error:e.error,expectedType:typeof v})),x={success:!p&&!f.aborted,aborted:f.aborted,abortReason:f.abortReason,terminated:f.terminated,result:v,successResults:y,results:f.results,failedResults:b,execution:{duration:_-r,handlersExecuted:c.length===0?0:f.currentIndex+(f.aborted?0:1),handlersSkipped:Math.max(0,c.length-(f.currentIndex+1)),handlersFailed:g.length,startTime:r,endTime:_},handlers:m,errors:g.map(e=>({handlerId:e.handlerId,error:e.error,timestamp:e.timestamp,severity:`non-blocking`}))};return this.cleanupOneTimeHandlers(e,f.handlers),x}async applyActionGuardControlsWithResult(e,t,n,r,i){let a,o;if(n?.throttle!==void 0)a=n.throttle;else if(t.length>0){for(let e of t)if(e.config.throttle!==void 0){a=e.config.throttle;break}}if(n?.debounce!==void 0)o=n.debounce;else if(t.length>0){for(let e of t)if(e.config.debounce!==void 0){o=e.config.debounce;break}}return o!==void 0&&!await this.actionGuard.debounce(e,o)?{success:!1,aborted:!0,abortReason:`Debounced execution`,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:Date.now()-r,handlersExecuted:0,handlersSkipped:i,handlersFailed:0,startTime:r,endTime:Date.now()},handlers:[],errors:[]}:a!==void 0&&!this.actionGuard.throttle(e,a)?{success:!1,aborted:!0,abortReason:`Throttled execution`,terminated:!1,result:void 0,successResults:[],results:[],failedResults:[],execution:{duration:Date.now()-r,handlersExecuted:0,handlersSkipped:i,handlersFailed:0,startTime:r,endTime:Date.now()},handlers:[],errors:[]}:null}generateFilterCacheKey(e){if(!e)return`no-filter`;let t=[];if(e.handlerIds?.length&&t.push(`h:${e.handlerIds.slice().sort().join(`,`)}`),e.excludeHandlerIds?.length&&t.push(`e:${e.excludeHandlerIds.slice().sort().join(`,`)}`),e.priority){let{min:n,max:r}=e.priority;(n!==void 0||r!==void 0)&&t.push(`p:${n??`*`}-${r??`*`}`)}return e.custom?`custom-`+Date.now()+Math.random():t.length>0?t.join(`|`):`no-filter`}getControllerFromPool(e,t,n){let r=this.controllerPool.pop();return r||={},r.abort=r=>{e.aborted=!0,e.abortReason=r,t&&n?.allowHandlerAbort&&t.abort(r)},r.modifyPayload=t=>{try{e.payload=t(e.payload)}catch(e){this.log(`Payload modification error`,e,`warn`)}},r.getPayload=()=>e.payload,r.jumpToPriority=t=>{e.jumpToPriority=t},r.return=t=>{e.terminated=!0,e.terminationResult=t},r.setResult=t=>{e.results.push(t)},r.getResults=()=>[...e.results],r.mergeResult=t=>{let n=e.results[e.results.length-1],r=e.results.slice(0,-1),i=t(r,n);e.results[e.results.length-1]=i},r}returnControllerToPool(e){this.controllerPool.length<this.maxControllerPoolSize&&this.controllerPool.push(e)}filterHandlers(e,t){if(!t)return e;let n=t.handlerIds?new Set(t.handlerIds):null,r=t.excludeHandlerIds?new Set(t.excludeHandlerIds):null;return e.filter(e=>{let i=e.config;if(n&&!n.has(i.id)||r&&r.has(i.id))return!1;if(t.priority){let e=i.priority;if(t.priority.min!==void 0&&e<t.priority.min||t.priority.max!==void 0&&e>t.priority.max)return!1}return!(t.custom&&!t.custom(i))})}processResults(e,t){let n=e.results;if(e.terminated&&e.terminationResult!==void 0)return e.terminationResult;if(!t)return n.length>0?n[n.length-1]:void 0;if(!t.collect&&!t.strategy)return;let r=t.maxResults?n.slice(0,t.maxResults):n;if(r.length!==0)switch(t.strategy){case`first`:return r[0];case`last`:return r[r.length-1];case`all`:return r;case`merge`:return t.merger?t.merger(r):r[r.length-1];case`custom`:if(t.merger)return t.merger(r);throw Error(`Custom result strategy requires a merger function`);default:return t.collect?r:r[r.length-1]}}async executePipeline(e,t,n){let r=(r,i)=>this.getControllerFromPool(e,t,n);switch(e.executionMode){case`sequential`:await B(e,r);break;case`parallel`:await V(e,r);break;case`race`:await H(e,r);break;default:throw Error(`Unknown execution mode: ${e.executionMode}`)}this.cleanupOneTimeHandlers(e.action,e.handlers)}cleanupOneTimeHandlers(e,t){let n=this.pipelines.get(e);if(!n)return;let r=t.filter(e=>e.config.once);r.length!==0&&(r.forEach(t=>{let r=n.findIndex(e=>e.id===t.id);r!==-1&&(n.splice(r,1),this.registryConfig?.debug&&console.log(`🎯 One-time handler removed: ${String(e)}`,{handlerId:t.id,remainingHandlers:n.length,registry:this.name}))}),n.length===0&&(this.pipelines.delete(e),this.lastRegisteredTimestamps.delete(e)))}getHandlerCount(e){let t=this.pipelines.get(e);return t?t.length:0}hasHandlers(e){return this.getHandlerCount(e)>0}getRegisteredActions(){return Array.from(this.pipelines.keys())}clearAction(e){this.pipelines.delete(e),this.lastRegisteredTimestamps.delete(e)}clearAll(){this.pipelines.clear(),this.lastRegisteredTimestamps.clear()}getName(){return this.name}getRegistryInfo(){let e=Array.from(this.pipelines.values()).reduce((e,t)=>e+t.length,0);return{name:this.name,totalActions:this.pipelines.size,totalHandlers:e,registeredActions:Array.from(this.pipelines.keys()),actionExecutionModes:new Map(this.actionExecutionModes),defaultExecutionMode:this.executionMode}}getActionStats(e){let t=this.pipelines.get(e);if(!t)return null;let n=new Map;t.forEach(e=>{n.has(e.config.priority)||n.set(e.config.priority,[]),n.get(e.config.priority).push(e)});let r=Array.from(n.entries()).sort(([e],[t])=>t-e).map(([e,t])=>({priority:e,handlers:t.map(e=>({id:e.config.id}))}));return{action:e,handlerCount:t.length,totalHandlers:t.length,handlersByPriority:r,executionStats:void 0,lastRegistered:this.lastRegisteredTimestamps.get(e)}}getAllActionStats(){return Array.from(this.pipelines.keys()).map(e=>this.getActionStats(e)).filter(e=>e!==null)}setExecutionMode(e){this.executionMode=e,this.registryConfig?.debug&&console.log(`🎯 Global execution mode set to: ${e}`)}setActionExecutionMode(e,t){this.actionExecutionModes.set(e,t),this.registryConfig?.debug&&console.log(`🎯 Execution mode set for action '${String(e)}': ${t}`)}getActionExecutionMode(e){return this.actionExecutionModes.get(e)||this.executionMode}removeActionExecutionMode(e){this.actionExecutionModes.delete(e),this.registryConfig?.debug&&console.log(`🎯 Execution mode reset for action '${String(e)}' to default: ${this.executionMode}`)}getRegistryConfig(){return this.registryConfig}isDebugEnabled(){return this.isDebugMode}createUnregisterFunction(e,t,n){return()=>{let r=this.pipelines.get(e);if(!r)return;let i=r.findIndex(e=>e.id===t&&e===n);if(i!==-1){if(r.splice(i,1),this.unregisterFunctions.delete(t),r.length===0&&(this.pipelines.delete(e),this.lastRegisteredTimestamps.delete(e)),n.config.cleanup&&typeof n.config.cleanup==`function`)try{n.config.cleanup()}catch(t){this.log(`Cleanup error during unregister: ${String(e)}`,t,`warn`)}this.log(`Handler unregistered: ${String(e)}`,{handlerId:t,remainingHandlers:r.length,actionRemoved:r.length===0})}}}getUnregisterFunctionCount(){return this.unregisterFunctions.size}hasUnregisterFunction(e){return this.unregisterFunctions.has(e)}destroy(){this.unregisterFunctions.clear();for(let[e,t]of this.pipelines.entries())for(let n of t)if(n.config.cleanup&&typeof n.config.cleanup==`function`)try{n.config.cleanup()}catch(t){this.log(`Cleanup error for handler during destroy: ${String(e)}`,t,`warn`)}this.pipelines.clear(),this.lastRegisteredTimestamps.clear(),this.actionGuard.destroy(),this.dispatchQueue?.clear?.(),this.actionExecutionModes.clear(),this.controllerPool.length=0,this.log(`ActionRegister destroyed`)}};function K(e={},t){let n,r;typeof e==`string`?(r=e,n={...t,name:t?.name||r}):(n=e,r=n.name||`ActionContext`);let i=c(null),a=({children:e})=>{let t=m(new G(n)),r=p(()=>({actionRegisterRef:t}),[]);return g(i.Provider,{value:r,children:e})},o=()=>{let e=u(i);if(!e)throw Error(`useFactoryActionContext must be used within a factory ActionContext Provider`);return e},s=()=>{let{actionRegisterRef:e}=o(),t=l((t,n,r)=>{let i=e.current;if(!i)throw Error(`ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up.`);let a={...r,...r?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0}}};return i.dispatch(t,n,a)},[e]),n=l((t,n,r)=>{let i=e.current;if(!i)throw Error(`ActionRegister not initialized`);let a={...r,...r?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0}}};return i.dispatchWithResult(t,n,a)},[e]);return{dispatch:t,dispatchWithResult:n}};return{Provider:a,useActionContext:o,useActionDispatch:()=>{let{dispatch:e}=s();return e},useActionHandler:(e,t,n)=>{let{actionRegisterRef:r}=o(),i=f(),a=m(t);a.current=t;let s=n?.priority??0,c=n?.id||`react_${String(e)}_${i}`,l=n?.blocking??!1,u=n?.once??!1,h=n?.debounce,g=n?.throttle,_=p(()=>({priority:s,id:c,blocking:l,once:u,replaceExisting:!0,...h!==void 0&&{debounce:h},...g!==void 0&&{throttle:g}}),[s,c,l,u,h,g]);d(()=>{let t=r.current;return t?t.register(e,(e,t)=>a.current(e,t),_):void 0},[e,r,_])},useActionRegister:()=>o().actionRegisterRef.current,useActionDispatchWithResult:()=>{let e=o(),t=m(new Set),n=l((n,r,i)=>{let a=e.actionRegisterRef.current;if(!a)throw Error(`ActionRegister not initialized`);let o={...i,...i?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0,onControllerCreated:e=>{t.current.add(e)}}}};return a.dispatch(n,r,o)},[e.actionRegisterRef]),r=l((n,r,i)=>{let a=e.actionRegisterRef.current;if(!a)throw Error(`ActionRegister not initialized`);let o={...i,...i?.signal?{}:{autoAbort:{enabled:!0,allowHandlerAbort:!0,onControllerCreated:e=>{t.current.add(e)}}}};return a.dispatchWithResult(n,r,o)},[e.actionRegisterRef]),i=l(()=>{t.current.forEach(e=>{e.signal.aborted||e.abort()}),t.current.clear()},[]),a=l(()=>{i()},[i]);return d(()=>{let e=t;return()=>{e.current.forEach(e=>{e.signal.aborted||e.abort()}),e.current.clear()}},[]),{dispatch:n,dispatchWithResult:r,abortAll:i,resetAbortScope:a}},context:i}}export{G as ActionRegister,k as Store,I as StoreErrorBoundary,v as StoreRegistry,K as createActionContext,A as createStore,R as createStoreErrorBoundary,P as defaultEqualityFn,M as useSafeStoreSubscription,F as useStoreSelector,L as withStoreErrorBoundary}; |
| 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; | ||
| } | ||
| /** | ||
| * 복사하지 않아야 할 특별한 객체 타입들을 확인 | ||
| */ | ||
| 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") 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) {} | ||
| 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) { | ||
| 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) { | ||
| return value; | ||
| } | ||
| } | ||
| /** | ||
| * 안전한 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; | ||
| return deepClone(value); | ||
| } | ||
| /** | ||
| * 안전한 setter - 입력값의 불변성을 보장하는 값 설정 | ||
| * | ||
| * @template T 값의 타입 | ||
| * @param value 설정할 값 | ||
| * @param enableCloning 복사 활성화 여부 (기본: true) | ||
| * @returns 불변성이 보장된 값 | ||
| */ | ||
| function safeSet(value, enableCloning = true) { | ||
| if (!enableCloning) 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) { | ||
| try { | ||
| const draft = deepClone(baseState); | ||
| const result = producer(draft); | ||
| return result !== void 0 ? result : draft; | ||
| } catch (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) {} | ||
| switch (strategy) { | ||
| case "reference": | ||
| result = referenceEquals(oldValue, newValue); | ||
| break; | ||
| case "shallow": | ||
| result = shallowEquals(oldValue, newValue, ignoreKeys); | ||
| break; | ||
| case "deep": { | ||
| const deepOptions = { | ||
| ...maxDepth !== void 0 && { maxDepth }, | ||
| ...ignoreKeys !== void 0 && { ignoreKeys }, | ||
| ...enableCircularCheck !== void 0 && { enableCircularCheck } | ||
| }; | ||
| result = deepEquals(oldValue, newValue, deepOptions); | ||
| break; | ||
| } | ||
| case "custom": | ||
| if (!customComparator) result = referenceEquals(oldValue, newValue); | ||
| else result = customComparator(oldValue, newValue); | ||
| break; | ||
| default: result = referenceEquals(oldValue, newValue); | ||
| } | ||
| } catch (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.ERROR, | ||
| throwOnError: false, | ||
| 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 }; |
| var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`immer`);c=s(c),(0,c.enableMapSet)();function l(e){return e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`||typeof e==`bigint`||typeof e==`symbol`}function u(e){if(!e||typeof e!=`object`)return!1;if(Array.isArray(e))return!0;if(e.constructor===Object){let t=e;return Object.values(t).some(e=>typeof e==`object`&&!!e)}return e.constructor!==Object}function d(e){if(!e||typeof e!=`object`)return!1;if(typeof Element<`u`&&e instanceof Element||typeof Node<`u`&&e instanceof Node||typeof HTMLElement<`u`&&e instanceof HTMLElement)return!0;let t=e;return typeof t.nodeType==`number`&&t.nodeType>0||typeof t.nodeName==`string`||typeof t.tagName==`string`||t._owner!==void 0||t.stateNode!==void 0||typeof e==`function`||e instanceof Promise||typeof t.then==`function`&&typeof t.catch==`function`||e instanceof WeakMap||e instanceof WeakSet}function f(e,t){if(l(e)||typeof e==`function`||d(e)||typeof e==`object`&&e&&`__contextActionRefState`in e&&e.__contextActionRefState===!0)return e;try{return(0,c.produce)(e,e=>{})}catch{}if(typeof structuredClone<`u`)try{return structuredClone(e)}catch{}return u(e)?g(e):h(e)}function p(e){if(l(e)||d(e)||typeof e==`function`)return e;try{return(0,c.produce)(e,e=>{})}catch{return g(e)}}function m(e){return typeof e==`object`&&!!e&&e.constructor===Object&&Object.getPrototypeOf(e)===Object.prototype}function h(e,t=new WeakSet){if(typeof e==`object`&&e&&t.has(e))return`[Circular]`;if(Array.isArray(e))return t.add(e),e.map(e=>typeof e==`object`&&e?`__contextActionRefState`in e&&e.__contextActionRefState===!0?e:h(e,t):e);if(m(e)){t.add(e);let n={};for(let[r,i]of Object.entries(e))typeof i==`object`&&i?`__contextActionRefState`in i&&i.__contextActionRefState===!0?n[r]=i:n[r]=h(i,t):n[r]=i;return n}return e}function g(e){try{let t=new WeakSet,n=new Map,r=0,i=e=>{if(!(typeof e!=`object`||!e||t.has(e))){if(t.add(e),`__contextActionRefState`in e&&e.__contextActionRefState===!0){let t=`refstate_${r++}`;n.set(t,e)}try{if(Array.isArray(e))e.forEach(i);else for(let t of Object.values(e))i(t)}catch{}}};try{i(e)}catch{}let a=(e=>{let t=new WeakSet;return JSON.stringify(e,function(e,r){if(typeof r==`object`&&r){if(t.has(r))return`[Circular]`;if(t.add(r),`__contextActionRefState`in r&&r.__contextActionRefState===!0){let e=Array.from(n.entries());for(let t=0;t<e.length;t++){let n=e[t];if(n&&n[1]===r)return{__REFSTATE_PLACEHOLDER__:n[0]}}}}return r})})(e),o=JSON.parse(a),s=e=>{if(typeof e!=`object`||!e)return e;if(e.__REFSTATE_PLACEHOLDER__&&n.has(e.__REFSTATE_PLACEHOLDER__))return n.get(e.__REFSTATE_PLACEHOLDER__);if(Array.isArray(e))return e.map(s);let t={};for(let[n,r]of Object.entries(e))t[n]=s(r);return t};return s(o)}catch{return e}}function _(e,t=!0){return!t||l(e)||d(e)||typeof e==`object`&&e&&`__contextActionRefState`in e&&e.__contextActionRefState===!0?e:f(e)}function v(e,t=!0){return t?f(e):e}const y={isDraft(e){return(0,c.isDraft)(e)},original(e){return(0,c.original)(e)},current(e){return(0,c.current)(e)},produce(e,t){return(0,c.produce)(e,t)}};function b(){}function x(e,t){try{return(0,c.produce)(e,t)}catch{try{let n=f(e),r=t(n);return r===void 0?n:r}catch{return e}}}const S={strategy:`reference`,maxDepth:5,enableCircularCheck:!0};let C={...S};function w(e){C={...S,...e}}function T(){return{...C}}function E(e,t){return Object.is(e,t)}function D(e,t,n=[]){if(Object.is(e,t))return!0;if(e==null||t==null||typeof e!=`object`||typeof t!=`object`)return e===t;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!Object.is(e[n],t[n]))return!1;return!0}let r=Object.keys(e).filter(e=>!n.includes(e)),i=Object.keys(t).filter(e=>!n.includes(e));if(r.length!==i.length)return!1;for(let n of r)if(!i.includes(n)||!Object.is(e[n],t[n]))return!1;return!0}function O(e,t,n={}){let{maxDepth:r=5,ignoreKeys:i=[],enableCircularCheck:a=!0}=n,o=a?new WeakMap:null;function s(e,t,n,a=``){if(n>r)return Object.is(e,t);if(Object.is(e,t))return!0;if(e==null||t==null)return e===t;if(typeof e!=typeof t)return!1;if(typeof e!=`object`)return e===t;if(o&&typeof e==`object`&&typeof t==`object`&&e!==null&&t!==null){if(o.has(e)&&o.get(e).has(t))return Object.is(e,t);o.has(e)||o.set(e,new WeakSet),o.get(e).add(t),o.has(t)||o.set(t,new WeakSet),o.get(t).add(e)}if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(e instanceof RegExp&&t instanceof RegExp)return e.toString()===t.toString();if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(!s(e[r],t[r],n+1,`${a}[${r}]`))return!1;return!0}if(Array.isArray(e)||Array.isArray(t))return!1;let c=Object.keys(e).filter(e=>!i.includes(e)),l=Object.keys(t).filter(e=>!i.includes(e));if(c.length!==l.length)return!1;for(let r of c)if(!l.includes(r)||!s(e[r],t[r],n+1,`${a}.${r}`))return!1;return!0}return s(e,t,0)}function k(e,t,n={}){let{strategy:r,customComparator:i,maxDepth:a,ignoreKeys:o,enableCircularCheck:s}={...C,...n},c;try{if(r!==`reference`&&r!==`custom`&&typeof e==`object`&&typeof t==`object`)try{let n=JSON.stringify(e),r=JSON.stringify(t);if(n.length<1e3&&r.length<1e3)return c=n===r,c}catch{}switch(r){case`reference`:c=E(e,t);break;case`shallow`:c=D(e,t,o);break;case`deep`:{let n={...a!==void 0&&{maxDepth:a},...o!==void 0&&{ignoreKeys:o},...s!==void 0&&{enableCircularCheck:s}};c=O(e,t,n);break}case`custom`:c=i?i(e,t):E(e,t);break;default:c=E(e,t)}}catch{c=E(e,t)}return c}let A=function(e){return e.STORE_ERROR=`STORE_ERROR`,e.ACTION_ERROR=`ACTION_ERROR`,e.REF_ERROR=`REF_ERROR`,e.VALIDATION_ERROR=`VALIDATION_ERROR`,e.INITIALIZATION_ERROR=`INITIALIZATION_ERROR`,e.TIMEOUT_ERROR=`TIMEOUT_ERROR`,e.CIRCULAR_REFERENCE_ERROR=`CIRCULAR_REFERENCE_ERROR`,e}({});var j=class e extends Error{constructor(t,n,r,i){super(n),this.name=`ContextActionError`,this.type=t,this.context=r??void 0,this.timestamp=Date.now(),Error.captureStackTrace&&Error.captureStackTrace(this,e),i&&(this.stack=`${this.stack}\nCaused by: ${i.stack}`)}};let M=function(e){return e[e.SILENT=0]=`SILENT`,e[e.ERROR=1]=`ERROR`,e[e.WARN=2]=`WARN`,e[e.INFO=3]=`INFO`,e[e.DEBUG=4]=`DEBUG`,e}({}),N={logLevel:M.ERROR,throwOnError:!1,enableStackTrace:!0,maxLogEntries:100,suppressRepeatedErrors:!0,logErrors:!0},P=[],F=new Map;function I(e){return`${e.type}:${e.message}:${e.context?.component||`unknown`}`}function L(e,t,n,r){let i=new j(e,t,n,r);if(R(i),N.throwOnError)throw i;return i}function R(e){let t=I(e);if(N.suppressRepeatedErrors){let n=F.get(t);if(n){n.count++,n.lastOccurred=Date.now(),n.count%10==0&&console.warn(`[Context-Action] Repeated error occurred ${n.count} times:`,e);return}}let n={error:e,count:1,lastOccurred:Date.now()};if(P.push(n),F.set(t,n),P.length>N.maxLogEntries){let e=P.shift();if(e){let t=I(e.error);F.delete(t)}}switch(typeof globalThis<`u`&&globalThis.globalErrorBoundary&&globalThis.globalErrorBoundary.reportError(e),N.logLevel){case M.DEBUG:console.debug(`[Context-Action] Debug:`,e);break;case M.INFO:console.info(`[Context-Action] Info:`,e);break;case M.WARN:console.warn(`[Context-Action] Warning:`,e);break;case M.ERROR:console.error(`[Context-Action] Error:`,e),N.enableStackTrace&&e.stack&&console.error(`Stack trace:`,e.stack);break;case M.SILENT:break}}const z={store:(e,t,n)=>{let r=`[Store Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return L(A.STORE_ERROR,r,t,n)},action:(e,t,n)=>{let r=`[Action Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return L(A.ACTION_ERROR,r,t,n)},ref:(e,t,n)=>{let r=`[Ref Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return L(A.REF_ERROR,r,t,n)},validation:(e,t,n)=>{let r=`[Validation Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return L(A.VALIDATION_ERROR,r,t,n)},initialization:(e,t,n)=>{let r=`[Initialization Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return L(A.INITIALIZATION_ERROR,r,t,n)},timeout:(e,t,n)=>{let r=`[Timeout Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return L(A.TIMEOUT_ERROR,r,t,n)},circularReference:(e,t,n)=>L(A.CIRCULAR_REFERENCE_ERROR,e,t,n)};function B(){let e=Object.values(A).reduce((e,t)=>(e[t]=0,e),{});P.forEach(t=>{e[t.error.type]+=t.count});let t=Array.from(F.entries()).map(([e,t])=>({signature:e,count:t.count,lastOccurred:t.lastOccurred})).sort((e,t)=>t.count-e.count).slice(0,10),n=P.slice(-10).map(e=>e.error);return{totalErrors:P.reduce((e,t)=>e+t.count,0),errorsByType:e,mostFrequentErrors:t,recentErrors:n}}Object.defineProperty(exports,`ContextActionError`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`ContextActionErrorType`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`ErrorHandlers`,{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,`ImmerUtils`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`__toESM`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`compareValues`,{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,`deepClone`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`deepCloneWithImmer`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`getErrorStatistics`,{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,`getGlobalComparisonOptions`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`handleError`,{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,`preloadImmer`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`produce`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`safeGet`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`safeSet`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`setGlobalComparisonOptions`,{enumerable:!0,get:function(){return w}}); |
| import{current as e,enableMapSet as t,isDraft as n,original as r,produce as i}from"immer";t();function a(e){return e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`||typeof e==`bigint`||typeof e==`symbol`}function o(e){if(!e||typeof e!=`object`)return!1;if(Array.isArray(e))return!0;if(e.constructor===Object){let t=e;return Object.values(t).some(e=>typeof e==`object`&&!!e)}return e.constructor!==Object}function s(e){if(!e||typeof e!=`object`)return!1;if(typeof Element<`u`&&e instanceof Element||typeof Node<`u`&&e instanceof Node||typeof HTMLElement<`u`&&e instanceof HTMLElement)return!0;let t=e;return typeof t.nodeType==`number`&&t.nodeType>0||typeof t.nodeName==`string`||typeof t.tagName==`string`||t._owner!==void 0||t.stateNode!==void 0||typeof e==`function`||e instanceof Promise||typeof t.then==`function`&&typeof t.catch==`function`||e instanceof WeakMap||e instanceof WeakSet}function c(e,t){if(a(e)||typeof e==`function`||s(e)||typeof e==`object`&&e&&`__contextActionRefState`in e&&e.__contextActionRefState===!0)return e;try{return i(e,e=>{})}catch{}if(typeof structuredClone<`u`)try{return structuredClone(e)}catch{}return o(e)?f(e):d(e)}function l(e){if(a(e)||s(e)||typeof e==`function`)return e;try{return i(e,e=>{})}catch{return f(e)}}function u(e){return typeof e==`object`&&!!e&&e.constructor===Object&&Object.getPrototypeOf(e)===Object.prototype}function d(e,t=new WeakSet){if(typeof e==`object`&&e&&t.has(e))return`[Circular]`;if(Array.isArray(e))return t.add(e),e.map(e=>typeof e==`object`&&e?`__contextActionRefState`in e&&e.__contextActionRefState===!0?e:d(e,t):e);if(u(e)){t.add(e);let n={};for(let[r,i]of Object.entries(e))typeof i==`object`&&i?`__contextActionRefState`in i&&i.__contextActionRefState===!0?n[r]=i:n[r]=d(i,t):n[r]=i;return n}return e}function f(e){try{let t=new WeakSet,n=new Map,r=0,i=e=>{if(!(typeof e!=`object`||!e||t.has(e))){if(t.add(e),`__contextActionRefState`in e&&e.__contextActionRefState===!0){let t=`refstate_${r++}`;n.set(t,e)}try{if(Array.isArray(e))e.forEach(i);else for(let t of Object.values(e))i(t)}catch{}}};try{i(e)}catch{}let a=(e=>{let t=new WeakSet;return JSON.stringify(e,function(e,r){if(typeof r==`object`&&r){if(t.has(r))return`[Circular]`;if(t.add(r),`__contextActionRefState`in r&&r.__contextActionRefState===!0){let e=Array.from(n.entries());for(let t=0;t<e.length;t++){let n=e[t];if(n&&n[1]===r)return{__REFSTATE_PLACEHOLDER__:n[0]}}}}return r})})(e),o=JSON.parse(a),s=e=>{if(typeof e!=`object`||!e)return e;if(e.__REFSTATE_PLACEHOLDER__&&n.has(e.__REFSTATE_PLACEHOLDER__))return n.get(e.__REFSTATE_PLACEHOLDER__);if(Array.isArray(e))return e.map(s);let t={};for(let[n,r]of Object.entries(e))t[n]=s(r);return t};return s(o)}catch{return e}}function p(e,t=!0){return!t||a(e)||s(e)||typeof e==`object`&&e&&`__contextActionRefState`in e&&e.__contextActionRefState===!0?e:c(e)}function m(e,t=!0){return t?c(e):e}const h={isDraft(e){return n(e)},original(e){return r(e)},current(t){return e(t)},produce(e,t){return i(e,t)}};function g(){}function _(e,t){try{return i(e,t)}catch{try{let n=c(e),r=t(n);return r===void 0?n:r}catch{return e}}}const v={strategy:`reference`,maxDepth:5,enableCircularCheck:!0};let y={...v};function b(e){y={...v,...e}}function x(){return{...y}}function S(e,t){return Object.is(e,t)}function C(e,t,n=[]){if(Object.is(e,t))return!0;if(e==null||t==null||typeof e!=`object`||typeof t!=`object`)return e===t;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!Object.is(e[n],t[n]))return!1;return!0}let r=Object.keys(e).filter(e=>!n.includes(e)),i=Object.keys(t).filter(e=>!n.includes(e));if(r.length!==i.length)return!1;for(let n of r)if(!i.includes(n)||!Object.is(e[n],t[n]))return!1;return!0}function w(e,t,n={}){let{maxDepth:r=5,ignoreKeys:i=[],enableCircularCheck:a=!0}=n,o=a?new WeakMap:null;function s(e,t,n,a=``){if(n>r)return Object.is(e,t);if(Object.is(e,t))return!0;if(e==null||t==null)return e===t;if(typeof e!=typeof t)return!1;if(typeof e!=`object`)return e===t;if(o&&typeof e==`object`&&typeof t==`object`&&e!==null&&t!==null){if(o.has(e)&&o.get(e).has(t))return Object.is(e,t);o.has(e)||o.set(e,new WeakSet),o.get(e).add(t),o.has(t)||o.set(t,new WeakSet),o.get(t).add(e)}if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(e instanceof RegExp&&t instanceof RegExp)return e.toString()===t.toString();if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(!s(e[r],t[r],n+1,`${a}[${r}]`))return!1;return!0}if(Array.isArray(e)||Array.isArray(t))return!1;let c=Object.keys(e).filter(e=>!i.includes(e)),l=Object.keys(t).filter(e=>!i.includes(e));if(c.length!==l.length)return!1;for(let r of c)if(!l.includes(r)||!s(e[r],t[r],n+1,`${a}.${r}`))return!1;return!0}return s(e,t,0)}function T(e,t,n={}){let{strategy:r,customComparator:i,maxDepth:a,ignoreKeys:o,enableCircularCheck:s}={...y,...n},c;try{if(r!==`reference`&&r!==`custom`&&typeof e==`object`&&typeof t==`object`)try{let n=JSON.stringify(e),r=JSON.stringify(t);if(n.length<1e3&&r.length<1e3)return c=n===r,c}catch{}switch(r){case`reference`:c=S(e,t);break;case`shallow`:c=C(e,t,o);break;case`deep`:{let n={...a!==void 0&&{maxDepth:a},...o!==void 0&&{ignoreKeys:o},...s!==void 0&&{enableCircularCheck:s}};c=w(e,t,n);break}case`custom`:c=i?i(e,t):S(e,t);break;default:c=S(e,t)}}catch{c=S(e,t)}return c}let E=function(e){return e.STORE_ERROR=`STORE_ERROR`,e.ACTION_ERROR=`ACTION_ERROR`,e.REF_ERROR=`REF_ERROR`,e.VALIDATION_ERROR=`VALIDATION_ERROR`,e.INITIALIZATION_ERROR=`INITIALIZATION_ERROR`,e.TIMEOUT_ERROR=`TIMEOUT_ERROR`,e.CIRCULAR_REFERENCE_ERROR=`CIRCULAR_REFERENCE_ERROR`,e}({});var D=class e extends Error{constructor(t,n,r,i){super(n),this.name=`ContextActionError`,this.type=t,this.context=r??void 0,this.timestamp=Date.now(),Error.captureStackTrace&&Error.captureStackTrace(this,e),i&&(this.stack=`${this.stack}\nCaused by: ${i.stack}`)}};let O=function(e){return e[e.SILENT=0]=`SILENT`,e[e.ERROR=1]=`ERROR`,e[e.WARN=2]=`WARN`,e[e.INFO=3]=`INFO`,e[e.DEBUG=4]=`DEBUG`,e}({}),k={logLevel:O.ERROR,throwOnError:!1,enableStackTrace:!0,maxLogEntries:100,suppressRepeatedErrors:!0,logErrors:!0},A=[],j=new Map;function M(e){return`${e.type}:${e.message}:${e.context?.component||`unknown`}`}function N(e,t,n,r){let i=new D(e,t,n,r);if(P(i),k.throwOnError)throw i;return i}function P(e){let t=M(e);if(k.suppressRepeatedErrors){let n=j.get(t);if(n){n.count++,n.lastOccurred=Date.now(),n.count%10==0&&console.warn(`[Context-Action] Repeated error occurred ${n.count} times:`,e);return}}let n={error:e,count:1,lastOccurred:Date.now()};if(A.push(n),j.set(t,n),A.length>k.maxLogEntries){let e=A.shift();if(e){let t=M(e.error);j.delete(t)}}switch(typeof globalThis<`u`&&globalThis.globalErrorBoundary&&globalThis.globalErrorBoundary.reportError(e),k.logLevel){case O.DEBUG:console.debug(`[Context-Action] Debug:`,e);break;case O.INFO:console.info(`[Context-Action] Info:`,e);break;case O.WARN:console.warn(`[Context-Action] Warning:`,e);break;case O.ERROR:console.error(`[Context-Action] Error:`,e),k.enableStackTrace&&e.stack&&console.error(`Stack trace:`,e.stack);break;case O.SILENT:break}}const F={store:(e,t,n)=>{let r=`[Store Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return N(E.STORE_ERROR,r,t,n)},action:(e,t,n)=>{let r=`[Action Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return N(E.ACTION_ERROR,r,t,n)},ref:(e,t,n)=>{let r=`[Ref Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return N(E.REF_ERROR,r,t,n)},validation:(e,t,n)=>{let r=`[Validation Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return N(E.VALIDATION_ERROR,r,t,n)},initialization:(e,t,n)=>{let r=`[Initialization Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return N(E.INITIALIZATION_ERROR,r,t,n)},timeout:(e,t,n)=>{let r=`[Timeout Error] ${e}\nContext: ${JSON.stringify(t,null,2)}`;return N(E.TIMEOUT_ERROR,r,t,n)},circularReference:(e,t,n)=>N(E.CIRCULAR_REFERENCE_ERROR,e,t,n)};function I(){let e=Object.values(E).reduce((e,t)=>(e[t]=0,e),{});A.forEach(t=>{e[t.error.type]+=t.count});let t=Array.from(j.entries()).map(([e,t])=>({signature:e,count:t.count,lastOccurred:t.lastOccurred})).sort((e,t)=>t.count-e.count).slice(0,10),n=A.slice(-10).map(e=>e.error);return{totalErrors:A.reduce((e,t)=>e+t.count,0),errorsByType:e,mostFrequentErrors:t,recentErrors:n}}export{D as ContextActionError,E as ContextActionErrorType,F as ErrorHandlers,h as ImmerUtils,T as compareValues,c as deepClone,l as deepCloneWithImmer,I as getErrorStatistics,x as getGlobalComparisonOptions,N as handleError,g as preloadImmer,_ as produce,p as safeGet,m as safeSet,b as setGlobalComparisonOptions}; |
| import{ErrorHandlers as e}from"./error-handling-CWVo5dVS.js";import t,{useEffect as n,useRef as r}from"react";function i(e){return typeof e==`object`&&!!e&&`subscribe`in e&&`getSnapshot`in e&&`setValue`in e&&`getValue`in e&&`name`in e&&typeof e.subscribe==`function`&&typeof e.getSnapshot==`function`&&typeof e.setValue==`function`&&typeof e.getValue==`function`&&typeof e.name==`string`}function a(e){return e!==void 0}function o(e){return{...e,validateValue:e.validateValue||a}}function s(e){if(!(!e||!i(e)))try{return e.getValue()}catch{return}}function c(e){let t={};for(let[n,r]of Object.entries(e)){let e=s(r);e!==void 0&&(t[n]=e)}return t}function l(e){return(t,n)=>{try{return e?e(t,n):Object.is(t,n)}catch{return Object.is(t,n)}}}const u={validateStoreConfig(e){return typeof e==`object`&&!!e&&typeof e.name==`string`&&e.name.length>0&&`initialValue`in e},validateStore(e){return i(e)},getSafeValue(e,t){return e??t}};function d(...e){return({children:n})=>e.reduceRight((e,n)=>t.createElement(n,null,e),n)}var f=class{constructor(){this.subscriptions=new Map,this.subscriptionCounter=0,this.isDisposed=!1}add(e,t=`unknown`){if(this.isDisposed)throw Error(`SubscriptionManager has been disposed`);let n=`sub_${++this.subscriptionCounter}_${Date.now()}`,r={unsubscribe:e,storeName:t,createdAt:Date.now(),isActive:!0};return this.subscriptions.set(n,r),n}addStoreSubscription(t,n){try{let e=t.subscribe(n);return this.add(e,t.name)}catch(n){throw e.store(`Failed to create store subscription`,{storeName:t.name},n instanceof Error?n:void 0),n}}remove(t){let n=this.subscriptions.get(t);if(!n)return!1;if(n.isActive)try{n.unsubscribe(),n.isActive=!1}catch(r){e.store(`Error during subscription cleanup`,{subscriptionId:t,storeName:n.storeName},r instanceof Error?r:void 0)}return this.subscriptions.delete(t),!0}cleanupAll(){Array.from(this.subscriptions.keys()).forEach(e=>{this.remove(e)})}getStats(){let e=Date.now(),t=Array.from(this.subscriptions.values()).filter(e=>e.isActive),n={},r=0,i=e;return t.forEach(t=>{n[t.storeName]=(n[t.storeName]||0)+1;let a=e-t.createdAt;r+=a,i=Math.min(i,t.createdAt)}),{totalSubscriptions:this.subscriptions.size,activeSubscriptions:t.length,averageAge:t.length>0?r/t.length:0,oldestSubscription:t.length>0?e-i:0,subscriptionsByStore:n}}dispose(){this.isDisposed||=(this.cleanupAll(),this.subscriptions.clear(),!0)}isManagerDisposed(){return this.isDisposed}};function p(){let e=r(null);return e.current||=new f,n(()=>()=>{e.current&&=(e.current.dispose(),null)},[]),e.current}export{f as SubscriptionManager,u as TypeUtils,d as composeProviders,l as createSafeEqualityFn,o as createStoreConfig,s as extractStoreValue,c as extractStoreValues,i as isStore,a as isValidStoreValue,p as useSubscriptionManager}; |
| import { ErrorHandlers } from "./error-handling-BigSDMxi.cjs"; | ||
| 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" && typeof config.name === "string" && config.name.length > 0 && "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; | ||
| } | ||
| //#endregion | ||
| export { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager }; |
| const e=require(`./error-handling-C48VsCLN.cjs`);let t=require(`react`);t=e.__toESM(t);function n(e){return typeof e==`object`&&!!e&&`subscribe`in e&&`getSnapshot`in e&&`setValue`in e&&`getValue`in e&&`name`in e&&typeof e.subscribe==`function`&&typeof e.getSnapshot==`function`&&typeof e.setValue==`function`&&typeof e.getValue==`function`&&typeof e.name==`string`}function r(e){return e!==void 0}function i(e){return{...e,validateValue:e.validateValue||r}}function a(e){if(!(!e||!n(e)))try{return e.getValue()}catch{return}}function o(e){let t={};for(let[n,r]of Object.entries(e)){let e=a(r);e!==void 0&&(t[n]=e)}return t}function s(e){return(t,n)=>{try{return e?e(t,n):Object.is(t,n)}catch{return Object.is(t,n)}}}const c={validateStoreConfig(e){return typeof e==`object`&&!!e&&typeof e.name==`string`&&e.name.length>0&&`initialValue`in e},validateStore(e){return n(e)},getSafeValue(e,t){return e??t}};function l(...e){return({children:n})=>e.reduceRight((e,n)=>t.default.createElement(n,null,e),n)}var u=class{constructor(){this.subscriptions=new Map,this.subscriptionCounter=0,this.isDisposed=!1}add(e,t=`unknown`){if(this.isDisposed)throw Error(`SubscriptionManager has been disposed`);let n=`sub_${++this.subscriptionCounter}_${Date.now()}`,r={unsubscribe:e,storeName:t,createdAt:Date.now(),isActive:!0};return this.subscriptions.set(n,r),n}addStoreSubscription(t,n){try{let e=t.subscribe(n);return this.add(e,t.name)}catch(n){throw e.ErrorHandlers.store(`Failed to create store subscription`,{storeName:t.name},n instanceof Error?n:void 0),n}}remove(t){let n=this.subscriptions.get(t);if(!n)return!1;if(n.isActive)try{n.unsubscribe(),n.isActive=!1}catch(r){e.ErrorHandlers.store(`Error during subscription cleanup`,{subscriptionId:t,storeName:n.storeName},r instanceof Error?r:void 0)}return this.subscriptions.delete(t),!0}cleanupAll(){Array.from(this.subscriptions.keys()).forEach(e=>{this.remove(e)})}getStats(){let e=Date.now(),t=Array.from(this.subscriptions.values()).filter(e=>e.isActive),n={},r=0,i=e;return t.forEach(t=>{n[t.storeName]=(n[t.storeName]||0)+1;let a=e-t.createdAt;r+=a,i=Math.min(i,t.createdAt)}),{totalSubscriptions:this.subscriptions.size,activeSubscriptions:t.length,averageAge:t.length>0?r/t.length:0,oldestSubscription:t.length>0?e-i:0,subscriptionsByStore:n}}dispose(){this.isDisposed||=(this.cleanupAll(),this.subscriptions.clear(),!0)}isManagerDisposed(){return this.isDisposed}};function d(){let e=(0,t.useRef)(null);return e.current||=new u,(0,t.useEffect)(()=>()=>{e.current&&=(e.current.dispose(),null)},[]),e.current}Object.defineProperty(exports,`SubscriptionManager`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`TypeUtils`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`composeProviders`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`createSafeEqualityFn`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`createStoreConfig`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`extractStoreValue`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`extractStoreValues`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`isStore`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`isValidStoreValue`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`useSubscriptionManager`,{enumerable:!0,get:function(){return d}}); |
-201
| Apache License | ||
| Version 2.0, January 2004 | ||
| http://www.apache.org/licenses/ | ||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||
| 1. Definitions. | ||
| "License" shall mean the terms and conditions for use, reproduction, | ||
| and distribution as defined by Sections 1 through 9 of this document. | ||
| "Licensor" shall mean the copyright owner or entity authorized by | ||
| the copyright owner that is granting the License. | ||
| "Legal Entity" shall mean the union of the acting entity and all | ||
| other entities that control, are controlled by, or are under common | ||
| control with that entity. For the purposes of this definition, | ||
| "control" means (i) the power, direct or indirect, to cause the | ||
| direction or management of such entity, whether by contract or | ||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||
| "You" (or "Your") shall mean an individual or Legal Entity | ||
| exercising permissions granted by this License. | ||
| "Source" form shall mean the preferred form for making modifications, | ||
| including but not limited to software source code, documentation | ||
| source, and configuration files. | ||
| "Object" form shall mean any form resulting from mechanical | ||
| transformation or translation of a Source form, including but | ||
| not limited to compiled object code, generated documentation, | ||
| and conversions to other media types. | ||
| "Work" shall mean the work of authorship, whether in Source or | ||
| Object form, made available under the License, as indicated by a | ||
| copyright notice that is included in or attached to the work | ||
| (an example is provided in the Appendix below). | ||
| "Derivative Works" shall mean any work, whether in Source or Object | ||
| form, that is based on (or derived from) the Work and for which the | ||
| editorial revisions, annotations, elaborations, or other modifications | ||
| represent, as a whole, an original work of authorship. For the purposes | ||
| of this License, Derivative Works shall not include works that remain | ||
| separable from, or merely link (or bind by name) to the interfaces of, | ||
| the Work and Derivative Works thereof. | ||
| "Contribution" shall mean any work of authorship, including | ||
| the original version of the Work and any modifications or additions | ||
| to that Work or Derivative Works thereof, that is intentionally | ||
| submitted to Licensor for inclusion in the Work by the copyright owner | ||
| or by an individual or Legal Entity authorized to submit on behalf of | ||
| the copyright owner. For the purposes of this definition, "submitted" | ||
| means any form of electronic, verbal, or written communication sent | ||
| to the Licensor or its representatives, including but not limited to | ||
| communication on electronic mailing lists, source code control systems, | ||
| and issue tracking systems that are managed by, or on behalf of, the | ||
| Licensor for the purpose of discussing and improving the Work, but | ||
| excluding communication that is conspicuously marked or otherwise | ||
| designated in writing by the copyright owner as "Not a Contribution." | ||
| "Contributor" shall mean Licensor and any individual or Legal Entity | ||
| on behalf of whom a Contribution has been received by Licensor and | ||
| subsequently incorporated within the Work. | ||
| 2. Grant of Copyright License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| copyright license to reproduce, prepare Derivative Works of, | ||
| publicly display, publicly perform, sublicense, and distribute the | ||
| Work and such Derivative Works in Source or Object form. | ||
| 3. Grant of Patent License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| (except as stated in this section) patent license to make, have made, | ||
| use, offer to sell, sell, import, and otherwise transfer the Work, | ||
| where such license applies only to those patent claims licensable | ||
| by such Contributor that are necessarily infringed by their | ||
| Contribution(s) alone or by combination of their Contribution(s) | ||
| with the Work to which such Contribution(s) was submitted. If You | ||
| institute patent litigation against any entity (including a | ||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | ||
| or a Contribution incorporated within the Work constitutes direct | ||
| or contributory patent infringement, then any patent licenses | ||
| granted to You under this License for that Work shall terminate | ||
| as of the date such litigation is filed. | ||
| 4. Redistribution. You may reproduce and distribute copies of the | ||
| Work or Derivative Works thereof in any medium, with or without | ||
| modifications, and in Source or Object form, provided that You | ||
| meet the following conditions: | ||
| (a) You must give any other recipients of the Work or | ||
| Derivative Works a copy of this License; and | ||
| (b) You must cause any modified files to carry prominent notices | ||
| stating that You changed the files; and | ||
| (c) You must retain, in the Source form of any Derivative Works | ||
| that You distribute, all copyright, patent, trademark, and | ||
| attribution notices from the Source form of the Work, | ||
| excluding those notices that do not pertain to any part of | ||
| the Derivative Works; and | ||
| (d) If the Work includes a "NOTICE" text file as part of its | ||
| distribution, then any Derivative Works that You distribute must | ||
| include a readable copy of the attribution notices contained | ||
| within such NOTICE file, excluding those notices that do not | ||
| pertain to any part of the Derivative Works, in at least one | ||
| of the following places: within a NOTICE text file distributed | ||
| as part of the Derivative Works; within the Source form or | ||
| documentation, if provided along with the Derivative Works; or, | ||
| within a display generated by the Derivative Works, if and | ||
| wherever such third-party notices normally appear. The contents | ||
| of the NOTICE file are for informational purposes only and | ||
| do not modify the License. You may add Your own attribution | ||
| notices within Derivative Works that You distribute, alongside | ||
| or as an addendum to the NOTICE text from the Work, provided | ||
| that such additional attribution notices cannot be construed | ||
| as modifying the License. | ||
| You may add Your own copyright statement to Your modifications and | ||
| may provide additional or different license terms and conditions | ||
| for use, reproduction, or distribution of Your modifications, or | ||
| for any such Derivative Works as a whole, provided Your use, | ||
| reproduction, and distribution of the Work otherwise complies with | ||
| the conditions stated in this License. | ||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | ||
| any Contribution intentionally submitted for inclusion in the Work | ||
| by You to the Licensor shall be under the terms and conditions of | ||
| this License, without any additional terms or conditions. | ||
| Notwithstanding the above, nothing herein shall supersede or modify | ||
| the terms of any separate license agreement you may have executed | ||
| with Licensor regarding such Contributions. | ||
| 6. Trademarks. This License does not grant permission to use the trade | ||
| names, trademarks, service marks, or product names of the Licensor, | ||
| except as required for reasonable and customary use in describing the | ||
| origin of the Work and reproducing the content of the NOTICE file. | ||
| 7. Disclaimer of Warranty. Unless required by applicable law or | ||
| agreed to in writing, Licensor provides the Work (and each | ||
| Contributor provides its Contributions) on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
| implied, including, without limitation, any warranties or conditions | ||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||
| PARTICULAR PURPOSE. You are solely responsible for determining the | ||
| appropriateness of using or redistributing the Work and assume any | ||
| risks associated with Your exercise of permissions under this License. | ||
| 8. Limitation of Liability. In no event and under no legal theory, | ||
| whether in tort (including negligence), contract, or otherwise, | ||
| unless required by applicable law (such as deliberate and grossly | ||
| negligent acts) or agreed to in writing, shall any Contributor be | ||
| liable to You for damages, including any direct, indirect, special, | ||
| incidental, or consequential damages of any character arising as a | ||
| result of this License or out of the use or inability to use the | ||
| Work (including but not limited to damages for loss of goodwill, | ||
| work stoppage, computer failure or malfunction, or any and all | ||
| other commercial damages or losses), even if such Contributor | ||
| has been advised of the possibility of such damages. | ||
| 9. Accepting Warranty or Additional Liability. While redistributing | ||
| the Work or Derivative Works thereof, You may choose to offer, | ||
| and charge a fee for, acceptance of support, warranty, indemnity, | ||
| or other liability obligations and/or rights consistent with this | ||
| License. However, in accepting such obligations, You may act only | ||
| on Your own behalf and on Your sole responsibility, not on behalf | ||
| of any other Contributor, and only if You agree to indemnify, | ||
| defend, and hold each Contributor harmless for any liability | ||
| incurred by, or claims asserted against, such Contributor by reason | ||
| of your accepting any such warranty or additional liability. | ||
| END OF TERMS AND CONDITIONS | ||
| APPENDIX: How to apply the Apache License to your work. | ||
| To apply the Apache License to your work, attach the following | ||
| boilerplate notice, with the fields enclosed by brackets "[]" | ||
| replaced with your own identifying information. (Don't include | ||
| the brackets!) The text should be enclosed in the appropriate | ||
| comment syntax for the file format. We also recommend that a | ||
| file or class name and description of purpose be included on the | ||
| same "printed page" as the copyright notice for easier | ||
| identification within third-party archives. | ||
| Copyright 2024 Jun Woo Bang | ||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. |
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
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
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
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances 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 2 instances in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
573953
88.69%41
127.78%7262
52.08%3
-70%34
112.5%- Removed