New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@context-action/react

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@context-action/react - npm Package Compare versions

Comparing version
0.8.3
to
0.8.4
+1489
dist/ActionContext-Bbkccg3d.cjs
const require_error_handling = require('./error-handling-ibCwx4ki.cjs');
let react = require("react");
react = require_error_handling.__toESM(react);
let react_jsx_runtime = require("react/jsx-runtime");
react_jsx_runtime = require_error_handling.__toESM(react_jsx_runtime);
let __context_action_core = require("@context-action/core");
__context_action_core = require_error_handling.__toESM(__context_action_core);
//#region src/stores/core/StoreRegistry.ts
/**
* Centralized store registry for managing multiple Store instances
*/
var StoreRegistry = class {
constructor(name = "default") {
this.stores = /* @__PURE__ */ new Map();
this.metadata = /* @__PURE__ */ new WeakMap();
this.listeners = /* @__PURE__ */ new Set();
this._snapshot = [];
this.name = name;
}
/**
* Subscribe to registry changes for reactive updates
*/
subscribe(listener) {
this.listeners.add(listener);
return () => {
this.listeners.delete(listener);
};
}
/**
* Register a new store in the registry
*/
register(name, store, metadata) {
if (this.stores.has(name)) {
if (this.stores.get(name)) {}
}
this.stores.set(name, store);
if (metadata) this.metadata.set(store, {
registeredAt: Date.now(),
name,
...metadata
});
this._updateSnapshot();
this._notifyListeners();
}
/**
* Unregister a store from the registry
*/
unregister(name) {
if (!this.stores.get(name)) return false;
this.stores.delete(name);
this._updateSnapshot();
this._notifyListeners();
return true;
}
/**
* Get a store by name
*/
getStore(name) {
return this.stores.get(name);
}
/**
* Check if a store exists
*/
hasStore(name) {
return this.stores.has(name);
}
/**
* Get all registered store names
*/
getStoreNames() {
return Array.from(this.stores.keys());
}
/**
* Get all stores as entries
*/
getAllStores() {
return new Map(this.stores);
}
/**
* Get store metadata
*/
getStoreMetadata(nameOrStore) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
return store ? this.metadata.get(store) : void 0;
}
/**
* Update store metadata
*/
updateStoreMetadata(nameOrStore, metadata) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
if (!store) return false;
const currentMetadata = this.metadata.get(store);
this.metadata.set(store, {
registeredAt: Date.now(),
name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown",
...currentMetadata,
...metadata
});
return true;
}
/**
* Get registry snapshot for React integration
*/
getSnapshot() {
return this._snapshot;
}
/**
* Clear all stores from registry
*/
clear() {
this.stores.clear();
this._updateSnapshot();
this._notifyListeners();
}
/**
* Dispose registry and cleanup resources
*/
dispose() {
this.clear();
this.listeners.clear();
}
/**
* Get count of registered stores
*/
getStoreCount() {
return this.stores.size;
}
/**
* Iterate over all stores
*/
forEach(callback) {
this.stores.forEach((store, name) => {
callback(store, name);
});
}
/**
* Get registry statistics
*/
getStats() {
return {
totalStores: this.stores.size,
storeNames: this.getStoreNames(),
registryName: this.name
};
}
/**
* Update internal snapshot
*/
_updateSnapshot() {
this._snapshot = Array.from(this.stores.entries());
}
/**
* Notify all listeners of registry changes
*/
_notifyListeners() {
this.listeners.forEach((listener) => {
try {
listener();
} catch (error) {
console.error("Error in registry listener:", error);
}
});
}
};
/**
* Global default registry instance
*/
const globalStoreRegistry = new StoreRegistry("global");
//#endregion
//#region src/stores/utils/type-guards.ts
function isRefState(value) {
return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean";
}
/**
* DOM Event 객체인지 확인하는 타입 가드
*/
function isDOMEvent(value) {
return value instanceof Event;
}
/**
* Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체)
*/
function isEventLike(value) {
return typeof value === "object" && value !== null && typeof value.preventDefault === "function";
}
/**
* target 프로퍼티를 가진 객체인지 확인하는 타입 가드
*/
function hasTargetProperty(value) {
return typeof value === "object" && value !== null && "target" in value;
}
/**
* DOM Element인지 확인하는 타입 가드
*/
function isDOMElement(value) {
return value instanceof Element;
}
/**
* 객체인지 확인하는 타입 가드 (null 제외)
*/
function isObject(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
/**
* 복합 타입 가드: Event 객체로 의심되는 객체인지 확인
* RefState가 아니면서 Event 관련 속성을 가진 객체를 감지
*/
function isSuspiciousEventObject(value, checkNested = true) {
if (!isObject(value) || isRefState(value)) return false;
if (isEventLikeObject(value)) return true;
if (checkNested) {
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const nestedValue = value[key];
if (isEventLikeObject(nestedValue)) return true;
}
}
return false;
}
/**
* 단일 객체가 이벤트와 같은지 확인
*/
function isEventLikeObject(value) {
if (!isObject(value)) return false;
const hasEventTarget = hasTargetProperty(value);
const hasPreventDefault = isEventLike(value);
const isEvent = isDOMEvent(value);
const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault);
const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value;
const constructorName = value?.constructor?.name;
const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false;
return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor;
}
/**
* 문제가 될 수 있는 속성들을 찾아내는 함수
*/
function findProblematicProperties(value) {
if (!isObject(value)) return [];
const problematicKeys = [];
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const prop = value[key];
if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key);
}
return problematicKeys;
}
/**
* 통합 타입 가드 객체
* 모든 타입 가드 함수들을 하나의 객체로 export
*/
const TypeGuards = {
isRefState,
isDOMEvent,
isEventLike,
hasTargetProperty,
isDOMElement,
isObject,
isSuspiciousEventObject,
findProblematicProperties
};
//#endregion
//#region src/stores/core/Store.ts
/**
* Core Store class for centralized state management with memory leak prevention
*
* Provides reactive state management with subscription capabilities, optimized for
* React integration through useSyncExternalStore. Features advanced cleanup mechanisms,
* automatic resource management, and comprehensive memory leak prevention.
*
* Key Features:
* - Automatic cleanup task registration and execution
* - Memory leak prevention with disposal patterns
* - Race condition protection for async operations
* - Advanced error recovery with exponential backoff
* - Resource monitoring and threshold management
*
* @template T - The type of value stored in this store
*
* @example
* ```typescript
* const userStore = createStore('user', { name: '', age: 0 });
*
* // Register cleanup tasks
* const unregister = userStore.registerCleanup(() => {
* console.log('Cleaning up user store resources');
* });
*
* // Automatic cleanup on disposal
* userStore.dispose();
* ```
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
* @public
*/
var Store = class {
constructor(name, initialValue) {
this.listeners = /* @__PURE__ */ new Set();
this._lastClonedValue = null;
this._lastClonedVersion = 0;
this._version = 0;
this.isUpdating = false;
this.updateQueue = [];
this.notificationMode = "batched";
this.pendingNotification = false;
this.animationFrameId = null;
this.pendingUpdatesCount = 0;
this.cleanupTasks = /* @__PURE__ */ new Set();
this.isDisposed = false;
this.errorCount = 0;
this.lastErrorTime = 0;
this.MAX_ERROR_COUNT = 5;
this.ERROR_RESET_TIME = 6e4;
this.subscriptionRegistry = /* @__PURE__ */ new WeakMap();
this.cloningEnabled = true;
this.subscribe = (listener) => {
if (this.isDisposed) {
console.warn(`Cannot subscribe to disposed store "${this.name}"`);
return () => {};
}
const enhancedListener = () => {
if (this.isDisposed) return;
try {
listener();
if (this.errorCount > 0) this.errorCount = 0;
} catch (error) {
this._handleListenerError(error, listener);
}
};
this.subscriptionRegistry.set(listener, {
subscribedAt: Date.now(),
errorCount: 0,
enhancedListener
});
this.listeners.add(enhancedListener);
return () => {
this.listeners.delete(enhancedListener);
this.subscriptionRegistry.delete(listener);
};
};
this.getSnapshot = () => {
return this._snapshot;
};
this.name = name;
this._value = initialValue;
this._snapshot = this._createSnapshot();
}
/**
* 현재 값 직접 가져오기 (액션 핸들러용)
* 핵심 로직: 불변성을 보장하는 깊은 복사본 반환
*
* @implements lazy-evaluation
* @implements store-immutability
* @memberof architecture-terms
*
* 사용 시나리오: Action handler에서 최신 상태 읽기
* 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨
*/
getValue() {
if (typeof this._value !== "object" || this._value === null) return this._value;
if (this.cloningEnabled) {
if (this._lastClonedVersion === this._version && this._lastClonedValue !== null) return this._lastClonedValue;
this._lastClonedValue = require_error_handling.safeGet(this._value, this.cloningEnabled);
this._lastClonedVersion = this._version;
return this._lastClonedValue;
}
return this._value;
}
/**
* Store 값 설정 및 구독자 알림
* 핵심 로직:
* 1. 입력값의 불변성 보장을 위한 깊은 복사 (선택적 skip 가능)
* 2. 강화된 값 비교 시스템으로 불필요한 리렌더링 방지
* 3. Structural sharing을 통한 성능 최적화
* 4. 값 변경 시에만 스냅샷 재생성 및 알림
*
* @implements unidirectional-data-flow
* @implements store-immutability
* @memberof architecture-terms
*
* 보안 강화: 입력값을 복사하여 Store 내부 상태가 외부 참조에 의해 변경되지 않도록 보호
* 성능 강화: 다층 비교 시스템으로 정확한 변경 감지 및 렌더링 최적화
*/
setValue(value, options) {
if (TypeGuards.isObject(value)) {
if (!TypeGuards.isRefState(value) && TypeGuards.isSuspiciousEventObject(value)) {
const eventHandling = options?.eventHandling || "block";
const hasEventTarget = TypeGuards.hasTargetProperty(value);
const hasPreventDefault = TypeGuards.isEventLike(value);
const isEvent = TypeGuards.isDOMEvent(value);
switch (eventHandling) {
case "allow": break;
case "transform":
if (options?.eventTransform) try {
value = options.eventTransform(value);
} catch (error) {
require_error_handling.ErrorHandlers.store("Event transformation failed in Store.setValue", {
storeName: this.name,
valueType: typeof value,
error: error instanceof Error ? error.message : String(error)
});
return;
}
else {
require_error_handling.ErrorHandlers.store("Event transformation requested but no transform function provided", {
storeName: this.name,
valueType: typeof value
});
return;
}
break;
case "block":
default:
require_error_handling.ErrorHandlers.store("Event object detected in Store.setValue - this may cause memory leaks", {
storeName: this.name,
valueType: typeof value,
constructorName: value?.constructor?.name,
isEvent,
hasTargetProperty: hasEventTarget,
hasPreventDefault,
problematicProperties: TypeGuards.findProblematicProperties(value)
});
return;
}
}
}
const safeValue = options?.skipClone ? value : require_error_handling.safeSet(value, this.cloningEnabled);
let hasChanged = true;
if (!options?.skipComparison) hasChanged = this._compareValues(this._value, safeValue);
if (hasChanged) {
this._value = safeValue;
this._version++;
this._snapshot = this._createSnapshot();
this._scheduleNotification();
}
}
/**
* Update value using updater function with Immer integration
* 핵심 로직:
* 1. Immer produce를 사용하여 draft 객체 제공
* 2. updater 결과를 불변성을 보장하며 설정
*
* @implements store-immutability
* 보안 강화: Immer draft를 통한 안전한 상태 수정
*/
update(updater) {
if (this.isUpdating) {
this.updateQueue.push(() => this.update(updater));
return;
}
try {
this.isUpdating = true;
let updatedValue;
try {
updatedValue = require_error_handling.produce(this._value, (draft) => {
const result = updater(draft);
return result !== void 0 ? result : draft;
});
} catch (immerError) {
if (process.env.NODE_ENV === "development") console.warn("[Store] Immer update failed, falling back to safe copy method", immerError);
const safeCurrentValue = require_error_handling.safeGet(this._value, this.cloningEnabled);
try {
updatedValue = require_error_handling.produce(safeCurrentValue, (draft) => {
const result = updater(draft);
return result !== void 0 ? result : draft;
});
} catch (secondImmerError) {
if (process.env.NODE_ENV === "development") console.warn("[Store] Immer completely failed, using direct update (immutability not guaranteed)", secondImmerError);
updatedValue = updater(safeCurrentValue);
}
}
if (TypeGuards.isObject(updatedValue)) {
if (!TypeGuards.isRefState(updatedValue) && TypeGuards.isSuspiciousEventObject(updatedValue)) {
const hasEventTarget = TypeGuards.hasTargetProperty(updatedValue);
const hasPreventDefault = TypeGuards.isEventLike(updatedValue);
const isEvent = TypeGuards.isDOMEvent(updatedValue);
require_error_handling.ErrorHandlers.store("Event object detected in Store.update result - this may cause memory leaks", {
storeName: this.name,
updatedValueType: typeof updatedValue,
constructorName: updatedValue?.constructor?.name,
isEvent,
hasTargetProperty: hasEventTarget,
hasPreventDefault,
problematicProperties: TypeGuards.findProblematicProperties(updatedValue)
});
return;
}
}
this.setValue(updatedValue);
} finally {
this.isUpdating = false;
if (this.updateQueue.length > 0) {
const nextUpdate = this.updateQueue.shift();
if (nextUpdate) Promise.resolve().then(nextUpdate);
}
}
}
/**
* Get number of active listeners
*/
getListenerCount() {
return this.listeners.size;
}
/**
* Clear all listeners
*/
clearListeners() {
this.listeners.clear();
}
/**
* Register cleanup task for automatic execution on disposal
*
* Registers a cleanup function that will be automatically called when the store
* is disposed. This prevents memory leaks and ensures proper resource cleanup.
*
* @param task - Cleanup function to register
* @returns Unregister function to remove the cleanup task
*
* @example
* ```typescript
* const timer = setInterval(() => {}, 1000);
* const unregister = store.registerCleanup(() => clearInterval(timer));
*
* // Later, remove the cleanup task if needed
* unregister();
* ```
*/
registerCleanup(task) {
if (this.isDisposed) {
console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`);
return () => {};
}
this.cleanupTasks.add(task);
return () => this.cleanupTasks.delete(task);
}
/**
* Enhanced Store disposal with comprehensive cleanup
*
* Performs complete cleanup of all store resources including listeners,
* timers, cleanup tasks, and internal state. Prevents memory leaks and
* ensures proper resource disposal.
*
* @example
* ```typescript
* // Manual disposal
* store.dispose();
*
* // Auto-disposal with useEffect
* useEffect(() => {
* return () => store.dispose();
* }, [store]);
* ```
*/
dispose() {
if (this.isDisposed) return;
this.isDisposed = true;
try {
this.cleanupTasks.forEach((task) => {
try {
task();
} catch (error) {
require_error_handling.ErrorHandlers.store("Error during cleanup task execution", { storeName: this.name }, error instanceof Error ? error : void 0);
}
});
this.cleanupTasks.clear();
this.subscriptionRegistry = /* @__PURE__ */ new WeakMap();
this.clearListeners();
if (this.animationFrameId !== null) {
cancelAnimationFrame(this.animationFrameId);
this.animationFrameId = null;
}
this.pendingNotification = false;
this.updateQueue.length = 0;
} catch (error) {
require_error_handling.ErrorHandlers.store("Critical error during store disposal", { storeName: this.name }, error instanceof Error ? error : void 0);
}
}
/**
* Check if store is disposed
* @returns true if store has been disposed
*/
isStoreDisposed() {
return this.isDisposed;
}
/**
* Store별 커스텀 비교 함수 설정
* 이 Store에만 적용되는 특별한 비교 로직 설정
*
* @param comparator - 커스텀 비교 함수 (oldValue, newValue) => boolean
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config
*/
setCustomComparator(comparator) {
this.customComparator = comparator;
}
/**
* Store별 비교 옵션 설정
* 이 Store에만 적용되는 비교 전략 설정
*
* @param options - 비교 옵션
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config
*/
setComparisonOptions(options) {
this.comparisonOptions = options;
}
/**
* 성능 최적화: Store별 복사 동작 제어
*
* @param enabled - true: 복사 활성화 (안전), false: 복사 비활성화 (성능 우선)
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/performance
*/
setCloningEnabled(enabled) {
this.cloningEnabled = enabled;
}
/**
* 현재 복사 설정 조회
*/
isCloningEnabled() {
return this.cloningEnabled;
}
/**
* 강화된 값 비교 시스템
* 1. 커스텀 비교 함수 우선 사용
* 2. Store별 비교 옵션 적용
* 3. 성능 최적화된 빠른 비교 fallback
* 4. 전역 비교 설정 사용
*
* @param oldValue - 이전 값
* @param newValue - 새로운 값
* @returns true if values are different (change detected), false if same
* @protected
*/
_compareValues(oldValue, newValue) {
let result;
try {
if (this.customComparator) result = !this.customComparator(oldValue, newValue);
else if (this.comparisonOptions) result = !require_error_handling.compareValues(oldValue, newValue, this.comparisonOptions);
else result = !require_error_handling.compareValues(oldValue, newValue, { strategy: "reference" });
} catch (error) {
require_error_handling.ErrorHandlers.store("Error during value comparison, falling back to reference comparison", { storeName: this.name }, error instanceof Error ? error : void 0);
result = !Object.is(oldValue, newValue);
}
return result;
}
_createSnapshot() {
return {
value: require_error_handling.safeGet(this._value, this.cloningEnabled),
name: this.name,
lastUpdate: Date.now()
};
}
/**
* requestAnimationFrame 기반 알림 스케줄링
* 브라우저의 다음 프레임에서 리스너 알림 실행
*/
_scheduleNotification() {
if (this.notificationMode === "immediate") this._notifyListeners();
else this._scheduleWithRAF();
}
/**
* requestAnimationFrame을 사용한 알림 스케줄링
* 누적 가능한 배치 시스템으로 개선
*/
_scheduleWithRAF() {
this.pendingUpdatesCount++;
if (!this.pendingNotification) {
this.pendingNotification = true;
this.animationFrameId = requestAnimationFrame(() => {
this._executeNotification();
});
}
}
/**
* 스케줄된 알림 실행
*/
_executeNotification() {
this.pendingNotification = false;
this.animationFrameId = null;
const batchedUpdates = this.pendingUpdatesCount;
this.pendingUpdatesCount = 0;
this._notifyListeners();
if (process.env.NODE_ENV === "development" && batchedUpdates > 1) console.debug(`[Store:${this.name}] Batched ${batchedUpdates} updates in single frame`);
}
/**
* Handle listener execution errors with recovery strategies
*/
_handleListenerError(error, listener) {
const now = Date.now();
if (now - this.lastErrorTime > this.ERROR_RESET_TIME) this.errorCount = 0;
this.errorCount++;
this.lastErrorTime = now;
const metadata = this.subscriptionRegistry.get(listener);
if (metadata) metadata.errorCount++;
require_error_handling.ErrorHandlers.store("Error in store listener execution", {
storeName: this.name,
listenerCount: this.listeners.size,
errorCount: this.errorCount,
subscriptionAge: metadata ? now - metadata.subscribedAt : "unknown"
}, error instanceof Error ? error : void 0);
if (metadata && metadata.errorCount >= 3) {
console.warn(`Removing problematic listener from store "${this.name}" after ${metadata.errorCount} errors`);
this.listeners.delete(metadata.enhancedListener);
this.subscriptionRegistry.delete(listener);
}
if (this.errorCount >= this.MAX_ERROR_COUNT) {
console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`);
this.clearListeners();
}
}
_notifyListeners() {
if (this.isDisposed) return;
this.listeners.forEach((listener) => {
if (this.isDisposed) return;
listener();
});
}
};
/**
* Factory function for creating type-safe Store instances
*
* Creates a new Store instance with the specified name and initial value.
* Provides type safety and integrates seamlessly with React hooks and
* the Context-Action framework patterns.
*
* @template T - The type of values stored in this store
*
* @param name - Unique identifier for the store (used for debugging)
* @param initialValue - Initial value to store
*
* @returns Configured Store instance ready for use
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
*
* @public
*/
function createStore(name, initialValue) {
return new Store(name, initialValue);
}
//#endregion
//#region src/stores/utils/sync-external-store-utils.ts
/**
* 향상된 구독 함수 생성 (내부 사용)
* 디바운싱, 스로틀링, 조건부 구독 기능 제공
*/
function createEnhancedSubscriber(store, options = {}) {
const { debounce, throttle, condition, debug, name = "unknown" } = options;
return (callback) => {
if (!store) return () => {};
let debounceTimer = null;
let throttleTimer = null;
let lastThrottleTime = 0;
const enhancedCallback = () => {
if (condition && !condition()) {
if (debug) console.debug(`[${name}] Subscription suspended due to condition`);
return;
}
const now = performance.now();
if (throttle && throttle > 0) {
if (now - lastThrottleTime < throttle) {
if (throttleTimer) clearTimeout(throttleTimer);
throttleTimer = setTimeout(() => {
lastThrottleTime = performance.now();
callback();
}, throttle - (now - lastThrottleTime));
return;
}
lastThrottleTime = now;
}
if (debounce && debounce > 0) {
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
callback();
if (debug) console.debug(`[${name}] Debounced callback executed after ${debounce}ms`);
}, debounce);
return;
}
callback();
};
const unsubscribe = store.subscribe(enhancedCallback);
return () => {
if (debounceTimer) clearTimeout(debounceTimer);
if (throttleTimer) clearTimeout(throttleTimer);
unsubscribe();
};
};
}
/**
* Null-safe Store 구독 훅
* useSyncExternalStore를 기반으로 한 안전한 구독
*/
function useSafeStoreSubscription(store, selector, options = {}) {
const { initialValue, equalityFn, debounce, throttle, condition, debug, name } = options;
const stableSubscriptionOptions = (0, react.useMemo)(() => ({
debounce,
throttle,
condition,
debug,
name
}), [
debounce,
throttle,
condition,
debug,
name
]);
const needsEnhancedSubscription = Boolean(debounce || throttle || condition);
const subscribe = (0, react.useCallback)((callback) => {
if (!store) return () => {};
if (needsEnhancedSubscription) return createEnhancedSubscriber(store, stableSubscriptionOptions)(callback);
return store.subscribe(callback);
}, [
store,
needsEnhancedSubscription,
stableSubscriptionOptions
]);
const getSnapshot = (0, react.useCallback)(() => {
if (!store) return initialValue;
const snapshot = store.getSnapshot();
return selector ? selector(snapshot.value) : snapshot.value;
}, [
store,
selector,
initialValue
]);
const cachedSnapshotRef = (0, react.useRef)();
const stableGetSnapshot = (0, react.useCallback)(() => {
const currentSnapshot = getSnapshot();
if (equalityFn && cachedSnapshotRef.current !== void 0) {
if (equalityFn(cachedSnapshotRef.current, currentSnapshot)) return cachedSnapshotRef.current;
}
cachedSnapshotRef.current = currentSnapshot;
return currentSnapshot;
}, [getSnapshot, equalityFn]);
const getServerSnapshot = (0, react.useCallback)(() => {
return initialValue;
}, [initialValue]);
return (0, react.useSyncExternalStore)(subscribe, equalityFn ? stableGetSnapshot : getSnapshot, getServerSnapshot);
}
/**
* 기본 동등성 비교 함수들
*/
const equalityFunctions = {
reference: (a, b) => Object.is(a, b),
shallow: (a, b) => {
if (Object.is(a, b)) return true;
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (const key of keysA) if (!Object.prototype.hasOwnProperty.call(b, key) || !Object.is(a[key], b[key])) return false;
return true;
},
deep: (a, b) => {
if (Object.is(a, b)) return true;
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
if (Array.isArray(a) !== Array.isArray(b)) return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (const key of keysA) {
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
if (!equalityFunctions.deep(a[key], b[key])) return false;
}
return true;
},
smart: (a, b) => {
if (Object.is(a, b)) return true;
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
return a.every((item, index) => {
const bItem = b[index];
if (typeof item === "object" && item !== null && typeof bItem === "object" && bItem !== null) return equalityFunctions.shallow(item, bItem);
return Object.is(item, bItem);
});
}
return equalityFunctions.shallow(a, b);
}
};
//#endregion
//#region src/stores/hooks/useStoreSelector.ts
const defaultEqualityFn = equalityFunctions.smart;
const shallowEqual = equalityFunctions.shallow;
const deepEqual = equalityFunctions.deep;
const smartEqual = equalityFunctions.smart;
/**
* Hook for selective store subscription with performance optimization
*
* Subscribes to specific parts of store data using a selector function,
* triggering re-renders only when the selected value actually changes.
* Essential for preventing unnecessary re-renders in complex applications.
*
* @template T - Type of the store value
* @template R - Type of the value returned by the selector
*
* @param store - Store instance to subscribe to
* @param selector - Function to extract needed data from store value
* @param equalityFn - Function to compare previous and new values (default: Object.is)
*
* @returns The value returned by the selector function
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usestoreselector-advanced-usage
*
* @public
*/
function useStoreSelector(store, selector, equalityFn = defaultEqualityFn) {
"use memo";
const stableSelector = (0, react.useCallback)(selector, [selector]);
const stableEqualityFn = (0, react.useCallback)(equalityFn, [equalityFn]);
const selectorWarningShownRef = (0, react.useRef)(false);
if (process.env.NODE_ENV === "development") {
if (selector !== stableSelector && !selectorWarningShownRef.current) {
console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name);
selectorWarningShownRef.current = true;
}
}
const previousValueRef = (0, react.useRef)();
const subscribe = (0, react.useCallback)((callback) => {
return store.subscribe(callback);
}, [store]);
const getSnapshot = (0, react.useCallback)(() => {
try {
const selectedValue = stableSelector(store.getValue());
if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current;
previousValueRef.current = selectedValue;
return selectedValue;
} catch (error) {
if (process.env.NODE_ENV === "development") console.error("useStoreSelector: Error in selector function:", error);
throw error;
}
}, [
store,
stableSelector,
stableEqualityFn
]);
return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
}
//#endregion
//#region src/stores/components/StoreErrorBoundary.tsx
/**
* Store 시스템을 위한 에러 경계 컴포넌트
*
* Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다.
* 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는
* 사용자 친화적인 메시지를 보여줍니다.
*/
var StoreErrorBoundary = class extends react.Component {
constructor(props) {
super(props);
this.resetTimeoutId = null;
this.resetErrorBoundary = () => {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
this.setState({
hasError: false,
error: null,
errorInfo: null,
errorId: null
});
};
this.state = {
hasError: false,
error: null,
errorInfo: null,
errorId: null
};
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error: error instanceof Error && error.name === "ContextActionError" ? error : null,
errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
};
}
componentDidCatch(error, errorInfo) {
if (error.name === "ContextActionError") {
const contextActionError = error;
this.setState({ errorInfo });
this.props.onError?.(contextActionError, errorInfo);
} else {
const contextActionError = require_error_handling.ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, {
component: "StoreErrorBoundary",
stack: error.stack,
componentStack: errorInfo.componentStack
}, error);
this.setState({
error: contextActionError,
errorInfo
});
this.props.onError?.(contextActionError, errorInfo);
}
}
componentDidUpdate(prevProps) {
const { hasError } = this.state;
const { resetOnPropsChange, resetKeys } = this.props;
if (hasError && resetOnPropsChange) {
if (resetKeys) {
if (resetKeys.some((key) => {
return prevProps[key] !== this.props[key];
})) this.resetErrorBoundary();
} else if (prevProps !== this.props) this.resetErrorBoundary();
}
}
componentWillUnmount() {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
}
render() {
const { hasError, error, errorInfo } = this.state;
const { children, fallback } = this.props;
if (hasError) {
if (fallback) {
if (typeof fallback === "function") return fallback(error, errorInfo);
return fallback;
}
return this.renderDefaultFallback();
}
return children;
}
renderDefaultFallback() {
if (process.env.NODE_ENV === "development") return this.renderDevelopmentFallback();
else return this.renderProductionFallback();
}
renderDevelopmentFallback() {
const { error, errorInfo, errorId } = this.state;
const stats = require_error_handling.getErrorStatistics();
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
padding: "20px",
margin: "20px",
border: "2px solid #ff6b6b",
borderRadius: "8px",
backgroundColor: "#ffe0e0",
fontFamily: "monospace"
},
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
style: {
color: "#d63031",
margin: "0 0 10px 0"
},
children: "🚨 Store Error Boundary"
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error ID:" }),
" ",
errorId
]
}),
error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Type:" }),
" ",
error.type,
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Message:" }),
" ",
error.message,
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Timestamp:" }),
" ",
new Date(error.timestamp).toISOString()
]
}),
error?.context && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Context:" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "12px"
},
children: JSON.stringify(error.context, null, 2)
})]
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Statistics:" }),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
"Total Errors: ",
stats.totalErrors,
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
"Recent Errors: ",
stats.recentErrors.length
]
}),
errorInfo && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
style: {
cursor: "pointer",
fontWeight: "bold"
},
children: "Component Stack"
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "11px",
whiteSpace: "pre-wrap"
},
children: errorInfo.componentStack
})]
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#00b894",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
fontWeight: "bold"
},
children: "Try Again"
})
]
});
}
renderProductionFallback() {
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
padding: "20px",
textAlign: "center",
backgroundColor: "#f8f9fa",
border: "1px solid #dee2e6",
borderRadius: "8px",
margin: "20px 0"
},
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
style: {
color: "#6c757d",
margin: "0 0 10px 0"
},
children: "Something went wrong"
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
style: {
color: "#6c757d",
margin: "0 0 15px 0"
},
children: "We're sorry, but something unexpected happened. Please try again."
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#007bff",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer"
},
children: "Try Again"
})
]
});
}
};
/**
* Enhanced HOC for automatic Store Error Boundary wrapping with security
*
* @template P - Component props type
* @param WrappedComponent - Component to wrap with error boundary
* @param errorBoundaryProps - Error boundary configuration
* @returns Enhanced component with comprehensive error handling
*/
function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) {
const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, {
...errorBoundaryProps,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WrappedComponent, { ...props })
});
WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`;
return WithStoreErrorBoundaryComponent;
}
/**
* 특정 Store와 연결된 에러 경계 생성 헬퍼
*/
function createStoreErrorBoundary(storeName, customFallback) {
return ({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, {
fallback: customFallback,
onError: (error, errorInfo) => {
console.group(`Store Error in ${storeName}`);
console.error("Error:", error);
console.error("Component Stack:", errorInfo.componentStack);
console.groupEnd();
},
resetKeys: [storeName],
children
});
}
//#endregion
//#region src/actions/ActionContext.tsx
function createActionContext(contextNameOrConfig = {}, config) {
let effectiveConfig;
let contextName;
if (typeof contextNameOrConfig === "string") {
contextName = contextNameOrConfig;
effectiveConfig = {
...config,
name: config?.name || contextName
};
} else {
effectiveConfig = contextNameOrConfig;
contextName = effectiveConfig.name || "ActionContext";
}
const FactoryActionContext = (0, react.createContext)(null);
const Provider = ({ children }) => {
const actionRegisterRef = (0, react.useRef)(new __context_action_core.ActionRegister(effectiveConfig));
const contextValue = (0, react.useMemo)(() => ({ actionRegisterRef }), []);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FactoryActionContext.Provider, {
value: contextValue,
children
});
};
const useFactoryActionContext = () => {
const context = (0, react.useContext)(FactoryActionContext);
if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider");
return context;
};
/**
* Optimized hook to get stable dispatch functions
*
* Returns stable dispatch functions that prevent re-renders and maintain
* reference equality across component renders.
*
* @returns Object with dispatch and dispatchWithResult functions
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useActionDispatcher = () => {
const { actionRegisterRef } = useFactoryActionContext();
return {
dispatch: (0, react.useCallback)((action, payload, options) => {
if (process.env.NODE_ENV === "development") console.log(`React dispatch called for '${String(action)}':`, {
hasPayload: payload !== void 0,
hasOptions: options !== void 0,
timestamp: (/* @__PURE__ */ new Date()).toISOString()
});
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up.");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatch(action, payload, dispatchOptions);
}, [actionRegisterRef]),
dispatchWithResult: (0, react.useCallback)((action, payload, options) => {
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatchWithResult(action, payload, dispatchOptions);
}, [actionRegisterRef])
};
};
const useAction = () => {
const { dispatch } = useActionDispatcher();
return dispatch;
};
const useActionHandler = (action, handler, config$1) => {
const { actionRegisterRef } = useFactoryActionContext();
const actionId = (0, react.useId)();
const handlerRef = (0, react.useRef)(handler);
handlerRef.current = handler;
const priority = config$1?.priority ?? 0;
const id = config$1?.id || `react_${String(action)}_${actionId}`;
const blocking = config$1?.blocking ?? false;
const once = config$1?.once ?? false;
const debounce = config$1?.debounce;
const throttle = config$1?.throttle;
const stableConfig = (0, react.useMemo)(() => ({
priority,
id,
blocking,
once,
replaceExisting: true,
...debounce !== void 0 && { debounce },
...throttle !== void 0 && { throttle }
}), [
priority,
id,
blocking,
once,
debounce,
throttle
]);
(0, react.useEffect)(() => {
const register = actionRegisterRef.current;
if (!register) return;
const wrapperHandler = (payload, controller) => {
return handlerRef.current(payload, controller);
};
if (process.env.NODE_ENV === "development") console.log(`Registering handler for '${String(action)}'`);
return register.register(action, wrapperHandler, stableConfig);
}, [
action,
actionRegisterRef,
stableConfig
]);
};
/**
* Hook that provides direct access to the ActionRegister instance
*
* This hook is useful when you need to:
* - Register multiple handlers dynamically
* - Access other ActionRegister methods like clearAction, getHandlers, etc.
* - Implement complex handler registration logic
* - Have more control over the registration lifecycle
*
* @returns ActionRegister instance or null if not initialized
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useFactoryActionRegister = () => {
return useFactoryActionContext().actionRegisterRef.current;
};
/**
* Hook that provides access to the dispatchWithResult function
*
* This hook returns a function that dispatches actions and returns detailed
* execution results including collected handler results, execution metadata,
* and error information.
*
* @returns dispatchWithResult function with full type safety
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result
*/
const useFactoryActionDispatchWithResult = () => {
const context = useFactoryActionContext();
const activeControllersRef = (0, react.useRef)(/* @__PURE__ */ new Set());
const dispatch = (0, react.useCallback)((action, payload, options) => {
const register = context.actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
let createdController;
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true,
onControllerCreated: (controller) => {
createdController = controller;
activeControllersRef.current.add(controller);
}
} }
};
return register.dispatch(action, payload, dispatchOptions).finally(() => {
if (createdController) activeControllersRef.current.delete(createdController);
});
}, [context.actionRegisterRef]);
const dispatchWithResult = (0, react.useCallback)((action, payload, options) => {
const register = context.actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
let createdController;
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true,
onControllerCreated: (controller) => {
createdController = controller;
activeControllersRef.current.add(controller);
}
} }
};
return register.dispatchWithResult(action, payload, dispatchOptions).finally(() => {
if (createdController) activeControllersRef.current.delete(createdController);
});
}, [context.actionRegisterRef]);
const abortAll = (0, react.useCallback)(() => {
activeControllersRef.current.forEach((controller) => {
if (!controller.signal.aborted) controller.abort();
});
activeControllersRef.current.clear();
}, []);
const resetAbortScope = (0, react.useCallback)(() => {
abortAll();
}, [abortAll]);
(0, react.useEffect)(() => {
const controllers = activeControllersRef;
return () => {
controllers.current.forEach((controller) => {
if (!controller.signal.aborted) controller.abort();
});
controllers.current.clear();
};
}, []);
return {
dispatch,
dispatchWithResult,
abortAll,
resetAbortScope
};
};
return {
Provider,
useActionContext: useFactoryActionContext,
useActionDispatch: useAction,
useActionHandler,
useActionRegister: useFactoryActionRegister,
useActionDispatchWithResult: useFactoryActionDispatchWithResult,
context: FactoryActionContext
};
}
//#endregion
Object.defineProperty(exports, 'Store', {
enumerable: true,
get: function () {
return Store;
}
});
Object.defineProperty(exports, 'StoreErrorBoundary', {
enumerable: true,
get: function () {
return StoreErrorBoundary;
}
});
Object.defineProperty(exports, 'StoreRegistry', {
enumerable: true,
get: function () {
return StoreRegistry;
}
});
Object.defineProperty(exports, 'createActionContext', {
enumerable: true,
get: function () {
return createActionContext;
}
});
Object.defineProperty(exports, 'createStore', {
enumerable: true,
get: function () {
return createStore;
}
});
Object.defineProperty(exports, 'createStoreErrorBoundary', {
enumerable: true,
get: function () {
return createStoreErrorBoundary;
}
});
Object.defineProperty(exports, 'defaultEqualityFn', {
enumerable: true,
get: function () {
return defaultEqualityFn;
}
});
Object.defineProperty(exports, 'useSafeStoreSubscription', {
enumerable: true,
get: function () {
return useSafeStoreSubscription;
}
});
Object.defineProperty(exports, 'useStoreSelector', {
enumerable: true,
get: function () {
return useStoreSelector;
}
});
Object.defineProperty(exports, 'withStoreErrorBoundary', {
enumerable: true,
get: function () {
return withStoreErrorBoundary;
}
});
import { ErrorHandlers, compareValues, getErrorStatistics, produce, safeGet, safeSet } from "./error-handling-CkdfKCZ0.js";
import React, { Component, createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useSyncExternalStore } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { ActionRegister } from "@context-action/core";
//#region src/stores/core/StoreRegistry.ts
/**
* Centralized store registry for managing multiple Store instances
*/
var StoreRegistry = class {
constructor(name = "default") {
this.stores = /* @__PURE__ */ new Map();
this.metadata = /* @__PURE__ */ new WeakMap();
this.listeners = /* @__PURE__ */ new Set();
this._snapshot = [];
this.name = name;
}
/**
* Subscribe to registry changes for reactive updates
*/
subscribe(listener) {
this.listeners.add(listener);
return () => {
this.listeners.delete(listener);
};
}
/**
* Register a new store in the registry
*/
register(name, store, metadata) {
if (this.stores.has(name)) {
if (this.stores.get(name)) {}
}
this.stores.set(name, store);
if (metadata) this.metadata.set(store, {
registeredAt: Date.now(),
name,
...metadata
});
this._updateSnapshot();
this._notifyListeners();
}
/**
* Unregister a store from the registry
*/
unregister(name) {
if (!this.stores.get(name)) return false;
this.stores.delete(name);
this._updateSnapshot();
this._notifyListeners();
return true;
}
/**
* Get a store by name
*/
getStore(name) {
return this.stores.get(name);
}
/**
* Check if a store exists
*/
hasStore(name) {
return this.stores.has(name);
}
/**
* Get all registered store names
*/
getStoreNames() {
return Array.from(this.stores.keys());
}
/**
* Get all stores as entries
*/
getAllStores() {
return new Map(this.stores);
}
/**
* Get store metadata
*/
getStoreMetadata(nameOrStore) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
return store ? this.metadata.get(store) : void 0;
}
/**
* Update store metadata
*/
updateStoreMetadata(nameOrStore, metadata) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
if (!store) return false;
const currentMetadata = this.metadata.get(store);
this.metadata.set(store, {
registeredAt: Date.now(),
name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown",
...currentMetadata,
...metadata
});
return true;
}
/**
* Get registry snapshot for React integration
*/
getSnapshot() {
return this._snapshot;
}
/**
* Clear all stores from registry
*/
clear() {
this.stores.clear();
this._updateSnapshot();
this._notifyListeners();
}
/**
* Dispose registry and cleanup resources
*/
dispose() {
this.clear();
this.listeners.clear();
}
/**
* Get count of registered stores
*/
getStoreCount() {
return this.stores.size;
}
/**
* Iterate over all stores
*/
forEach(callback) {
this.stores.forEach((store, name) => {
callback(store, name);
});
}
/**
* Get registry statistics
*/
getStats() {
return {
totalStores: this.stores.size,
storeNames: this.getStoreNames(),
registryName: this.name
};
}
/**
* Update internal snapshot
*/
_updateSnapshot() {
this._snapshot = Array.from(this.stores.entries());
}
/**
* Notify all listeners of registry changes
*/
_notifyListeners() {
this.listeners.forEach((listener) => {
try {
listener();
} catch (error) {
console.error("Error in registry listener:", error);
}
});
}
};
/**
* Global default registry instance
*/
const globalStoreRegistry = new StoreRegistry("global");
//#endregion
//#region src/stores/utils/type-guards.ts
function isRefState(value) {
return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean";
}
/**
* DOM Event 객체인지 확인하는 타입 가드
*/
function isDOMEvent(value) {
return value instanceof Event;
}
/**
* Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체)
*/
function isEventLike(value) {
return typeof value === "object" && value !== null && typeof value.preventDefault === "function";
}
/**
* target 프로퍼티를 가진 객체인지 확인하는 타입 가드
*/
function hasTargetProperty(value) {
return typeof value === "object" && value !== null && "target" in value;
}
/**
* DOM Element인지 확인하는 타입 가드
*/
function isDOMElement(value) {
return value instanceof Element;
}
/**
* 객체인지 확인하는 타입 가드 (null 제외)
*/
function isObject(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
/**
* 복합 타입 가드: Event 객체로 의심되는 객체인지 확인
* RefState가 아니면서 Event 관련 속성을 가진 객체를 감지
*/
function isSuspiciousEventObject(value, checkNested = true) {
if (!isObject(value) || isRefState(value)) return false;
if (isEventLikeObject(value)) return true;
if (checkNested) {
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const nestedValue = value[key];
if (isEventLikeObject(nestedValue)) return true;
}
}
return false;
}
/**
* 단일 객체가 이벤트와 같은지 확인
*/
function isEventLikeObject(value) {
if (!isObject(value)) return false;
const hasEventTarget = hasTargetProperty(value);
const hasPreventDefault = isEventLike(value);
const isEvent = isDOMEvent(value);
const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault);
const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value;
const constructorName = value?.constructor?.name;
const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false;
return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor;
}
/**
* 문제가 될 수 있는 속성들을 찾아내는 함수
*/
function findProblematicProperties(value) {
if (!isObject(value)) return [];
const problematicKeys = [];
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const prop = value[key];
if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key);
}
return problematicKeys;
}
/**
* 통합 타입 가드 객체
* 모든 타입 가드 함수들을 하나의 객체로 export
*/
const TypeGuards = {
isRefState,
isDOMEvent,
isEventLike,
hasTargetProperty,
isDOMElement,
isObject,
isSuspiciousEventObject,
findProblematicProperties
};
//#endregion
//#region src/stores/core/Store.ts
/**
* Core Store class for centralized state management with memory leak prevention
*
* Provides reactive state management with subscription capabilities, optimized for
* React integration through useSyncExternalStore. Features advanced cleanup mechanisms,
* automatic resource management, and comprehensive memory leak prevention.
*
* Key Features:
* - Automatic cleanup task registration and execution
* - Memory leak prevention with disposal patterns
* - Race condition protection for async operations
* - Advanced error recovery with exponential backoff
* - Resource monitoring and threshold management
*
* @template T - The type of value stored in this store
*
* @example
* ```typescript
* const userStore = createStore('user', { name: '', age: 0 });
*
* // Register cleanup tasks
* const unregister = userStore.registerCleanup(() => {
* console.log('Cleaning up user store resources');
* });
*
* // Automatic cleanup on disposal
* userStore.dispose();
* ```
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
* @public
*/
var Store = class {
constructor(name, initialValue) {
this.listeners = /* @__PURE__ */ new Set();
this._lastClonedValue = null;
this._lastClonedVersion = 0;
this._version = 0;
this.isUpdating = false;
this.updateQueue = [];
this.notificationMode = "batched";
this.pendingNotification = false;
this.animationFrameId = null;
this.pendingUpdatesCount = 0;
this.cleanupTasks = /* @__PURE__ */ new Set();
this.isDisposed = false;
this.errorCount = 0;
this.lastErrorTime = 0;
this.MAX_ERROR_COUNT = 5;
this.ERROR_RESET_TIME = 6e4;
this.subscriptionRegistry = /* @__PURE__ */ new WeakMap();
this.cloningEnabled = true;
this.subscribe = (listener) => {
if (this.isDisposed) {
console.warn(`Cannot subscribe to disposed store "${this.name}"`);
return () => {};
}
const enhancedListener = () => {
if (this.isDisposed) return;
try {
listener();
if (this.errorCount > 0) this.errorCount = 0;
} catch (error) {
this._handleListenerError(error, listener);
}
};
this.subscriptionRegistry.set(listener, {
subscribedAt: Date.now(),
errorCount: 0,
enhancedListener
});
this.listeners.add(enhancedListener);
return () => {
this.listeners.delete(enhancedListener);
this.subscriptionRegistry.delete(listener);
};
};
this.getSnapshot = () => {
return this._snapshot;
};
this.name = name;
this._value = initialValue;
this._snapshot = this._createSnapshot();
}
/**
* 현재 값 직접 가져오기 (액션 핸들러용)
* 핵심 로직: 불변성을 보장하는 깊은 복사본 반환
*
* @implements lazy-evaluation
* @implements store-immutability
* @memberof architecture-terms
*
* 사용 시나리오: Action handler에서 최신 상태 읽기
* 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨
*/
getValue() {
if (typeof this._value !== "object" || this._value === null) return this._value;
if (this.cloningEnabled) {
if (this._lastClonedVersion === this._version && this._lastClonedValue !== null) return this._lastClonedValue;
this._lastClonedValue = safeGet(this._value, this.cloningEnabled);
this._lastClonedVersion = this._version;
return this._lastClonedValue;
}
return this._value;
}
/**
* Store 값 설정 및 구독자 알림
* 핵심 로직:
* 1. 입력값의 불변성 보장을 위한 깊은 복사 (선택적 skip 가능)
* 2. 강화된 값 비교 시스템으로 불필요한 리렌더링 방지
* 3. Structural sharing을 통한 성능 최적화
* 4. 값 변경 시에만 스냅샷 재생성 및 알림
*
* @implements unidirectional-data-flow
* @implements store-immutability
* @memberof architecture-terms
*
* 보안 강화: 입력값을 복사하여 Store 내부 상태가 외부 참조에 의해 변경되지 않도록 보호
* 성능 강화: 다층 비교 시스템으로 정확한 변경 감지 및 렌더링 최적화
*/
setValue(value, options) {
if (TypeGuards.isObject(value)) {
if (!TypeGuards.isRefState(value) && TypeGuards.isSuspiciousEventObject(value)) {
const eventHandling = options?.eventHandling || "block";
const hasEventTarget = TypeGuards.hasTargetProperty(value);
const hasPreventDefault = TypeGuards.isEventLike(value);
const isEvent = TypeGuards.isDOMEvent(value);
switch (eventHandling) {
case "allow": break;
case "transform":
if (options?.eventTransform) try {
value = options.eventTransform(value);
} catch (error) {
ErrorHandlers.store("Event transformation failed in Store.setValue", {
storeName: this.name,
valueType: typeof value,
error: error instanceof Error ? error.message : String(error)
});
return;
}
else {
ErrorHandlers.store("Event transformation requested but no transform function provided", {
storeName: this.name,
valueType: typeof value
});
return;
}
break;
case "block":
default:
ErrorHandlers.store("Event object detected in Store.setValue - this may cause memory leaks", {
storeName: this.name,
valueType: typeof value,
constructorName: value?.constructor?.name,
isEvent,
hasTargetProperty: hasEventTarget,
hasPreventDefault,
problematicProperties: TypeGuards.findProblematicProperties(value)
});
return;
}
}
}
const safeValue = options?.skipClone ? value : safeSet(value, this.cloningEnabled);
let hasChanged = true;
if (!options?.skipComparison) hasChanged = this._compareValues(this._value, safeValue);
if (hasChanged) {
this._value = safeValue;
this._version++;
this._snapshot = this._createSnapshot();
this._scheduleNotification();
}
}
/**
* Update value using updater function with Immer integration
* 핵심 로직:
* 1. Immer produce를 사용하여 draft 객체 제공
* 2. updater 결과를 불변성을 보장하며 설정
*
* @implements store-immutability
* 보안 강화: Immer draft를 통한 안전한 상태 수정
*/
update(updater) {
if (this.isUpdating) {
this.updateQueue.push(() => this.update(updater));
return;
}
try {
this.isUpdating = true;
let updatedValue;
try {
updatedValue = produce(this._value, (draft) => {
const result = updater(draft);
return result !== void 0 ? result : draft;
});
} catch (immerError) {
console.warn("[Store] Immer update failed, falling back to safe copy method", immerError);
const safeCurrentValue = safeGet(this._value, this.cloningEnabled);
try {
updatedValue = produce(safeCurrentValue, (draft) => {
const result = updater(draft);
return result !== void 0 ? result : draft;
});
} catch (secondImmerError) {
console.warn("[Store] Immer completely failed, using direct update (immutability not guaranteed)", secondImmerError);
updatedValue = updater(safeCurrentValue);
}
}
if (TypeGuards.isObject(updatedValue)) {
if (!TypeGuards.isRefState(updatedValue) && TypeGuards.isSuspiciousEventObject(updatedValue)) {
const hasEventTarget = TypeGuards.hasTargetProperty(updatedValue);
const hasPreventDefault = TypeGuards.isEventLike(updatedValue);
const isEvent = TypeGuards.isDOMEvent(updatedValue);
ErrorHandlers.store("Event object detected in Store.update result - this may cause memory leaks", {
storeName: this.name,
updatedValueType: typeof updatedValue,
constructorName: updatedValue?.constructor?.name,
isEvent,
hasTargetProperty: hasEventTarget,
hasPreventDefault,
problematicProperties: TypeGuards.findProblematicProperties(updatedValue)
});
return;
}
}
this.setValue(updatedValue);
} finally {
this.isUpdating = false;
if (this.updateQueue.length > 0) {
const nextUpdate = this.updateQueue.shift();
if (nextUpdate) Promise.resolve().then(nextUpdate);
}
}
}
/**
* Get number of active listeners
*/
getListenerCount() {
return this.listeners.size;
}
/**
* Clear all listeners
*/
clearListeners() {
this.listeners.clear();
}
/**
* Register cleanup task for automatic execution on disposal
*
* Registers a cleanup function that will be automatically called when the store
* is disposed. This prevents memory leaks and ensures proper resource cleanup.
*
* @param task - Cleanup function to register
* @returns Unregister function to remove the cleanup task
*
* @example
* ```typescript
* const timer = setInterval(() => {}, 1000);
* const unregister = store.registerCleanup(() => clearInterval(timer));
*
* // Later, remove the cleanup task if needed
* unregister();
* ```
*/
registerCleanup(task) {
if (this.isDisposed) {
console.warn(`Store "${this.name}" is already disposed, cleanup task ignored`);
return () => {};
}
this.cleanupTasks.add(task);
return () => this.cleanupTasks.delete(task);
}
/**
* Enhanced Store disposal with comprehensive cleanup
*
* Performs complete cleanup of all store resources including listeners,
* timers, cleanup tasks, and internal state. Prevents memory leaks and
* ensures proper resource disposal.
*
* @example
* ```typescript
* // Manual disposal
* store.dispose();
*
* // Auto-disposal with useEffect
* useEffect(() => {
* return () => store.dispose();
* }, [store]);
* ```
*/
dispose() {
if (this.isDisposed) return;
this.isDisposed = true;
try {
this.cleanupTasks.forEach((task) => {
try {
task();
} catch (error) {
ErrorHandlers.store("Error during cleanup task execution", { storeName: this.name }, error instanceof Error ? error : void 0);
}
});
this.cleanupTasks.clear();
this.subscriptionRegistry = /* @__PURE__ */ new WeakMap();
this.clearListeners();
if (this.animationFrameId !== null) {
cancelAnimationFrame(this.animationFrameId);
this.animationFrameId = null;
}
this.pendingNotification = false;
this.updateQueue.length = 0;
} catch (error) {
ErrorHandlers.store("Critical error during store disposal", { storeName: this.name }, error instanceof Error ? error : void 0);
}
}
/**
* Check if store is disposed
* @returns true if store has been disposed
*/
isStoreDisposed() {
return this.isDisposed;
}
/**
* Store별 커스텀 비교 함수 설정
* 이 Store에만 적용되는 특별한 비교 로직 설정
*
* @param comparator - 커스텀 비교 함수 (oldValue, newValue) => boolean
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config
*/
setCustomComparator(comparator) {
this.customComparator = comparator;
}
/**
* Store별 비교 옵션 설정
* 이 Store에만 적용되는 비교 전략 설정
*
* @param options - 비교 옵션
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-config
*/
setComparisonOptions(options) {
this.comparisonOptions = options;
}
/**
* 성능 최적화: Store별 복사 동작 제어
*
* @param enabled - true: 복사 활성화 (안전), false: 복사 비활성화 (성능 우선)
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/performance
*/
setCloningEnabled(enabled) {
this.cloningEnabled = enabled;
}
/**
* 현재 복사 설정 조회
*/
isCloningEnabled() {
return this.cloningEnabled;
}
/**
* 강화된 값 비교 시스템
* 1. 커스텀 비교 함수 우선 사용
* 2. Store별 비교 옵션 적용
* 3. 성능 최적화된 빠른 비교 fallback
* 4. 전역 비교 설정 사용
*
* @param oldValue - 이전 값
* @param newValue - 새로운 값
* @returns true if values are different (change detected), false if same
* @protected
*/
_compareValues(oldValue, newValue) {
let result;
try {
if (this.customComparator) result = !this.customComparator(oldValue, newValue);
else if (this.comparisonOptions) result = !compareValues(oldValue, newValue, this.comparisonOptions);
else result = !compareValues(oldValue, newValue, { strategy: "reference" });
} catch (error) {
ErrorHandlers.store("Error during value comparison, falling back to reference comparison", { storeName: this.name }, error instanceof Error ? error : void 0);
result = !Object.is(oldValue, newValue);
}
return result;
}
_createSnapshot() {
return {
value: safeGet(this._value, this.cloningEnabled),
name: this.name,
lastUpdate: Date.now()
};
}
/**
* requestAnimationFrame 기반 알림 스케줄링
* 브라우저의 다음 프레임에서 리스너 알림 실행
*/
_scheduleNotification() {
if (this.notificationMode === "immediate") this._notifyListeners();
else this._scheduleWithRAF();
}
/**
* requestAnimationFrame을 사용한 알림 스케줄링
* 누적 가능한 배치 시스템으로 개선
*/
_scheduleWithRAF() {
this.pendingUpdatesCount++;
if (!this.pendingNotification) {
this.pendingNotification = true;
this.animationFrameId = requestAnimationFrame(() => {
this._executeNotification();
});
}
}
/**
* 스케줄된 알림 실행
*/
_executeNotification() {
this.pendingNotification = false;
this.animationFrameId = null;
const batchedUpdates = this.pendingUpdatesCount;
this.pendingUpdatesCount = 0;
this._notifyListeners();
if (batchedUpdates > 1) console.debug(`[Store:${this.name}] Batched ${batchedUpdates} updates in single frame`);
}
/**
* Handle listener execution errors with recovery strategies
*/
_handleListenerError(error, listener) {
const now = Date.now();
if (now - this.lastErrorTime > this.ERROR_RESET_TIME) this.errorCount = 0;
this.errorCount++;
this.lastErrorTime = now;
const metadata = this.subscriptionRegistry.get(listener);
if (metadata) metadata.errorCount++;
ErrorHandlers.store("Error in store listener execution", {
storeName: this.name,
listenerCount: this.listeners.size,
errorCount: this.errorCount,
subscriptionAge: metadata ? now - metadata.subscribedAt : "unknown"
}, error instanceof Error ? error : void 0);
if (metadata && metadata.errorCount >= 3) {
console.warn(`Removing problematic listener from store "${this.name}" after ${metadata.errorCount} errors`);
this.listeners.delete(metadata.enhancedListener);
this.subscriptionRegistry.delete(listener);
}
if (this.errorCount >= this.MAX_ERROR_COUNT) {
console.error(`Store "${this.name}" disabled due to excessive errors (${this.errorCount})`);
this.clearListeners();
}
}
_notifyListeners() {
if (this.isDisposed) return;
this.listeners.forEach((listener) => {
if (this.isDisposed) return;
listener();
});
}
};
/**
* Factory function for creating type-safe Store instances
*
* Creates a new Store instance with the specified name and initial value.
* Provides type safety and integrates seamlessly with React hooks and
* the Context-Action framework patterns.
*
* @template T - The type of values stored in this store
*
* @param name - Unique identifier for the store (used for debugging)
* @param initialValue - Initial value to store
*
* @returns Configured Store instance ready for use
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
*
* @public
*/
function createStore(name, initialValue) {
return new Store(name, initialValue);
}
//#endregion
//#region src/stores/utils/sync-external-store-utils.ts
/**
* 향상된 구독 함수 생성 (내부 사용)
* 디바운싱, 스로틀링, 조건부 구독 기능 제공
*/
function createEnhancedSubscriber(store, options = {}) {
const { debounce, throttle, condition, debug, name = "unknown" } = options;
return (callback) => {
if (!store) return () => {};
let debounceTimer = null;
let throttleTimer = null;
let lastThrottleTime = 0;
const enhancedCallback = () => {
if (condition && !condition()) {
if (debug) console.debug(`[${name}] Subscription suspended due to condition`);
return;
}
const now = performance.now();
if (throttle && throttle > 0) {
if (now - lastThrottleTime < throttle) {
if (throttleTimer) clearTimeout(throttleTimer);
throttleTimer = setTimeout(() => {
lastThrottleTime = performance.now();
callback();
}, throttle - (now - lastThrottleTime));
return;
}
lastThrottleTime = now;
}
if (debounce && debounce > 0) {
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
callback();
if (debug) console.debug(`[${name}] Debounced callback executed after ${debounce}ms`);
}, debounce);
return;
}
callback();
};
const unsubscribe = store.subscribe(enhancedCallback);
return () => {
if (debounceTimer) clearTimeout(debounceTimer);
if (throttleTimer) clearTimeout(throttleTimer);
unsubscribe();
};
};
}
/**
* Null-safe Store 구독 훅
* useSyncExternalStore를 기반으로 한 안전한 구독
*/
function useSafeStoreSubscription(store, selector, options = {}) {
const { initialValue, equalityFn, debounce, throttle, condition, debug, name } = options;
const stableSubscriptionOptions = useMemo(() => ({
debounce,
throttle,
condition,
debug,
name
}), [
debounce,
throttle,
condition,
debug,
name
]);
const needsEnhancedSubscription = Boolean(debounce || throttle || condition);
const subscribe = useCallback((callback) => {
if (!store) return () => {};
if (needsEnhancedSubscription) return createEnhancedSubscriber(store, stableSubscriptionOptions)(callback);
return store.subscribe(callback);
}, [
store,
needsEnhancedSubscription,
stableSubscriptionOptions
]);
const getSnapshot = useCallback(() => {
if (!store) return initialValue;
const snapshot = store.getSnapshot();
return selector ? selector(snapshot.value) : snapshot.value;
}, [
store,
selector,
initialValue
]);
const cachedSnapshotRef = useRef();
const stableGetSnapshot = useCallback(() => {
const currentSnapshot = getSnapshot();
if (equalityFn && cachedSnapshotRef.current !== void 0) {
if (equalityFn(cachedSnapshotRef.current, currentSnapshot)) return cachedSnapshotRef.current;
}
cachedSnapshotRef.current = currentSnapshot;
return currentSnapshot;
}, [getSnapshot, equalityFn]);
const getServerSnapshot = useCallback(() => {
return initialValue;
}, [initialValue]);
return useSyncExternalStore(subscribe, equalityFn ? stableGetSnapshot : getSnapshot, getServerSnapshot);
}
/**
* 기본 동등성 비교 함수들
*/
const equalityFunctions = {
reference: (a, b) => Object.is(a, b),
shallow: (a, b) => {
if (Object.is(a, b)) return true;
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (const key of keysA) if (!Object.prototype.hasOwnProperty.call(b, key) || !Object.is(a[key], b[key])) return false;
return true;
},
deep: (a, b) => {
if (Object.is(a, b)) return true;
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
if (Array.isArray(a) !== Array.isArray(b)) return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (const key of keysA) {
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
if (!equalityFunctions.deep(a[key], b[key])) return false;
}
return true;
},
smart: (a, b) => {
if (Object.is(a, b)) return true;
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
return a.every((item, index) => {
const bItem = b[index];
if (typeof item === "object" && item !== null && typeof bItem === "object" && bItem !== null) return equalityFunctions.shallow(item, bItem);
return Object.is(item, bItem);
});
}
return equalityFunctions.shallow(a, b);
}
};
//#endregion
//#region src/stores/hooks/useStoreSelector.ts
const defaultEqualityFn = equalityFunctions.smart;
const shallowEqual = equalityFunctions.shallow;
const deepEqual = equalityFunctions.deep;
const smartEqual = equalityFunctions.smart;
/**
* Hook for selective store subscription with performance optimization
*
* Subscribes to specific parts of store data using a selector function,
* triggering re-renders only when the selected value actually changes.
* Essential for preventing unnecessary re-renders in complex applications.
*
* @template T - Type of the store value
* @template R - Type of the value returned by the selector
*
* @param store - Store instance to subscribe to
* @param selector - Function to extract needed data from store value
* @param equalityFn - Function to compare previous and new values (default: Object.is)
*
* @returns The value returned by the selector function
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/advanced-hooks#usestoreselector-advanced-usage
*
* @public
*/
function useStoreSelector(store, selector, equalityFn = defaultEqualityFn) {
"use memo";
const stableSelector = useCallback(selector, [selector]);
const stableEqualityFn = useCallback(equalityFn, [equalityFn]);
const selectorWarningShownRef = useRef(false);
if (selector !== stableSelector && !selectorWarningShownRef.current) {
console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name);
selectorWarningShownRef.current = true;
}
const previousValueRef = useRef();
const subscribe = useCallback((callback) => {
return store.subscribe(callback);
}, [store]);
const getSnapshot = useCallback(() => {
try {
const selectedValue = stableSelector(store.getValue());
if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current;
previousValueRef.current = selectedValue;
return selectedValue;
} catch (error) {
console.error("useStoreSelector: Error in selector function:", error);
throw error;
}
}, [
store,
stableSelector,
stableEqualityFn
]);
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
}
//#endregion
//#region src/stores/components/StoreErrorBoundary.tsx
/**
* Store 시스템을 위한 에러 경계 컴포넌트
*
* Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다.
* 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는
* 사용자 친화적인 메시지를 보여줍니다.
*/
var StoreErrorBoundary = class extends Component {
constructor(props) {
super(props);
this.resetTimeoutId = null;
this.resetErrorBoundary = () => {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
this.setState({
hasError: false,
error: null,
errorInfo: null,
errorId: null
});
};
this.state = {
hasError: false,
error: null,
errorInfo: null,
errorId: null
};
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error: error instanceof Error && error.name === "ContextActionError" ? error : null,
errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
};
}
componentDidCatch(error, errorInfo) {
if (error.name === "ContextActionError") {
const contextActionError = error;
this.setState({ errorInfo });
this.props.onError?.(contextActionError, errorInfo);
} else {
const contextActionError = ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, {
component: "StoreErrorBoundary",
stack: error.stack,
componentStack: errorInfo.componentStack
}, error);
this.setState({
error: contextActionError,
errorInfo
});
this.props.onError?.(contextActionError, errorInfo);
}
}
componentDidUpdate(prevProps) {
const { hasError } = this.state;
const { resetOnPropsChange, resetKeys } = this.props;
if (hasError && resetOnPropsChange) {
if (resetKeys) {
if (resetKeys.some((key) => {
return prevProps[key] !== this.props[key];
})) this.resetErrorBoundary();
} else if (prevProps !== this.props) this.resetErrorBoundary();
}
}
componentWillUnmount() {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
}
render() {
const { hasError, error, errorInfo } = this.state;
const { children, fallback } = this.props;
if (hasError) {
if (fallback) {
if (typeof fallback === "function") return fallback(error, errorInfo);
return fallback;
}
return this.renderDefaultFallback();
}
return children;
}
renderDefaultFallback() {
return this.renderDevelopmentFallback();
}
renderDevelopmentFallback() {
const { error, errorInfo, errorId } = this.state;
const stats = getErrorStatistics();
return /* @__PURE__ */ jsxs("div", {
style: {
padding: "20px",
margin: "20px",
border: "2px solid #ff6b6b",
borderRadius: "8px",
backgroundColor: "#ffe0e0",
fontFamily: "monospace"
},
children: [
/* @__PURE__ */ jsx("h2", {
style: {
color: "#d63031",
margin: "0 0 10px 0"
},
children: "🚨 Store Error Boundary"
}),
/* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ jsx("strong", { children: "Error ID:" }),
" ",
errorId
]
}),
error && /* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ jsx("strong", { children: "Error Type:" }),
" ",
error.type,
/* @__PURE__ */ jsx("br", {}),
/* @__PURE__ */ jsx("strong", { children: "Message:" }),
" ",
error.message,
/* @__PURE__ */ jsx("br", {}),
/* @__PURE__ */ jsx("strong", { children: "Timestamp:" }),
" ",
new Date(error.timestamp).toISOString()
]
}),
error?.context && /* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ jsx("strong", { children: "Context:" }), /* @__PURE__ */ jsx("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "12px"
},
children: JSON.stringify(error.context, null, 2)
})]
}),
/* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ jsx("strong", { children: "Error Statistics:" }),
/* @__PURE__ */ jsx("br", {}),
"Total Errors: ",
stats.totalErrors,
/* @__PURE__ */ jsx("br", {}),
"Recent Errors: ",
stats.recentErrors.length
]
}),
errorInfo && /* @__PURE__ */ jsxs("details", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ jsx("summary", {
style: {
cursor: "pointer",
fontWeight: "bold"
},
children: "Component Stack"
}), /* @__PURE__ */ jsx("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "11px",
whiteSpace: "pre-wrap"
},
children: errorInfo.componentStack
})]
}),
/* @__PURE__ */ jsx("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#00b894",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
fontWeight: "bold"
},
children: "Try Again"
})
]
});
}
renderProductionFallback() {
return /* @__PURE__ */ jsxs("div", {
style: {
padding: "20px",
textAlign: "center",
backgroundColor: "#f8f9fa",
border: "1px solid #dee2e6",
borderRadius: "8px",
margin: "20px 0"
},
children: [
/* @__PURE__ */ jsx("h3", {
style: {
color: "#6c757d",
margin: "0 0 10px 0"
},
children: "Something went wrong"
}),
/* @__PURE__ */ jsx("p", {
style: {
color: "#6c757d",
margin: "0 0 15px 0"
},
children: "We're sorry, but something unexpected happened. Please try again."
}),
/* @__PURE__ */ jsx("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#007bff",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer"
},
children: "Try Again"
})
]
});
}
};
/**
* Enhanced HOC for automatic Store Error Boundary wrapping with security
*
* @template P - Component props type
* @param WrappedComponent - Component to wrap with error boundary
* @param errorBoundaryProps - Error boundary configuration
* @returns Enhanced component with comprehensive error handling
*/
function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) {
const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ jsx(StoreErrorBoundary, {
...errorBoundaryProps,
children: /* @__PURE__ */ jsx(WrappedComponent, { ...props })
});
WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`;
return WithStoreErrorBoundaryComponent;
}
/**
* 특정 Store와 연결된 에러 경계 생성 헬퍼
*/
function createStoreErrorBoundary(storeName, customFallback) {
return ({ children }) => /* @__PURE__ */ jsx(StoreErrorBoundary, {
fallback: customFallback,
onError: (error, errorInfo) => {
console.group(`Store Error in ${storeName}`);
console.error("Error:", error);
console.error("Component Stack:", errorInfo.componentStack);
console.groupEnd();
},
resetKeys: [storeName],
children
});
}
//#endregion
//#region src/actions/ActionContext.tsx
function createActionContext(contextNameOrConfig = {}, config) {
let effectiveConfig;
let contextName;
if (typeof contextNameOrConfig === "string") {
contextName = contextNameOrConfig;
effectiveConfig = {
...config,
name: config?.name || contextName
};
} else {
effectiveConfig = contextNameOrConfig;
contextName = effectiveConfig.name || "ActionContext";
}
const FactoryActionContext = createContext(null);
const Provider = ({ children }) => {
const actionRegisterRef = useRef(new ActionRegister(effectiveConfig));
const contextValue = useMemo(() => ({ actionRegisterRef }), []);
return /* @__PURE__ */ jsx(FactoryActionContext.Provider, {
value: contextValue,
children
});
};
const useFactoryActionContext = () => {
const context = useContext(FactoryActionContext);
if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider");
return context;
};
/**
* Optimized hook to get stable dispatch functions
*
* Returns stable dispatch functions that prevent re-renders and maintain
* reference equality across component renders.
*
* @returns Object with dispatch and dispatchWithResult functions
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useActionDispatcher = () => {
const { actionRegisterRef } = useFactoryActionContext();
return {
dispatch: useCallback((action, payload, options) => {
console.log(`React dispatch called for '${String(action)}':`, {
hasPayload: payload !== void 0,
hasOptions: options !== void 0,
timestamp: (/* @__PURE__ */ new Date()).toISOString()
});
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up.");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatch(action, payload, dispatchOptions);
}, [actionRegisterRef]),
dispatchWithResult: useCallback((action, payload, options) => {
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatchWithResult(action, payload, dispatchOptions);
}, [actionRegisterRef])
};
};
const useAction = () => {
const { dispatch } = useActionDispatcher();
return dispatch;
};
const useActionHandler = (action, handler, config$1) => {
const { actionRegisterRef } = useFactoryActionContext();
const actionId = useId();
const handlerRef = useRef(handler);
handlerRef.current = handler;
const priority = config$1?.priority ?? 0;
const id = config$1?.id || `react_${String(action)}_${actionId}`;
const blocking = config$1?.blocking ?? false;
const once = config$1?.once ?? false;
const debounce = config$1?.debounce;
const throttle = config$1?.throttle;
const stableConfig = useMemo(() => ({
priority,
id,
blocking,
once,
replaceExisting: true,
...debounce !== void 0 && { debounce },
...throttle !== void 0 && { throttle }
}), [
priority,
id,
blocking,
once,
debounce,
throttle
]);
useEffect(() => {
const register = actionRegisterRef.current;
if (!register) return;
const wrapperHandler = (payload, controller) => {
return handlerRef.current(payload, controller);
};
console.log(`Registering handler for '${String(action)}'`);
return register.register(action, wrapperHandler, stableConfig);
}, [
action,
actionRegisterRef,
stableConfig
]);
};
/**
* Hook that provides direct access to the ActionRegister instance
*
* This hook is useful when you need to:
* - Register multiple handlers dynamically
* - Access other ActionRegister methods like clearAction, getHandlers, etc.
* - Implement complex handler registration logic
* - Have more control over the registration lifecycle
*
* @returns ActionRegister instance or null if not initialized
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useFactoryActionRegister = () => {
return useFactoryActionContext().actionRegisterRef.current;
};
/**
* Hook that provides access to the dispatchWithResult function
*
* This hook returns a function that dispatches actions and returns detailed
* execution results including collected handler results, execution metadata,
* and error information.
*
* @returns dispatchWithResult function with full type safety
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result
*/
const useFactoryActionDispatchWithResult = () => {
const context = useFactoryActionContext();
const activeControllersRef = useRef(/* @__PURE__ */ new Set());
const dispatch = useCallback((action, payload, options) => {
const register = context.actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
let createdController;
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true,
onControllerCreated: (controller) => {
createdController = controller;
activeControllersRef.current.add(controller);
}
} }
};
return register.dispatch(action, payload, dispatchOptions).finally(() => {
if (createdController) activeControllersRef.current.delete(createdController);
});
}, [context.actionRegisterRef]);
const dispatchWithResult = useCallback((action, payload, options) => {
const register = context.actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
let createdController;
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true,
onControllerCreated: (controller) => {
createdController = controller;
activeControllersRef.current.add(controller);
}
} }
};
return register.dispatchWithResult(action, payload, dispatchOptions).finally(() => {
if (createdController) activeControllersRef.current.delete(createdController);
});
}, [context.actionRegisterRef]);
const abortAll = useCallback(() => {
activeControllersRef.current.forEach((controller) => {
if (!controller.signal.aborted) controller.abort();
});
activeControllersRef.current.clear();
}, []);
const resetAbortScope = useCallback(() => {
abortAll();
}, [abortAll]);
useEffect(() => {
const controllers = activeControllersRef;
return () => {
controllers.current.forEach((controller) => {
if (!controller.signal.aborted) controller.abort();
});
controllers.current.clear();
};
}, []);
return {
dispatch,
dispatchWithResult,
abortAll,
resetAbortScope
};
};
return {
Provider,
useActionContext: useFactoryActionContext,
useActionDispatch: useAction,
useActionHandler,
useActionRegister: useFactoryActionRegister,
useActionDispatchWithResult: useFactoryActionDispatchWithResult,
context: FactoryActionContext
};
}
//#endregion
export { Store, StoreErrorBoundary, StoreRegistry, createActionContext, createStore, createStoreErrorBoundary, defaultEqualityFn, useSafeStoreSubscription, useStoreSelector, withStoreErrorBoundary };
//# sourceMappingURL=ActionContext-BIIFgZEq.js.map

Sorry, the diff of this file is too big to display

+1
-1
const require_error_handling = require('./error-handling-ibCwx4ki.cjs');
const require_ActionContext = require('./ActionContext-B6V0n1wh.cjs');
const require_ActionContext = require('./ActionContext-Bbkccg3d.cjs');
const require_utils = require('./utils-ZdkTBqFK.cjs');

@@ -4,0 +4,0 @@ let react = require("react");

@@ -1,2 +0,2 @@

import { StoreErrorBoundary, StoreRegistry, createActionContext, createStore, createStoreErrorBoundary, defaultEqualityFn, useSafeStoreSubscription, withStoreErrorBoundary } from "./ActionContext-BuVbb-bA.js";
import { StoreErrorBoundary, StoreRegistry, createActionContext, createStore, createStoreErrorBoundary, defaultEqualityFn, useSafeStoreSubscription, withStoreErrorBoundary } from "./ActionContext-BIIFgZEq.js";
import { ContextActionError, ContextActionErrorType, ImmerUtils, compareValues, deepClone, deepCloneWithImmer, getGlobalComparisonOptions, handleError, preloadImmer, produce, safeGet, safeSet, setGlobalComparisonOptions } from "./error-handling-CkdfKCZ0.js";

@@ -3,0 +3,0 @@ import { SubscriptionManager, TypeUtils, composeProviders, createSafeEqualityFn, createStoreConfig, extractStoreValue, extractStoreValues, isStore, isValidStoreValue, useSubscriptionManager } from "./utils-B_r1_2dw.js";

const require_error_handling = require('./error-handling-ibCwx4ki.cjs');
const require_ActionContext = require('./ActionContext-B6V0n1wh.cjs');
const require_ActionContext = require('./ActionContext-Bbkccg3d.cjs');
let react = require("react");

@@ -4,0 +4,0 @@ react = require_error_handling.__toESM(react);

@@ -1,2 +0,2 @@

import { Store, StoreErrorBoundary, StoreRegistry, createActionContext, createStore, defaultEqualityFn, useSafeStoreSubscription, useStoreSelector } from "./ActionContext-BuVbb-bA.js";
import { Store, StoreErrorBoundary, StoreRegistry, createActionContext, createStore, defaultEqualityFn, useSafeStoreSubscription, useStoreSelector } from "./ActionContext-BIIFgZEq.js";
import { ErrorHandlers } from "./error-handling-CkdfKCZ0.js";

@@ -3,0 +3,0 @@ import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";

@@ -1,1 +0,1 @@

{"version":3,"file":"Store--dj9U0mo.d.cts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/core/StoreRegistry.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"}
{"version":3,"file":"Store--dj9U0mo.d.cts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/core/StoreRegistry.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Store-CoQcuZnp.d.ts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/core/StoreRegistry.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"}
{"version":3,"file":"Store-CoQcuZnp.d.ts","names":[],"sources":["../src/stores/core/types.ts","../src/stores/core/StoreRegistry.ts","../src/stores/utils/comparison.ts","../src/stores/core/Store.ts"],"sourcesContent":[],"mappings":"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"}
{
"name": "@context-action/react",
"version": "0.8.3",
"version": "0.8.4",
"type": "module",

@@ -72,3 +72,3 @@ "description": "React integration for @context-action/core - Context and hooks for type-safe action management",

"dependencies": {
"@context-action/core": "^0.8.1",
"@context-action/core": "^0.8.4",
"immer": "^10.1.3",

@@ -75,0 +75,0 @@ "react-compiler-runtime": "1.0.0"

const require_error_handling = require('./error-handling-ibCwx4ki.cjs');
let react = require("react");
react = require_error_handling.__toESM(react);
let react_jsx_runtime = require("react/jsx-runtime");
react_jsx_runtime = require_error_handling.__toESM(react_jsx_runtime);
let __context_action_core = require("@context-action/core");
__context_action_core = require_error_handling.__toESM(__context_action_core);
//#region src/stores/core/StoreRegistry.ts
/**
* Centralized store registry for managing multiple Store instances
*/
var StoreRegistry = class {
constructor(name = "default") {
this.stores = /* @__PURE__ */ new Map();
this.metadata = /* @__PURE__ */ new WeakMap();
this.listeners = /* @__PURE__ */ new Set();
this._snapshot = [];
this.name = name;
}
/**
* Subscribe to registry changes for reactive updates
*/
subscribe(listener) {
this.listeners.add(listener);
return () => {
this.listeners.delete(listener);
};
}
/**
* Register a new store in the registry
*/
register(name, store, metadata) {
if (this.stores.has(name)) {
if (this.stores.get(name)) {}
}
this.stores.set(name, store);
if (metadata) this.metadata.set(store, {
registeredAt: Date.now(),
name,
...metadata
});
this._updateSnapshot();
this._notifyListeners();
}
/**
* Unregister a store from the registry
*/
unregister(name) {
if (!this.stores.get(name)) return false;
this.stores.delete(name);
this._updateSnapshot();
this._notifyListeners();
return true;
}
/**
* Get a store by name
*/
getStore(name) {
return this.stores.get(name);
}
/**
* Check if a store exists
*/
hasStore(name) {
return this.stores.has(name);
}
/**
* Get all registered store names
*/
getStoreNames() {
return Array.from(this.stores.keys());
}
/**
* Get all stores as entries
*/
getAllStores() {
return new Map(this.stores);
}
/**
* Get store metadata
*/
getStoreMetadata(nameOrStore) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
return store ? this.metadata.get(store) : void 0;
}
/**
* Update store metadata
*/
updateStoreMetadata(nameOrStore, metadata) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
if (!store) return false;
const currentMetadata = this.metadata.get(store);
this.metadata.set(store, {
registeredAt: Date.now(),
name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown",
...currentMetadata,
...metadata
});
return true;
}
/**
* Get registry snapshot for React integration
*/
getSnapshot() {
return this._snapshot;
}
/**
* Clear all stores from registry
*/
clear() {
this.stores.clear();
this._updateSnapshot();
this._notifyListeners();
}
/**
* Dispose registry and cleanup resources
*/
dispose() {
this.clear();
this.listeners.clear();
}
/**
* Get count of registered stores
*/
getStoreCount() {
return this.stores.size;
}
/**
* Iterate over all stores
*/
forEach(callback) {
this.stores.forEach((store, name) => {
callback(store, name);
});
}
/**
* Get registry statistics
*/
getStats() {
return {
totalStores: this.stores.size,
storeNames: this.getStoreNames(),
registryName: this.name
};
}
/**
* Update internal snapshot
*/
_updateSnapshot() {
this._snapshot = Array.from(this.stores.entries());
}
/**
* Notify all listeners of registry changes
*/
_notifyListeners() {
this.listeners.forEach((listener) => {
try {
listener();
} catch (error) {
console.error("Error in registry listener:", error);
}
});
}
};
/**
* Global default registry instance
*/
const globalStoreRegistry = new StoreRegistry("global");
//#endregion
//#region src/stores/utils/type-guards.ts
function isRefState(value) {
return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean";
}
/**
* DOM Event 객체인지 확인하는 타입 가드
*/
function isDOMEvent(value) {
return value instanceof Event;
}
/**
* Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체)
*/
function isEventLike(value) {
return typeof value === "object" && value !== null && typeof value.preventDefault === "function";
}
/**
* target 프로퍼티를 가진 객체인지 확인하는 타입 가드
*/
function hasTargetProperty(value) {
return typeof value === "object" && value !== null && "target" in value;
}
/**
* DOM Element인지 확인하는 타입 가드
*/
function isDOMElement(value) {
return value instanceof Element;
}
/**
* 객체인지 확인하는 타입 가드 (null 제외)
*/
function isObject(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
/**
* 복합 타입 가드: Event 객체로 의심되는 객체인지 확인
* RefState가 아니면서 Event 관련 속성을 가진 객체를 감지
*/
function isSuspiciousEventObject(value, checkNested = true) {
if (!isObject(value) || isRefState(value)) return false;
if (isEventLikeObject(value)) return true;
if (checkNested) {
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const nestedValue = value[key];
if (isEventLikeObject(nestedValue)) return true;
}
}
return false;
}
/**
* 단일 객체가 이벤트와 같은지 확인
*/
function isEventLikeObject(value) {
if (!isObject(value)) return false;
const hasEventTarget = hasTargetProperty(value);
const hasPreventDefault = isEventLike(value);
const isEvent = isDOMEvent(value);
const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault);
const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value;
const constructorName = value?.constructor?.name;
const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false;
return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor;
}
/**
* 문제가 될 수 있는 속성들을 찾아내는 함수
*/
function findProblematicProperties(value) {
if (!isObject(value)) return [];
const problematicKeys = [];
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const prop = value[key];
if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key);
}
return problematicKeys;
}
/**
* 통합 타입 가드 객체
* 모든 타입 가드 함수들을 하나의 객체로 export
*/
const TypeGuards = {
isRefState,
isDOMEvent,
isEventLike,
hasTargetProperty,
isDOMElement,
isObject,
isSuspiciousEventObject,
findProblematicProperties
};
//#endregion
//#region src/stores/core/Store.ts
/**
* Core Store class for centralized state management with memory leak prevention
*
* Provides reactive state management with subscription capabilities, optimized for
* React integration through useSyncExternalStore. Features advanced cleanup mechanisms,
* automatic resource management, and comprehensive memory leak prevention.
*
* Key Features:
* - Automatic cleanup task registration and execution
* - Memory leak prevention with disposal patterns
* - Race condition protection for async operations
* - Advanced error recovery with exponential backoff
* - Resource monitoring and threshold management
*
* @template T - The type of value stored in this store
*
* @example
* ```typescript
* const userStore = createStore('user', { name: '', age: 0 });
*
* // Register cleanup tasks
* const unregister = userStore.registerCleanup(() => {
* console.log('Cleaning up user store resources');
* });
*
* // Automatic cleanup on disposal
* userStore.dispose();
* ```
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
* @public
*/
var Store = class {
constructor(name, initialValue) {
this.listeners = /* @__PURE__ */ new Set();
this._lastClonedValue = null;
this._lastClonedVersion = 0;
this._version = 0;
this.isUpdating = false;
this.updateQueue = [];
this.notificationMode = "batched";
this.pendingNotification = false;
this.animationFrameId = null;
this.pendingUpdatesCount = 0;
this.cleanupTasks = /* @__PURE__ */ new Set();
this.isDisposed = false;
this.errorCount = 0;
this.lastErrorTime = 0;
this.MAX_ERROR_COUNT = 5;
this.ERROR_RESET_TIME = 6e4;
this.subscriptionRegistry = /* @__PURE__ */ new WeakMap();
this.cloningEnabled = true;
this.subscribe = (listener) => {
if (this.isDisposed) {
console.warn(`Cannot subscribe to disposed store "${this.name}"`);
return () => {};
}
const enhancedListener = () => {
if (this.isDisposed) return;
try {
listener();
if (this.errorCount > 0) this.errorCount = 0;
} catch (error) {
this._handleListenerError(error, listener);
}
};
this.subscriptionRegistry.set(listener, {
subscribedAt: Date.now(),
errorCount: 0,
enhancedListener
});
this.listeners.add(enhancedListener);
return () => {
this.listeners.delete(enhancedListener);
this.subscriptionRegistry.delete(listener);
};
};
this.getSnapshot = () => {
return this._snapshot;
};
this.name = name;
this._value = initialValue;
this._snapshot = this._createSnapshot();
}
/**
* 현재 값 직접 가져오기 (액션 핸들러용)
* 핵심 로직: 불변성을 보장하는 깊은 복사본 반환
*
* @implements lazy-evaluation
* @implements store-immutability
* @memberof architecture-terms
*
* 사용 시나리오: Action handler에서 최신 상태 읽기
* 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨
*/
getValue() {
if (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) {
"use memo";
const stableSelector = (0, react.useCallback)(selector, [selector]);
const stableEqualityFn = (0, react.useCallback)(equalityFn, [equalityFn]);
const selectorWarningShownRef = (0, react.useRef)(false);
if (process.env.NODE_ENV === "development") {
if (selector !== stableSelector && !selectorWarningShownRef.current) {
console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name);
selectorWarningShownRef.current = true;
}
}
const previousValueRef = (0, react.useRef)();
const subscribe = (0, react.useCallback)((callback) => {
return store.subscribe(callback);
}, [store]);
const getSnapshot = (0, react.useCallback)(() => {
try {
const selectedValue = stableSelector(store.getValue());
if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current;
previousValueRef.current = selectedValue;
return selectedValue;
} catch (error) {
if (process.env.NODE_ENV === "development") console.error("useStoreSelector: Error in selector function:", error);
throw error;
}
}, [
store,
stableSelector,
stableEqualityFn
]);
return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
}
//#endregion
//#region src/stores/components/StoreErrorBoundary.tsx
/**
* Store 시스템을 위한 에러 경계 컴포넌트
*
* Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다.
* 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는
* 사용자 친화적인 메시지를 보여줍니다.
*/
var StoreErrorBoundary = class extends react.Component {
constructor(props) {
super(props);
this.resetTimeoutId = null;
this.resetErrorBoundary = () => {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
this.setState({
hasError: false,
error: null,
errorInfo: null,
errorId: null
});
};
this.state = {
hasError: false,
error: null,
errorInfo: null,
errorId: null
};
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error: error instanceof Error && error.name === "ContextActionError" ? error : null,
errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
};
}
componentDidCatch(error, errorInfo) {
if (error.name === "ContextActionError") {
const contextActionError = error;
this.setState({ errorInfo });
this.props.onError?.(contextActionError, errorInfo);
} else {
const contextActionError = require_error_handling.ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, {
component: "StoreErrorBoundary",
stack: error.stack,
componentStack: errorInfo.componentStack
}, error);
this.setState({
error: contextActionError,
errorInfo
});
this.props.onError?.(contextActionError, errorInfo);
}
}
componentDidUpdate(prevProps) {
const { hasError } = this.state;
const { resetOnPropsChange, resetKeys } = this.props;
if (hasError && resetOnPropsChange) {
if (resetKeys) {
if (resetKeys.some((key) => {
return prevProps[key] !== this.props[key];
})) this.resetErrorBoundary();
} else if (prevProps !== this.props) this.resetErrorBoundary();
}
}
componentWillUnmount() {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
}
render() {
const { hasError, error, errorInfo } = this.state;
const { children, fallback } = this.props;
if (hasError) {
if (fallback) {
if (typeof fallback === "function") return fallback(error, errorInfo);
return fallback;
}
return this.renderDefaultFallback();
}
return children;
}
renderDefaultFallback() {
if (process.env.NODE_ENV === "development") return this.renderDevelopmentFallback();
else return this.renderProductionFallback();
}
renderDevelopmentFallback() {
const { error, errorInfo, errorId } = this.state;
const stats = require_error_handling.getErrorStatistics();
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
padding: "20px",
margin: "20px",
border: "2px solid #ff6b6b",
borderRadius: "8px",
backgroundColor: "#ffe0e0",
fontFamily: "monospace"
},
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
style: {
color: "#d63031",
margin: "0 0 10px 0"
},
children: "🚨 Store Error Boundary"
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error ID:" }),
" ",
errorId
]
}),
error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Type:" }),
" ",
error.type,
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Message:" }),
" ",
error.message,
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Timestamp:" }),
" ",
new Date(error.timestamp).toISOString()
]
}),
error?.context && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Context:" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "12px"
},
children: JSON.stringify(error.context, null, 2)
})]
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Error Statistics:" }),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
"Total Errors: ",
stats.totalErrors,
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
"Recent Errors: ",
stats.recentErrors.length
]
}),
errorInfo && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
style: {
cursor: "pointer",
fontWeight: "bold"
},
children: "Component Stack"
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "11px",
whiteSpace: "pre-wrap"
},
children: errorInfo.componentStack
})]
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#00b894",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
fontWeight: "bold"
},
children: "Try Again"
})
]
});
}
renderProductionFallback() {
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
padding: "20px",
textAlign: "center",
backgroundColor: "#f8f9fa",
border: "1px solid #dee2e6",
borderRadius: "8px",
margin: "20px 0"
},
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
style: {
color: "#6c757d",
margin: "0 0 10px 0"
},
children: "Something went wrong"
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
style: {
color: "#6c757d",
margin: "0 0 15px 0"
},
children: "We're sorry, but something unexpected happened. Please try again."
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#007bff",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer"
},
children: "Try Again"
})
]
});
}
};
/**
* Enhanced HOC for automatic Store Error Boundary wrapping with security
*
* @template P - Component props type
* @param WrappedComponent - Component to wrap with error boundary
* @param errorBoundaryProps - Error boundary configuration
* @returns Enhanced component with comprehensive error handling
*/
function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) {
const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, {
...errorBoundaryProps,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WrappedComponent, { ...props })
});
WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`;
return WithStoreErrorBoundaryComponent;
}
/**
* 특정 Store와 연결된 에러 경계 생성 헬퍼
*/
function createStoreErrorBoundary(storeName, customFallback) {
return ({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StoreErrorBoundary, {
fallback: customFallback,
onError: (error, errorInfo) => {
console.group(`Store Error in ${storeName}`);
console.error("Error:", error);
console.error("Component Stack:", errorInfo.componentStack);
console.groupEnd();
},
resetKeys: [storeName],
children
});
}
//#endregion
//#region src/actions/ActionContext.tsx
function createActionContext(contextNameOrConfig = {}, config) {
let effectiveConfig;
let contextName;
if (typeof contextNameOrConfig === "string") {
contextName = contextNameOrConfig;
effectiveConfig = {
...config,
name: config?.name || contextName
};
} else {
effectiveConfig = contextNameOrConfig;
contextName = effectiveConfig.name || "ActionContext";
}
const FactoryActionContext = (0, react.createContext)(null);
const Provider = ({ children }) => {
const actionRegisterRef = (0, react.useRef)(new __context_action_core.ActionRegister(effectiveConfig));
const contextValue = (0, react.useMemo)(() => ({ actionRegisterRef }), []);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FactoryActionContext.Provider, {
value: contextValue,
children
});
};
const useFactoryActionContext = () => {
const context = (0, react.useContext)(FactoryActionContext);
if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider");
return context;
};
/**
* Optimized hook to get stable dispatch functions
*
* Returns stable dispatch functions that prevent re-renders and maintain
* reference equality across component renders.
*
* @returns Object with dispatch and dispatchWithResult functions
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useActionDispatcher = () => {
const { actionRegisterRef } = useFactoryActionContext();
return {
dispatch: (0, react.useCallback)((action, payload, options) => {
if (process.env.NODE_ENV === "development") console.log(`React dispatch called for '${String(action)}':`, {
hasPayload: payload !== void 0,
hasOptions: options !== void 0,
timestamp: (/* @__PURE__ */ new Date()).toISOString()
});
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up.");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatch(action, payload, dispatchOptions);
}, [actionRegisterRef]),
dispatchWithResult: (0, react.useCallback)((action, payload, options) => {
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatchWithResult(action, payload, dispatchOptions);
}, [actionRegisterRef])
};
};
const useAction = () => {
const { dispatch } = useActionDispatcher();
return dispatch;
};
const useActionHandler = (action, handler, config$1) => {
const { actionRegisterRef } = useFactoryActionContext();
const actionId = (0, react.useId)();
const handlerRef = (0, react.useRef)(handler);
handlerRef.current = handler;
const priority = config$1?.priority ?? 0;
const id = config$1?.id || `react_${String(action)}_${actionId}`;
const blocking = config$1?.blocking ?? false;
const once = config$1?.once ?? false;
const debounce = config$1?.debounce;
const throttle = config$1?.throttle;
const stableConfig = (0, react.useMemo)(() => ({
priority,
id,
blocking,
once,
replaceExisting: true,
...debounce !== void 0 && { debounce },
...throttle !== void 0 && { throttle }
}), [
priority,
id,
blocking,
once,
debounce,
throttle
]);
(0, react.useEffect)(() => {
const register = actionRegisterRef.current;
if (!register) return;
const wrapperHandler = (payload, controller) => {
return handlerRef.current(payload, controller);
};
if (process.env.NODE_ENV === "development") console.log(`Registering handler for '${String(action)}'`);
return register.register(action, wrapperHandler, stableConfig);
}, [
action,
actionRegisterRef,
stableConfig
]);
};
/**
* Hook that provides direct access to the ActionRegister instance
*
* This hook is useful when you need to:
* - Register multiple handlers dynamically
* - Access other ActionRegister methods like clearAction, getHandlers, etc.
* - Implement complex handler registration logic
* - Have more control over the registration lifecycle
*
* @returns ActionRegister instance or null if not initialized
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useFactoryActionRegister = () => {
return useFactoryActionContext().actionRegisterRef.current;
};
/**
* Hook that provides access to the dispatchWithResult function
*
* This hook returns a function that dispatches actions and returns detailed
* execution results including collected handler results, execution metadata,
* and error information.
*
* @returns dispatchWithResult function with full type safety
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result
*/
const useFactoryActionDispatchWithResult = () => {
const context = useFactoryActionContext();
const activeControllersRef = (0, react.useRef)(/* @__PURE__ */ new Set());
const dispatch = (0, react.useCallback)((action, payload, options) => {
const register = context.actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
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 { ErrorHandlers, compareValues, getErrorStatistics, produce, safeGet, safeSet } from "./error-handling-CkdfKCZ0.js";
import React, { Component, createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useSyncExternalStore } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { ActionRegister } from "@context-action/core";
//#region src/stores/core/StoreRegistry.ts
/**
* Centralized store registry for managing multiple Store instances
*/
var StoreRegistry = class {
constructor(name = "default") {
this.stores = /* @__PURE__ */ new Map();
this.metadata = /* @__PURE__ */ new WeakMap();
this.listeners = /* @__PURE__ */ new Set();
this._snapshot = [];
this.name = name;
}
/**
* Subscribe to registry changes for reactive updates
*/
subscribe(listener) {
this.listeners.add(listener);
return () => {
this.listeners.delete(listener);
};
}
/**
* Register a new store in the registry
*/
register(name, store, metadata) {
if (this.stores.has(name)) {
if (this.stores.get(name)) {}
}
this.stores.set(name, store);
if (metadata) this.metadata.set(store, {
registeredAt: Date.now(),
name,
...metadata
});
this._updateSnapshot();
this._notifyListeners();
}
/**
* Unregister a store from the registry
*/
unregister(name) {
if (!this.stores.get(name)) return false;
this.stores.delete(name);
this._updateSnapshot();
this._notifyListeners();
return true;
}
/**
* Get a store by name
*/
getStore(name) {
return this.stores.get(name);
}
/**
* Check if a store exists
*/
hasStore(name) {
return this.stores.has(name);
}
/**
* Get all registered store names
*/
getStoreNames() {
return Array.from(this.stores.keys());
}
/**
* Get all stores as entries
*/
getAllStores() {
return new Map(this.stores);
}
/**
* Get store metadata
*/
getStoreMetadata(nameOrStore) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
return store ? this.metadata.get(store) : void 0;
}
/**
* Update store metadata
*/
updateStoreMetadata(nameOrStore, metadata) {
const store = typeof nameOrStore === "string" ? this.stores.get(nameOrStore) : nameOrStore;
if (!store) return false;
const currentMetadata = this.metadata.get(store);
this.metadata.set(store, {
registeredAt: Date.now(),
name: typeof nameOrStore === "string" ? nameOrStore : currentMetadata?.name || "unknown",
...currentMetadata,
...metadata
});
return true;
}
/**
* Get registry snapshot for React integration
*/
getSnapshot() {
return this._snapshot;
}
/**
* Clear all stores from registry
*/
clear() {
this.stores.clear();
this._updateSnapshot();
this._notifyListeners();
}
/**
* Dispose registry and cleanup resources
*/
dispose() {
this.clear();
this.listeners.clear();
}
/**
* Get count of registered stores
*/
getStoreCount() {
return this.stores.size;
}
/**
* Iterate over all stores
*/
forEach(callback) {
this.stores.forEach((store, name) => {
callback(store, name);
});
}
/**
* Get registry statistics
*/
getStats() {
return {
totalStores: this.stores.size,
storeNames: this.getStoreNames(),
registryName: this.name
};
}
/**
* Update internal snapshot
*/
_updateSnapshot() {
this._snapshot = Array.from(this.stores.entries());
}
/**
* Notify all listeners of registry changes
*/
_notifyListeners() {
this.listeners.forEach((listener) => {
try {
listener();
} catch (error) {
console.error("Error in registry listener:", error);
}
});
}
};
/**
* Global default registry instance
*/
const globalStoreRegistry = new StoreRegistry("global");
//#endregion
//#region src/stores/utils/type-guards.ts
function isRefState(value) {
return typeof value === "object" && value !== null && "target" in value && "isReady" in value && "isMounted" in value && "mountPromise" in value && typeof value.isReady === "boolean" && typeof value.isMounted === "boolean";
}
/**
* DOM Event 객체인지 확인하는 타입 가드
*/
function isDOMEvent(value) {
return value instanceof Event;
}
/**
* Event-like 객체인지 확인하는 타입 가드 (preventDefault 메서드를 가진 객체)
*/
function isEventLike(value) {
return typeof value === "object" && value !== null && typeof value.preventDefault === "function";
}
/**
* target 프로퍼티를 가진 객체인지 확인하는 타입 가드
*/
function hasTargetProperty(value) {
return typeof value === "object" && value !== null && "target" in value;
}
/**
* DOM Element인지 확인하는 타입 가드
*/
function isDOMElement(value) {
return value instanceof Element;
}
/**
* 객체인지 확인하는 타입 가드 (null 제외)
*/
function isObject(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
/**
* 복합 타입 가드: Event 객체로 의심되는 객체인지 확인
* RefState가 아니면서 Event 관련 속성을 가진 객체를 감지
*/
function isSuspiciousEventObject(value, checkNested = true) {
if (!isObject(value) || isRefState(value)) return false;
if (isEventLikeObject(value)) return true;
if (checkNested) {
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const nestedValue = value[key];
if (isEventLikeObject(nestedValue)) return true;
}
}
return false;
}
/**
* 단일 객체가 이벤트와 같은지 확인
*/
function isEventLikeObject(value) {
if (!isObject(value)) return false;
const hasEventTarget = hasTargetProperty(value);
const hasPreventDefault = isEventLike(value);
const isEvent = isDOMEvent(value);
const hasEventProperties = "type" in value && typeof value.type === "string" && (hasEventTarget || hasPreventDefault);
const hasReactMarkers = "nativeEvent" in value || "persist" in value || "$$typeof" in value || "_reactInternalFiber" in value || "_owner" in value;
const constructorName = value?.constructor?.name;
const hasEventConstructor = constructorName ? constructorName.includes("Event") || constructorName === "SyntheticEvent" || constructorName.includes("MouseEvent") || constructorName.includes("KeyboardEvent") || constructorName.includes("TouchEvent") || constructorName.includes("FocusEvent") || constructorName.includes("SubmitEvent") : false;
return isEvent || hasEventProperties || hasReactMarkers || hasEventConstructor;
}
/**
* 문제가 될 수 있는 속성들을 찾아내는 함수
*/
function findProblematicProperties(value) {
if (!isObject(value)) return [];
const problematicKeys = [];
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) {
const prop = value[key];
if (isDOMElement(prop) || isDOMEvent(prop) || isObject(prop) && hasTargetProperty(prop)) problematicKeys.push(key);
}
return problematicKeys;
}
/**
* 통합 타입 가드 객체
* 모든 타입 가드 함수들을 하나의 객체로 export
*/
const TypeGuards = {
isRefState,
isDOMEvent,
isEventLike,
hasTargetProperty,
isDOMElement,
isObject,
isSuspiciousEventObject,
findProblematicProperties
};
//#endregion
//#region src/stores/core/Store.ts
/**
* Core Store class for centralized state management with memory leak prevention
*
* Provides reactive state management with subscription capabilities, optimized for
* React integration through useSyncExternalStore. Features advanced cleanup mechanisms,
* automatic resource management, and comprehensive memory leak prevention.
*
* Key Features:
* - Automatic cleanup task registration and execution
* - Memory leak prevention with disposal patterns
* - Race condition protection for async operations
* - Advanced error recovery with exponential backoff
* - Resource monitoring and threshold management
*
* @template T - The type of value stored in this store
*
* @example
* ```typescript
* const userStore = createStore('user', { name: '', age: 0 });
*
* // Register cleanup tasks
* const unregister = userStore.registerCleanup(() => {
* console.log('Cleaning up user store resources');
* });
*
* // Automatic cleanup on disposal
* userStore.dispose();
* ```
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/store/basic-usage
* @public
*/
var Store = class {
constructor(name, initialValue) {
this.listeners = /* @__PURE__ */ new Set();
this._lastClonedValue = null;
this._lastClonedVersion = 0;
this._version = 0;
this.isUpdating = false;
this.updateQueue = [];
this.notificationMode = "batched";
this.pendingNotification = false;
this.animationFrameId = null;
this.pendingUpdatesCount = 0;
this.cleanupTasks = /* @__PURE__ */ new Set();
this.isDisposed = false;
this.errorCount = 0;
this.lastErrorTime = 0;
this.MAX_ERROR_COUNT = 5;
this.ERROR_RESET_TIME = 6e4;
this.subscriptionRegistry = /* @__PURE__ */ new WeakMap();
this.cloningEnabled = true;
this.subscribe = (listener) => {
if (this.isDisposed) {
console.warn(`Cannot subscribe to disposed store "${this.name}"`);
return () => {};
}
const enhancedListener = () => {
if (this.isDisposed) return;
try {
listener();
if (this.errorCount > 0) this.errorCount = 0;
} catch (error) {
this._handleListenerError(error, listener);
}
};
this.subscriptionRegistry.set(listener, {
subscribedAt: Date.now(),
errorCount: 0,
enhancedListener
});
this.listeners.add(enhancedListener);
return () => {
this.listeners.delete(enhancedListener);
this.subscriptionRegistry.delete(listener);
};
};
this.getSnapshot = () => {
return this._snapshot;
};
this.name = name;
this._value = initialValue;
this._snapshot = this._createSnapshot();
}
/**
* 현재 값 직접 가져오기 (액션 핸들러용)
* 핵심 로직: 불변성을 보장하는 깊은 복사본 반환
*
* @implements lazy-evaluation
* @implements store-immutability
* @memberof architecture-terms
*
* 사용 시나리오: Action handler에서 최신 상태 읽기
* 보안 강화: 외부에서 반환된 값을 수정해도 Store 내부 상태는 보호됨
*/
getValue() {
if (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) {
"use memo";
const stableSelector = useCallback(selector, [selector]);
const stableEqualityFn = useCallback(equalityFn, [equalityFn]);
const selectorWarningShownRef = useRef(false);
if (selector !== stableSelector && !selectorWarningShownRef.current) {
console.warn("useStoreSelector: selector function changed. Consider wrapping it with useCallback to avoid unnecessary recalculations.", "Store:", store.name);
selectorWarningShownRef.current = true;
}
const previousValueRef = useRef();
const subscribe = useCallback((callback) => {
return store.subscribe(callback);
}, [store]);
const getSnapshot = useCallback(() => {
try {
const selectedValue = stableSelector(store.getValue());
if (previousValueRef.current !== void 0 && stableEqualityFn(previousValueRef.current, selectedValue)) return previousValueRef.current;
previousValueRef.current = selectedValue;
return selectedValue;
} catch (error) {
console.error("useStoreSelector: Error in selector function:", error);
throw error;
}
}, [
store,
stableSelector,
stableEqualityFn
]);
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
}
//#endregion
//#region src/stores/components/StoreErrorBoundary.tsx
/**
* Store 시스템을 위한 에러 경계 컴포넌트
*
* Store 관련 에러들을 캐치하고 적절한 fallback UI를 제공합니다.
* 개발 모드에서는 자세한 에러 정보를 표시하고, 프로덕션에서는
* 사용자 친화적인 메시지를 보여줍니다.
*/
var StoreErrorBoundary = class extends Component {
constructor(props) {
super(props);
this.resetTimeoutId = null;
this.resetErrorBoundary = () => {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
this.setState({
hasError: false,
error: null,
errorInfo: null,
errorId: null
});
};
this.state = {
hasError: false,
error: null,
errorInfo: null,
errorId: null
};
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error: error instanceof Error && error.name === "ContextActionError" ? error : null,
errorId: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
};
}
componentDidCatch(error, errorInfo) {
if (error.name === "ContextActionError") {
const contextActionError = error;
this.setState({ errorInfo });
this.props.onError?.(contextActionError, errorInfo);
} else {
const contextActionError = ErrorHandlers.store(`Unhandled error in Store component: ${error.message}`, {
component: "StoreErrorBoundary",
stack: error.stack,
componentStack: errorInfo.componentStack
}, error);
this.setState({
error: contextActionError,
errorInfo
});
this.props.onError?.(contextActionError, errorInfo);
}
}
componentDidUpdate(prevProps) {
const { hasError } = this.state;
const { resetOnPropsChange, resetKeys } = this.props;
if (hasError && resetOnPropsChange) {
if (resetKeys) {
if (resetKeys.some((key) => {
return prevProps[key] !== this.props[key];
})) this.resetErrorBoundary();
} else if (prevProps !== this.props) this.resetErrorBoundary();
}
}
componentWillUnmount() {
if (this.resetTimeoutId) clearTimeout(this.resetTimeoutId);
}
render() {
const { hasError, error, errorInfo } = this.state;
const { children, fallback } = this.props;
if (hasError) {
if (fallback) {
if (typeof fallback === "function") return fallback(error, errorInfo);
return fallback;
}
return this.renderDefaultFallback();
}
return children;
}
renderDefaultFallback() {
return this.renderDevelopmentFallback();
}
renderDevelopmentFallback() {
const { error, errorInfo, errorId } = this.state;
const stats = getErrorStatistics();
return /* @__PURE__ */ jsxs("div", {
style: {
padding: "20px",
margin: "20px",
border: "2px solid #ff6b6b",
borderRadius: "8px",
backgroundColor: "#ffe0e0",
fontFamily: "monospace"
},
children: [
/* @__PURE__ */ jsx("h2", {
style: {
color: "#d63031",
margin: "0 0 10px 0"
},
children: "🚨 Store Error Boundary"
}),
/* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ jsx("strong", { children: "Error ID:" }),
" ",
errorId
]
}),
error && /* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ jsx("strong", { children: "Error Type:" }),
" ",
error.type,
/* @__PURE__ */ jsx("br", {}),
/* @__PURE__ */ jsx("strong", { children: "Message:" }),
" ",
error.message,
/* @__PURE__ */ jsx("br", {}),
/* @__PURE__ */ jsx("strong", { children: "Timestamp:" }),
" ",
new Date(error.timestamp).toISOString()
]
}),
error?.context && /* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ jsx("strong", { children: "Context:" }), /* @__PURE__ */ jsx("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "12px"
},
children: JSON.stringify(error.context, null, 2)
})]
}),
/* @__PURE__ */ jsxs("div", {
style: { marginBottom: "15px" },
children: [
/* @__PURE__ */ jsx("strong", { children: "Error Statistics:" }),
/* @__PURE__ */ jsx("br", {}),
"Total Errors: ",
stats.totalErrors,
/* @__PURE__ */ jsx("br", {}),
"Recent Errors: ",
stats.recentErrors.length
]
}),
errorInfo && /* @__PURE__ */ jsxs("details", {
style: { marginBottom: "15px" },
children: [/* @__PURE__ */ jsx("summary", {
style: {
cursor: "pointer",
fontWeight: "bold"
},
children: "Component Stack"
}), /* @__PURE__ */ jsx("pre", {
style: {
background: "#f8f9fa",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
fontSize: "11px",
whiteSpace: "pre-wrap"
},
children: errorInfo.componentStack
})]
}),
/* @__PURE__ */ jsx("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#00b894",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
fontWeight: "bold"
},
children: "Try Again"
})
]
});
}
renderProductionFallback() {
return /* @__PURE__ */ jsxs("div", {
style: {
padding: "20px",
textAlign: "center",
backgroundColor: "#f8f9fa",
border: "1px solid #dee2e6",
borderRadius: "8px",
margin: "20px 0"
},
children: [
/* @__PURE__ */ jsx("h3", {
style: {
color: "#6c757d",
margin: "0 0 10px 0"
},
children: "Something went wrong"
}),
/* @__PURE__ */ jsx("p", {
style: {
color: "#6c757d",
margin: "0 0 15px 0"
},
children: "We're sorry, but something unexpected happened. Please try again."
}),
/* @__PURE__ */ jsx("button", {
onClick: this.resetErrorBoundary,
style: {
padding: "8px 16px",
backgroundColor: "#007bff",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer"
},
children: "Try Again"
})
]
});
}
};
/**
* Enhanced HOC for automatic Store Error Boundary wrapping with security
*
* @template P - Component props type
* @param WrappedComponent - Component to wrap with error boundary
* @param errorBoundaryProps - Error boundary configuration
* @returns Enhanced component with comprehensive error handling
*/
function withStoreErrorBoundary(WrappedComponent, errorBoundaryProps) {
const WithStoreErrorBoundaryComponent = (props) => /* @__PURE__ */ jsx(StoreErrorBoundary, {
...errorBoundaryProps,
children: /* @__PURE__ */ jsx(WrappedComponent, { ...props })
});
WithStoreErrorBoundaryComponent.displayName = `withStoreErrorBoundary(${WrappedComponent.displayName || WrappedComponent.name})`;
return WithStoreErrorBoundaryComponent;
}
/**
* 특정 Store와 연결된 에러 경계 생성 헬퍼
*/
function createStoreErrorBoundary(storeName, customFallback) {
return ({ children }) => /* @__PURE__ */ jsx(StoreErrorBoundary, {
fallback: customFallback,
onError: (error, errorInfo) => {
console.group(`Store Error in ${storeName}`);
console.error("Error:", error);
console.error("Component Stack:", errorInfo.componentStack);
console.groupEnd();
},
resetKeys: [storeName],
children
});
}
//#endregion
//#region src/actions/ActionContext.tsx
function createActionContext(contextNameOrConfig = {}, config) {
let effectiveConfig;
let contextName;
if (typeof contextNameOrConfig === "string") {
contextName = contextNameOrConfig;
effectiveConfig = {
...config,
name: config?.name || contextName
};
} else {
effectiveConfig = contextNameOrConfig;
contextName = effectiveConfig.name || "ActionContext";
}
const FactoryActionContext = createContext(null);
const Provider = ({ children }) => {
const actionRegisterRef = useRef(new ActionRegister(effectiveConfig));
const contextValue = useMemo(() => ({ actionRegisterRef }), []);
return /* @__PURE__ */ jsx(FactoryActionContext.Provider, {
value: contextValue,
children
});
};
const useFactoryActionContext = () => {
const context = useContext(FactoryActionContext);
if (!context) throw new Error("useFactoryActionContext must be used within a factory ActionContext Provider");
return context;
};
/**
* Optimized hook to get stable dispatch functions
*
* Returns stable dispatch functions that prevent re-renders and maintain
* reference equality across component renders.
*
* @returns Object with dispatch and dispatchWithResult functions
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useActionDispatcher = () => {
const { actionRegisterRef } = useFactoryActionContext();
return {
dispatch: useCallback((action, payload, options) => {
console.log(`React dispatch called for '${String(action)}':`, {
hasPayload: payload !== void 0,
hasOptions: options !== void 0,
timestamp: (/* @__PURE__ */ new Date()).toISOString()
});
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up.");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatch(action, payload, dispatchOptions);
}, [actionRegisterRef]),
dispatchWithResult: useCallback((action, payload, options) => {
const register = actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
const dispatchOptions = {
...options,
...options?.signal ? {} : { autoAbort: {
enabled: true,
allowHandlerAbort: true
} }
};
return register.dispatchWithResult(action, payload, dispatchOptions);
}, [actionRegisterRef])
};
};
const useAction = () => {
const { dispatch } = useActionDispatcher();
return dispatch;
};
const useActionHandler = (action, handler, config$1) => {
const { actionRegisterRef } = useFactoryActionContext();
const actionId = useId();
const handlerRef = useRef(handler);
handlerRef.current = handler;
const priority = config$1?.priority ?? 0;
const id = config$1?.id || `react_${String(action)}_${actionId}`;
const blocking = config$1?.blocking ?? false;
const once = config$1?.once ?? false;
const debounce = config$1?.debounce;
const throttle = config$1?.throttle;
const stableConfig = useMemo(() => ({
priority,
id,
blocking,
once,
replaceExisting: true,
...debounce !== void 0 && { debounce },
...throttle !== void 0 && { throttle }
}), [
priority,
id,
blocking,
once,
debounce,
throttle
]);
useEffect(() => {
const register = actionRegisterRef.current;
if (!register) return;
const wrapperHandler = (payload, controller) => {
return handlerRef.current(payload, controller);
};
console.log(`Registering handler for '${String(action)}'`);
return register.register(action, wrapperHandler, stableConfig);
}, [
action,
actionRegisterRef,
stableConfig
]);
};
/**
* Hook that provides direct access to the ActionRegister instance
*
* This hook is useful when you need to:
* - Register multiple handlers dynamically
* - Access other ActionRegister methods like clearAction, getHandlers, etc.
* - Implement complex handler registration logic
* - Have more control over the registration lifecycle
*
* @returns ActionRegister instance or null if not initialized
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-access
*/
const useFactoryActionRegister = () => {
return useFactoryActionContext().actionRegisterRef.current;
};
/**
* Hook that provides access to the dispatchWithResult function
*
* This hook returns a function that dispatches actions and returns detailed
* execution results including collected handler results, execution metadata,
* and error information.
*
* @returns dispatchWithResult function with full type safety
*
* @see https://mineclover.github.io/context-action/en/guide/patterns/action/dispatch-with-result
*/
const useFactoryActionDispatchWithResult = () => {
const context = useFactoryActionContext();
const activeControllersRef = useRef(/* @__PURE__ */ new Set());
const dispatch = useCallback((action, payload, options) => {
const register = context.actionRegisterRef.current;
if (!register) throw new Error("ActionRegister not initialized");
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-BuVbb-bA.js.map

Sorry, the diff of this file is too big to display