@context-action/react
Advanced tools
+149
-15
@@ -30,14 +30,78 @@ //#region rolldown:runtime | ||
| /** | ||
| * ActionRegister를 Context로 공유할 수 있는 헬퍼 함수 | ||
| * @returns Provider, hooks를 포함한 객체 | ||
| * Create a React Context for sharing ActionRegister instance across components | ||
| * @template T - The action payload map type | ||
| * @param config 로거 설정 (선택사항) | ||
| * @returns Object containing Provider component and hooks for action management | ||
| * @example | ||
| * ```typescript | ||
| * interface AppActions extends ActionPayloadMap { | ||
| * increment: void; | ||
| * setCount: number; | ||
| * } | ||
| * | ||
| * const { Provider, useAction, useActionHandler } = createActionContext<AppActions>({ | ||
| * logLevel: LogLevel.DEBUG, | ||
| * useOtel: true | ||
| * }); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <Provider> | ||
| * <Counter /> | ||
| * </Provider> | ||
| * ); | ||
| * } | ||
| * | ||
| * function Counter() { | ||
| * const [count, setCount] = useState(0); | ||
| * const dispatch = useAction(); | ||
| * | ||
| * useActionHandler('increment', () => setCount(prev => prev + 1)); | ||
| * | ||
| * return ( | ||
| * <button onClick={() => dispatch('increment')}> | ||
| * Count: {count} | ||
| * </button> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| function createActionContext() { | ||
| function createActionContext(config) { | ||
| const ActionContext = (0, react.createContext)(null); | ||
| /** | ||
| * Provider 컴포넌트 | ||
| * ActionRegister 인스턴스를 Context로 제공합니다 | ||
| */ | ||
| const Provider = ({ children }) => { | ||
| const actionRegisterRef = (0, react.useRef)(new __context_action_core.ActionRegister()); | ||
| const envLogLevel = (0, __context_action_core.getLogLevelFromEnv)(); | ||
| const configLogLevel = config?.logLevel ?? envLogLevel; | ||
| let logger; | ||
| if (config?.logger) logger = config.logger; | ||
| else if (config?.useOtel) logger = new __context_action_core.OtelConsoleLogger(configLogLevel); | ||
| else logger = new __context_action_core.ConsoleLogger(configLogLevel); | ||
| if (config?.otelContext && logger instanceof __context_action_core.OtelConsoleLogger) logger.setContext(config.otelContext); | ||
| const actionRegisterRef = (0, react.useRef)(new __context_action_core.ActionRegister({ | ||
| logger, | ||
| logLevel: configLogLevel, | ||
| useOtel: config?.useOtel, | ||
| otelContext: config?.otelContext | ||
| })); | ||
| logger.debug("ActionContext Provider initialized", { | ||
| logLevel: configLogLevel, | ||
| useOtel: config?.useOtel ?? false, | ||
| hasOtelContext: !!config?.otelContext | ||
| }); | ||
| return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionContext.Provider, { | ||
| value: { actionRegisterRef }, | ||
| value: { | ||
| actionRegisterRef, | ||
| logger | ||
| }, | ||
| children | ||
| }); | ||
| }; | ||
| /** | ||
| * Context 접근 hook | ||
| * @returns ActionContextType - ActionRegister 참조를 포함한 컨텍스트 | ||
| * @throws Error - Provider 외부에서 사용될 경우 | ||
| */ | ||
| const useActionContext = () => { | ||
@@ -48,21 +112,73 @@ const context = (0, react.useContext)(ActionContext); | ||
| }; | ||
| /** | ||
| * dispatch 함수 반환 hook | ||
| * @returns ActionRegister의 dispatch 함수 | ||
| * @throws Error - Provider 외부에서 사용될 경우 | ||
| */ | ||
| const useAction = () => { | ||
| const { actionRegisterRef } = useActionContext(); | ||
| return actionRegisterRef.current; | ||
| const context = (0, react.useContext)(ActionContext); | ||
| if (!context) throw new Error("useAction must be used within Provider. Make sure your component is wrapped with the ActionContext Provider."); | ||
| /** strict mode */ | ||
| if (!(context.actionRegisterRef.current instanceof __context_action_core.ActionRegister)) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| const dispatch = (0, react.useMemo)(() => { | ||
| if (context.actionRegisterRef.current instanceof __context_action_core.ActionRegister) { | ||
| const boundDispatch = context.actionRegisterRef.current.dispatch.bind(context.actionRegisterRef.current); | ||
| return ((action, payload) => { | ||
| context.logger.trace("useAction dispatch called", { | ||
| action, | ||
| payload | ||
| }); | ||
| return boundDispatch(action, payload); | ||
| }); | ||
| } | ||
| return (...args) => { | ||
| context.logger.error("ActionRegister is not initialized", { args }); | ||
| throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| }; | ||
| }, [context.actionRegisterRef.current, context.logger]); | ||
| return dispatch; | ||
| }; | ||
| const useActionHandler = (action, handler, config) => { | ||
| const actionRegister = useAction(); | ||
| /** | ||
| * Action Handler 등록 hook | ||
| * @template K - 액션 키 타입 | ||
| * @param action - 등록할 액션 이름 | ||
| * @param handler - 액션 처리 함수 | ||
| * @param config - 핸들러 설정 (선택사항) | ||
| * @description 성능 최적화를 위해 handler는 useCallback으로 메모이제이션하는 것을 권장합니다 | ||
| */ | ||
| const useActionHandler = (action, handler, config$1) => { | ||
| const { actionRegisterRef, logger } = useActionContext(); | ||
| const componentId = (0, react.useId)(); | ||
| (0, react.useEffect)(() => { | ||
| if (!actionRegisterRef.current) { | ||
| logger.error("ActionRegister is not initialized in useActionHandler"); | ||
| throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| } | ||
| logger.debug("useActionHandler registering", { | ||
| action: String(action), | ||
| componentId, | ||
| priority: config$1?.priority ?? 0, | ||
| blocking: config$1?.blocking ?? false | ||
| }); | ||
| const actionRegister = actionRegisterRef.current; | ||
| const unregister = actionRegister.register(action, handler, { | ||
| ...config, | ||
| id: config?.id || componentId | ||
| ...config$1, | ||
| id: config$1?.id || componentId | ||
| }); | ||
| return unregister; | ||
| return () => { | ||
| logger.debug("useActionHandler unregistering", { | ||
| action: String(action), | ||
| componentId | ||
| }); | ||
| unregister(); | ||
| }; | ||
| }, [ | ||
| action, | ||
| handler, | ||
| config, | ||
| config$1?.id, | ||
| config$1?.priority, | ||
| config$1?.blocking, | ||
| componentId, | ||
| actionRegister | ||
| actionRegisterRef.current, | ||
| logger | ||
| ]); | ||
@@ -85,2 +201,20 @@ }; | ||
| }); | ||
| exports.createActionContext = createActionContext; | ||
| Object.defineProperty(exports, 'ConsoleLogger', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __context_action_core.ConsoleLogger; | ||
| } | ||
| }); | ||
| Object.defineProperty(exports, 'OtelConsoleLogger', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __context_action_core.OtelConsoleLogger; | ||
| } | ||
| }); | ||
| exports.createActionContext = createActionContext; | ||
| Object.defineProperty(exports, 'getLogLevelFromEnv', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __context_action_core.getLogLevelFromEnv; | ||
| } | ||
| }); |
+55
-7
@@ -1,2 +0,2 @@ | ||
| import { ActionHandler, ActionHandler as ActionHandler$1, ActionPayloadMap, ActionPayloadMap as ActionPayloadMap$1, ActionRegister, ActionRegister as ActionRegister$1, HandlerConfig, HandlerConfig as HandlerConfig$1, PipelineController } from "@context-action/core"; | ||
| import { ActionHandler, ActionHandler as ActionHandler$1, ActionPayloadMap, ActionPayloadMap as ActionPayloadMap$1, ActionRegister, ActionRegister as ActionRegister$1, ConsoleLogger, HandlerConfig, HandlerConfig as HandlerConfig$1, LogLevel, LogLevel as LogLevel$1, Logger, Logger as Logger$1, OtelConsoleLogger, OtelContext, OtelContext as OtelContext$1, PipelineController, getLogLevelFromEnv } from "@context-action/core"; | ||
| import React, { ReactNode } from "react"; | ||
@@ -7,2 +7,15 @@ | ||
| /** | ||
| * Configuration options for createActionContext | ||
| */ | ||
| interface ActionContextConfig { | ||
| /** Custom logger implementation. Defaults to ConsoleLogger */ | ||
| logger?: Logger$1; | ||
| /** Log level for the logger. Defaults to ERROR if not provided */ | ||
| logLevel?: LogLevel$1; | ||
| /** OpenTelemetry context for tracing */ | ||
| otelContext?: OtelContext$1; | ||
| /** Whether to use OTEL-aware logger. Defaults to false */ | ||
| useOtel?: boolean; | ||
| } | ||
| /** | ||
| * Context type for ActionRegister | ||
@@ -12,2 +25,3 @@ */ | ||
| actionRegisterRef: React.RefObject<ActionRegister$1<T>>; | ||
| logger: Logger$1; | ||
| } | ||
@@ -22,14 +36,48 @@ /** | ||
| useActionContext: () => ActionContextType<T>; | ||
| useAction: () => ActionRegister$1<T>; | ||
| useAction: () => ActionRegister$1<T>['dispatch']; | ||
| useActionHandler: <K extends keyof T>(action: K, handler: ActionHandler$1<T[K]>, config?: HandlerConfig$1) => void; | ||
| } | ||
| /** | ||
| * ActionRegister를 Context로 공유할 수 있는 헬퍼 함수 | ||
| * @returns Provider, hooks를 포함한 객체 | ||
| * Create a React Context for sharing ActionRegister instance across components | ||
| * @template T - The action payload map type | ||
| * @param config 로거 설정 (선택사항) | ||
| * @returns Object containing Provider component and hooks for action management | ||
| * @example | ||
| * ```typescript | ||
| * interface AppActions extends ActionPayloadMap { | ||
| * increment: void; | ||
| * setCount: number; | ||
| * } | ||
| * | ||
| * const { Provider, useAction, useActionHandler } = createActionContext<AppActions>({ | ||
| * logLevel: LogLevel.DEBUG, | ||
| * useOtel: true | ||
| * }); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <Provider> | ||
| * <Counter /> | ||
| * </Provider> | ||
| * ); | ||
| * } | ||
| * | ||
| * function Counter() { | ||
| * const [count, setCount] = useState(0); | ||
| * const dispatch = useAction(); | ||
| * | ||
| * useActionHandler('increment', () => setCount(prev => prev + 1)); | ||
| * | ||
| * return ( | ||
| * <button onClick={() => dispatch('increment')}> | ||
| * Count: {count} | ||
| * </button> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function createActionContext<T extends ActionPayloadMap$1 = ActionPayloadMap$1>(): ActionContextReturn<T>; | ||
| declare function createActionContext<T extends ActionPayloadMap$1 = ActionPayloadMap$1>(config?: ActionContextConfig): ActionContextReturn<T>; | ||
| //# sourceMappingURL=ActionContext.d.ts.map | ||
| //#endregion | ||
| export { ActionContextReturn, ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, type HandlerConfig, type PipelineController, createActionContext }; | ||
| export { ActionContextConfig, ActionContextReturn, ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, ConsoleLogger, type HandlerConfig, type LogLevel, type Logger, OtelConsoleLogger, type OtelContext, type PipelineController, createActionContext, getLogLevelFromEnv }; | ||
| //# sourceMappingURL=index.d.cts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.cts","names":[],"sources":["../src/ActionContext.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AAAkC,UAAjB,iBAAiB,CAAA,UAAW,kBAAX,GAA8B,kBAA9B,CAAA,CAAA;EAAA,iBAAW,EACxB,KAAA,CAAM,SADkB,CACR,gBADQ,CACO,CADP,CAAA,CAAA;;;;;AACT,UAMnB,mBANmB,CAAA,UAMW,kBANX,GAM8B,kBAN9B,CAAA,CAAA;EAMnB,QAAA,EACL,KAAA,CAAM,EADD,CAAA;IAAmB,QAAA,EACH,SADG;EAAA,CAAA,CAAA;EAA2B,gBAAG,EAAA,GAAA,GAExC,iBAFwC,CAEtB,CAFsB,CAAA;EAAgB,SACjD,EAAA,GAAA,GAEd,gBAFc,CAEC,CAFD,CAAA;EAAS,gBAAxB,EAAA,CAAA,UAAA,MAGmB,CAHnB,CAAA,CAAA,MAAA,EAIN,CAJM,EAAA,OAAA,EAKL,eALK,CAKS,CALT,CAKW,CALX,CAAA,CAAA,EAAA,MAAA,CAAA,EAML,eANK,EAAA,GAAA,IAAA;;;;;;AAIN,iBAUI,mBAVJ,CAAA,UAUkC,kBAVlC,GAUqD,kBAVrD,CAAA,CAAA,CAAA,EAU0E,mBAV1E,CAU8F,CAV9F,CAAA"} | ||
| {"version":3,"file":"index.d.cts","names":[],"sources":["../src/ActionContext.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AAAoC,UAAnB,mBAAA,CAAmB;EAAA;EAEnB,MAEJ,CAAA,EAFF,QAEE;EAAQ;EAEM,QAAA,CAAA,EAFd,UAEc;EAQV;EAAiB,WAAA,CAAA,EARlB,aAQkB;EAAA;EAA2B,OAAG,CAAA,EAAA,OAAA;;;;;AAEhD,UAFC,iBAED,CAAA,UAF6B,kBAE7B,GAFgD,kBAEhD,CAAA,CAAA;EAMC,iBAAA,EAPI,KAAA,CAAM,SAOS,CAPC,gBAOD,CAPgB,CAOhB,CAAA,CAAA;EAAA,MAAA,EAN1B,QAM0B;;;;;AAEQ,UAF3B,mBAE2B,CAAA,UAFG,kBAEH,GAFsB,kBAEtB,CAAA,CAAA;EAAC,QAAnB,EADd,KAAA,CAAM,EACQ,CAAA;IACQ,QAAA,EAFD,SAEC;EAAC,CAAA,CAAA;EAAF,gBACI,EAAA,GAAA,GAFX,iBAEW,CAFO,CAEP,CAAA;EAAC,SAC1B,EAAA,GAAA,GAFO,gBAEP,CAFsB,CAEtB,CAAA,CAAA,UAAA,CAAA;EAAC,gBACc,EAAA,CAAA,UAAA,MAFU,CAEV,CAAA,CAAA,MAAA,EADf,CACe,EAAA,OAAA,EAAd,eAAc,CAAA,CAAA,CAAE,CAAF,CAAA,CAAA,EAAA,MAAA,CAAA,EACd,eADc,EAAA,GAAA,IAAA;;;;AACD;AA2C1B;;;;;;;AAAqI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAArH,8BAA8B,qBAAmB,6BAA2B,sBAAsB,oBAAoB"} |
+55
-7
@@ -1,2 +0,2 @@ | ||
| import { ActionHandler, ActionHandler as ActionHandler$1, ActionPayloadMap, ActionPayloadMap as ActionPayloadMap$1, ActionRegister, ActionRegister as ActionRegister$1, HandlerConfig, HandlerConfig as HandlerConfig$1, PipelineController } from "@context-action/core"; | ||
| import { ActionHandler, ActionHandler as ActionHandler$1, ActionPayloadMap, ActionPayloadMap as ActionPayloadMap$1, ActionRegister, ActionRegister as ActionRegister$1, ConsoleLogger, HandlerConfig, HandlerConfig as HandlerConfig$1, LogLevel, LogLevel as LogLevel$1, Logger, Logger as Logger$1, OtelConsoleLogger, OtelContext, OtelContext as OtelContext$1, PipelineController, getLogLevelFromEnv } from "@context-action/core"; | ||
| import React, { ReactNode } from "react"; | ||
@@ -7,2 +7,15 @@ | ||
| /** | ||
| * Configuration options for createActionContext | ||
| */ | ||
| interface ActionContextConfig { | ||
| /** Custom logger implementation. Defaults to ConsoleLogger */ | ||
| logger?: Logger$1; | ||
| /** Log level for the logger. Defaults to ERROR if not provided */ | ||
| logLevel?: LogLevel$1; | ||
| /** OpenTelemetry context for tracing */ | ||
| otelContext?: OtelContext$1; | ||
| /** Whether to use OTEL-aware logger. Defaults to false */ | ||
| useOtel?: boolean; | ||
| } | ||
| /** | ||
| * Context type for ActionRegister | ||
@@ -12,2 +25,3 @@ */ | ||
| actionRegisterRef: React.RefObject<ActionRegister$1<T>>; | ||
| logger: Logger$1; | ||
| } | ||
@@ -22,14 +36,48 @@ /** | ||
| useActionContext: () => ActionContextType<T>; | ||
| useAction: () => ActionRegister$1<T>; | ||
| useAction: () => ActionRegister$1<T>['dispatch']; | ||
| useActionHandler: <K extends keyof T>(action: K, handler: ActionHandler$1<T[K]>, config?: HandlerConfig$1) => void; | ||
| } | ||
| /** | ||
| * ActionRegister를 Context로 공유할 수 있는 헬퍼 함수 | ||
| * @returns Provider, hooks를 포함한 객체 | ||
| * Create a React Context for sharing ActionRegister instance across components | ||
| * @template T - The action payload map type | ||
| * @param config 로거 설정 (선택사항) | ||
| * @returns Object containing Provider component and hooks for action management | ||
| * @example | ||
| * ```typescript | ||
| * interface AppActions extends ActionPayloadMap { | ||
| * increment: void; | ||
| * setCount: number; | ||
| * } | ||
| * | ||
| * const { Provider, useAction, useActionHandler } = createActionContext<AppActions>({ | ||
| * logLevel: LogLevel.DEBUG, | ||
| * useOtel: true | ||
| * }); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <Provider> | ||
| * <Counter /> | ||
| * </Provider> | ||
| * ); | ||
| * } | ||
| * | ||
| * function Counter() { | ||
| * const [count, setCount] = useState(0); | ||
| * const dispatch = useAction(); | ||
| * | ||
| * useActionHandler('increment', () => setCount(prev => prev + 1)); | ||
| * | ||
| * return ( | ||
| * <button onClick={() => dispatch('increment')}> | ||
| * Count: {count} | ||
| * </button> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function createActionContext<T extends ActionPayloadMap$1 = ActionPayloadMap$1>(): ActionContextReturn<T>; | ||
| declare function createActionContext<T extends ActionPayloadMap$1 = ActionPayloadMap$1>(config?: ActionContextConfig): ActionContextReturn<T>; | ||
| //# sourceMappingURL=ActionContext.d.ts.map | ||
| //#endregion | ||
| export { ActionContextReturn, ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, type HandlerConfig, type PipelineController, createActionContext }; | ||
| export { ActionContextConfig, ActionContextReturn, ActionContextType, type ActionHandler, type ActionPayloadMap, ActionRegister, ConsoleLogger, type HandlerConfig, type LogLevel, type Logger, OtelConsoleLogger, type OtelContext, type PipelineController, createActionContext, getLogLevelFromEnv }; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","names":[],"sources":["../src/ActionContext.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AAAkC,UAAjB,iBAAiB,CAAA,UAAW,kBAAX,GAA8B,kBAA9B,CAAA,CAAA;EAAA,iBAAW,EACxB,KAAA,CAAM,SADkB,CACR,gBADQ,CACO,CADP,CAAA,CAAA;;;;;AACT,UAMnB,mBANmB,CAAA,UAMW,kBANX,GAM8B,kBAN9B,CAAA,CAAA;EAMnB,QAAA,EACL,KAAA,CAAM,EADD,CAAA;IAAmB,QAAA,EACH,SADG;EAAA,CAAA,CAAA;EAA2B,gBAAG,EAAA,GAAA,GAExC,iBAFwC,CAEtB,CAFsB,CAAA;EAAgB,SACjD,EAAA,GAAA,GAEd,gBAFc,CAEC,CAFD,CAAA;EAAS,gBAAxB,EAAA,CAAA,UAAA,MAGmB,CAHnB,CAAA,CAAA,MAAA,EAIN,CAJM,EAAA,OAAA,EAKL,eALK,CAKS,CALT,CAKW,CALX,CAAA,CAAA,EAAA,MAAA,CAAA,EAML,eANK,EAAA,GAAA,IAAA;;;;;;AAIN,iBAUI,mBAVJ,CAAA,UAUkC,kBAVlC,GAUqD,kBAVrD,CAAA,CAAA,CAAA,EAU0E,mBAV1E,CAU8F,CAV9F,CAAA"} | ||
| {"version":3,"file":"index.d.ts","names":[],"sources":["../src/ActionContext.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AAAoC,UAAnB,mBAAA,CAAmB;EAAA;EAEnB,MAEJ,CAAA,EAFF,QAEE;EAAQ;EAEM,QAAA,CAAA,EAFd,UAEc;EAQV;EAAiB,WAAA,CAAA,EARlB,aAQkB;EAAA;EAA2B,OAAG,CAAA,EAAA,OAAA;;;;;AAEhD,UAFC,iBAED,CAAA,UAF6B,kBAE7B,GAFgD,kBAEhD,CAAA,CAAA;EAMC,iBAAA,EAPI,KAAA,CAAM,SAOS,CAPC,gBAOD,CAPgB,CAOhB,CAAA,CAAA;EAAA,MAAA,EAN1B,QAM0B;;;;;AAEQ,UAF3B,mBAE2B,CAAA,UAFG,kBAEH,GAFsB,kBAEtB,CAAA,CAAA;EAAC,QAAnB,EADd,KAAA,CAAM,EACQ,CAAA;IACQ,QAAA,EAFD,SAEC;EAAC,CAAA,CAAA;EAAF,gBACI,EAAA,GAAA,GAFX,iBAEW,CAFO,CAEP,CAAA;EAAC,SAC1B,EAAA,GAAA,GAFO,gBAEP,CAFsB,CAEtB,CAAA,CAAA,UAAA,CAAA;EAAC,gBACc,EAAA,CAAA,UAAA,MAFU,CAEV,CAAA,CAAA,MAAA,EADf,CACe,EAAA,OAAA,EAAd,eAAc,CAAA,CAAA,CAAE,CAAF,CAAA,CAAA,EAAA,MAAA,CAAA,EACd,eADc,EAAA,GAAA,IAAA;;;;AACD;AA2C1B;;;;;;;AAAqI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAArH,8BAA8B,qBAAmB,6BAA2B,sBAAsB,oBAAoB"} |
+133
-17
@@ -1,3 +0,3 @@ | ||
| import { ActionRegister, ActionRegister as ActionRegister$1 } from "@context-action/core"; | ||
| import React, { createContext, useContext, useEffect, useId, useRef } from "react"; | ||
| import { ActionRegister, ActionRegister as ActionRegister$1, ConsoleLogger, ConsoleLogger as ConsoleLogger$1, OtelConsoleLogger, OtelConsoleLogger as OtelConsoleLogger$1, getLogLevelFromEnv, getLogLevelFromEnv as getLogLevelFromEnv$1 } from "@context-action/core"; | ||
| import React, { createContext, useContext, useEffect, useId, useMemo, useRef } from "react"; | ||
| import { jsx } from "react/jsx-runtime"; | ||
@@ -7,14 +7,78 @@ | ||
| /** | ||
| * ActionRegister를 Context로 공유할 수 있는 헬퍼 함수 | ||
| * @returns Provider, hooks를 포함한 객체 | ||
| * Create a React Context for sharing ActionRegister instance across components | ||
| * @template T - The action payload map type | ||
| * @param config 로거 설정 (선택사항) | ||
| * @returns Object containing Provider component and hooks for action management | ||
| * @example | ||
| * ```typescript | ||
| * interface AppActions extends ActionPayloadMap { | ||
| * increment: void; | ||
| * setCount: number; | ||
| * } | ||
| * | ||
| * const { Provider, useAction, useActionHandler } = createActionContext<AppActions>({ | ||
| * logLevel: LogLevel.DEBUG, | ||
| * useOtel: true | ||
| * }); | ||
| * | ||
| * function App() { | ||
| * return ( | ||
| * <Provider> | ||
| * <Counter /> | ||
| * </Provider> | ||
| * ); | ||
| * } | ||
| * | ||
| * function Counter() { | ||
| * const [count, setCount] = useState(0); | ||
| * const dispatch = useAction(); | ||
| * | ||
| * useActionHandler('increment', () => setCount(prev => prev + 1)); | ||
| * | ||
| * return ( | ||
| * <button onClick={() => dispatch('increment')}> | ||
| * Count: {count} | ||
| * </button> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| function createActionContext() { | ||
| function createActionContext(config) { | ||
| const ActionContext = createContext(null); | ||
| /** | ||
| * Provider 컴포넌트 | ||
| * ActionRegister 인스턴스를 Context로 제공합니다 | ||
| */ | ||
| const Provider = ({ children }) => { | ||
| const actionRegisterRef = useRef(new ActionRegister$1()); | ||
| const envLogLevel = getLogLevelFromEnv$1(); | ||
| const configLogLevel = config?.logLevel ?? envLogLevel; | ||
| let logger; | ||
| if (config?.logger) logger = config.logger; | ||
| else if (config?.useOtel) logger = new OtelConsoleLogger$1(configLogLevel); | ||
| else logger = new ConsoleLogger$1(configLogLevel); | ||
| if (config?.otelContext && logger instanceof OtelConsoleLogger$1) logger.setContext(config.otelContext); | ||
| const actionRegisterRef = useRef(new ActionRegister$1({ | ||
| logger, | ||
| logLevel: configLogLevel, | ||
| useOtel: config?.useOtel, | ||
| otelContext: config?.otelContext | ||
| })); | ||
| logger.debug("ActionContext Provider initialized", { | ||
| logLevel: configLogLevel, | ||
| useOtel: config?.useOtel ?? false, | ||
| hasOtelContext: !!config?.otelContext | ||
| }); | ||
| return /* @__PURE__ */ jsx(ActionContext.Provider, { | ||
| value: { actionRegisterRef }, | ||
| value: { | ||
| actionRegisterRef, | ||
| logger | ||
| }, | ||
| children | ||
| }); | ||
| }; | ||
| /** | ||
| * Context 접근 hook | ||
| * @returns ActionContextType - ActionRegister 참조를 포함한 컨텍스트 | ||
| * @throws Error - Provider 외부에서 사용될 경우 | ||
| */ | ||
| const useActionContext = () => { | ||
@@ -25,21 +89,73 @@ const context = useContext(ActionContext); | ||
| }; | ||
| /** | ||
| * dispatch 함수 반환 hook | ||
| * @returns ActionRegister의 dispatch 함수 | ||
| * @throws Error - Provider 외부에서 사용될 경우 | ||
| */ | ||
| const useAction = () => { | ||
| const { actionRegisterRef } = useActionContext(); | ||
| return actionRegisterRef.current; | ||
| const context = useContext(ActionContext); | ||
| if (!context) throw new Error("useAction must be used within Provider. Make sure your component is wrapped with the ActionContext Provider."); | ||
| /** strict mode */ | ||
| if (!(context.actionRegisterRef.current instanceof ActionRegister$1)) throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| const dispatch = useMemo(() => { | ||
| if (context.actionRegisterRef.current instanceof ActionRegister$1) { | ||
| const boundDispatch = context.actionRegisterRef.current.dispatch.bind(context.actionRegisterRef.current); | ||
| return ((action, payload) => { | ||
| context.logger.trace("useAction dispatch called", { | ||
| action, | ||
| payload | ||
| }); | ||
| return boundDispatch(action, payload); | ||
| }); | ||
| } | ||
| return (...args) => { | ||
| context.logger.error("ActionRegister is not initialized", { args }); | ||
| throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| }; | ||
| }, [context.actionRegisterRef.current, context.logger]); | ||
| return dispatch; | ||
| }; | ||
| const useActionHandler = (action, handler, config) => { | ||
| const actionRegister = useAction(); | ||
| /** | ||
| * Action Handler 등록 hook | ||
| * @template K - 액션 키 타입 | ||
| * @param action - 등록할 액션 이름 | ||
| * @param handler - 액션 처리 함수 | ||
| * @param config - 핸들러 설정 (선택사항) | ||
| * @description 성능 최적화를 위해 handler는 useCallback으로 메모이제이션하는 것을 권장합니다 | ||
| */ | ||
| const useActionHandler = (action, handler, config$1) => { | ||
| const { actionRegisterRef, logger } = useActionContext(); | ||
| const componentId = useId(); | ||
| useEffect(() => { | ||
| if (!actionRegisterRef.current) { | ||
| logger.error("ActionRegister is not initialized in useActionHandler"); | ||
| throw new Error("ActionRegister is not initialized. Make sure the ActionContext Provider is properly set up."); | ||
| } | ||
| logger.debug("useActionHandler registering", { | ||
| action: String(action), | ||
| componentId, | ||
| priority: config$1?.priority ?? 0, | ||
| blocking: config$1?.blocking ?? false | ||
| }); | ||
| const actionRegister = actionRegisterRef.current; | ||
| const unregister = actionRegister.register(action, handler, { | ||
| ...config, | ||
| id: config?.id || componentId | ||
| ...config$1, | ||
| id: config$1?.id || componentId | ||
| }); | ||
| return unregister; | ||
| return () => { | ||
| logger.debug("useActionHandler unregistering", { | ||
| action: String(action), | ||
| componentId | ||
| }); | ||
| unregister(); | ||
| }; | ||
| }, [ | ||
| action, | ||
| handler, | ||
| config, | ||
| config$1?.id, | ||
| config$1?.priority, | ||
| config$1?.blocking, | ||
| componentId, | ||
| actionRegister | ||
| actionRegisterRef.current, | ||
| logger | ||
| ]); | ||
@@ -56,3 +172,3 @@ }; | ||
| //#endregion | ||
| export { ActionRegister, createActionContext }; | ||
| export { ActionRegister, ConsoleLogger, OtelConsoleLogger, createActionContext, getLogLevelFromEnv }; | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","names":["ActionRegister","action: K","handler: ActionHandler<T[K]>","config?: HandlerConfig"],"sources":["../src/ActionContext.tsx"],"sourcesContent":["import React, { createContext, ReactNode, useContext, useRef, useEffect, useId } from 'react';\nimport { ActionPayloadMap, ActionRegister, ActionHandler, HandlerConfig } from '@context-action/core';\n\n/**\n * Context type for ActionRegister\n */\nexport interface ActionContextType<T extends ActionPayloadMap = ActionPayloadMap> {\n actionRegisterRef: React.RefObject<ActionRegister<T>>;\n}\n\n/**\n * Return type for createActionContext\n */\nexport interface ActionContextReturn<T extends ActionPayloadMap = ActionPayloadMap> {\n Provider: React.FC<{ children: ReactNode }>;\n useActionContext: () => ActionContextType<T>;\n useAction: () => ActionRegister<T>;\n useActionHandler: <K extends keyof T>(\n action: K,\n handler: ActionHandler<T[K]>,\n config?: HandlerConfig\n ) => void;\n}\n\n/**\n * ActionRegister를 Context로 공유할 수 있는 헬퍼 함수\n * @returns Provider, hooks를 포함한 객체\n */\nexport function createActionContext<T extends ActionPayloadMap = ActionPayloadMap>(): ActionContextReturn<T> {\n\n const ActionContext = createContext<ActionContextType<T> | null>(null);\n\n // Provider 컴포넌트\n const Provider = ({ children }: { children: ReactNode }) => {\n const actionRegisterRef = useRef(new ActionRegister<T>());\n return (\n <ActionContext.Provider value={{ actionRegisterRef }}>\n {children}\n </ActionContext.Provider>\n );\n };\n\n // Context 접근 hook\n const useActionContext = () => {\n const context = useContext(ActionContext);\n if (!context) {\n throw new Error('useActionContext must be used within Provider');\n }\n return context;\n };\n\n // ActionRegister 인스턴스 반환 hook\n const useAction = () => {\n const { actionRegisterRef } = useActionContext();\n return actionRegisterRef.current!;\n };\n\n // Action Handler 등록 hook\n const useActionHandler = <K extends keyof T>(\n action: K,\n handler: ActionHandler<T[K]>,\n config?: HandlerConfig\n ) => {\n const actionRegister = useAction();\n const componentId = useId();\n \n useEffect(() => {\n const unregister = actionRegister.register(\n action,\n handler,\n { ...config, id: config?.id || componentId }\n );\n \n return unregister;\n }, [action, handler, config, componentId, actionRegister]);\n };\n\n return {\n Provider,\n useActionContext,\n useAction,\n useActionHandler,\n };\n}\n"],"mappings":";;;;;;;;;AA4BA,SAAgB,sBAA6F;CAE3G,MAAM,gBAAgB,cAA2C,KAAK;CAGtE,MAAM,WAAW,CAAC,EAAE,UAAmC,KAAK;EAC1D,MAAM,oBAAoB,OAAO,IAAIA,mBAAoB;AACzD,6BACG,cAAc;GAAS,OAAO,EAAE,kBAAmB;GACjD;IACsB;CAE5B;CAGD,MAAM,mBAAmB,MAAM;EAC7B,MAAM,UAAU,WAAW,cAAc;AACzC,MAAI,CAAC,QACH,OAAM,IAAI,MAAM;AAElB,SAAO;CACR;CAGD,MAAM,YAAY,MAAM;EACtB,MAAM,EAAE,mBAAmB,GAAG,kBAAkB;AAChD,SAAO,kBAAkB;CAC1B;CAGD,MAAM,mBAAmB,CACvBC,QACAC,SACAC,WACG;EACH,MAAM,iBAAiB,WAAW;EAClC,MAAM,cAAc,OAAO;EAE3B,UAAU,MAAM;GACd,MAAM,aAAa,eAAe,SAChC,QACA,SACA;IAAE,GAAG;IAAQ,IAAI,QAAQ,MAAM;GAAa,EAC7C;AAED,UAAO;EACR,GAAE;GAAC;GAAQ;GAAS;GAAQ;GAAa;EAAe,EAAC;CAC3D;AAED,QAAO;EACL;EACA;EACA;EACA;CACD;AACF"} | ||
| {"version":3,"file":"index.js","names":["config?: ActionContextConfig","getLogLevelFromEnv","logger: Logger","OtelConsoleLogger","ConsoleLogger","ActionRegister","action: any","payload?: any","action: K","handler: ActionHandler<T[K]>","config?: HandlerConfig","config"],"sources":["../src/ActionContext.tsx"],"sourcesContent":["import React, { createContext, ReactNode, useContext, useRef, useEffect, useId, useMemo } from 'react';\nimport { ActionPayloadMap, ActionRegister, ActionHandler, HandlerConfig, Logger, LogLevel, ConsoleLogger, OtelConsoleLogger, OtelContext, getLogLevelFromEnv } from '@context-action/core';\n\n/**\n * Configuration options for createActionContext\n */\nexport interface ActionContextConfig {\n /** Custom logger implementation. Defaults to ConsoleLogger */\n logger?: Logger\n /** Log level for the logger. Defaults to ERROR if not provided */\n logLevel?: LogLevel\n /** OpenTelemetry context for tracing */\n otelContext?: OtelContext\n /** Whether to use OTEL-aware logger. Defaults to false */\n useOtel?: boolean\n}\n\n/**\n * Context type for ActionRegister\n */\nexport interface ActionContextType<T extends ActionPayloadMap = ActionPayloadMap> {\n actionRegisterRef: React.RefObject<ActionRegister<T>>;\n logger: Logger;\n}\n\n/**\n * Return type for createActionContext\n */\nexport interface ActionContextReturn<T extends ActionPayloadMap = ActionPayloadMap> {\n Provider: React.FC<{ children: ReactNode }>;\n useActionContext: () => ActionContextType<T>;\n useAction: () => ActionRegister<T>['dispatch'];\n useActionHandler: <K extends keyof T>(\n action: K,\n handler: ActionHandler<T[K]>,\n config?: HandlerConfig\n ) => void;\n}\n\n/**\n * Create a React Context for sharing ActionRegister instance across components\n * @template T - The action payload map type\n * @param config 로거 설정 (선택사항)\n * @returns Object containing Provider component and hooks for action management\n * @example\n * ```typescript\n * interface AppActions extends ActionPayloadMap {\n * increment: void;\n * setCount: number;\n * }\n * \n * const { Provider, useAction, useActionHandler } = createActionContext<AppActions>({\n * logLevel: LogLevel.DEBUG,\n * useOtel: true\n * });\n * \n * function App() {\n * return (\n * <Provider>\n * <Counter />\n * </Provider>\n * );\n * }\n * \n * function Counter() {\n * const [count, setCount] = useState(0);\n * const dispatch = useAction();\n * \n * useActionHandler('increment', () => setCount(prev => prev + 1));\n * \n * return (\n * <button onClick={() => dispatch('increment')}>\n * Count: {count}\n * </button>\n * );\n * }\n * ```\n */\nexport function createActionContext<T extends ActionPayloadMap = ActionPayloadMap>(config?: ActionContextConfig): ActionContextReturn<T> {\n\n const ActionContext = createContext<ActionContextType<T> | null>(null);\n\n /**\n * Provider 컴포넌트\n * ActionRegister 인스턴스를 Context로 제공합니다\n */\n const Provider = ({ children }: { children: ReactNode }) => {\n // 로거 설정\n const envLogLevel = getLogLevelFromEnv()\n const configLogLevel = config?.logLevel ?? envLogLevel\n \n let logger: Logger\n if (config?.logger) {\n logger = config.logger\n } else if (config?.useOtel) {\n logger = new OtelConsoleLogger(configLogLevel)\n } else {\n logger = new ConsoleLogger(configLogLevel)\n }\n \n // OTEL 컨텍스트 설정\n if (config?.otelContext && logger instanceof OtelConsoleLogger) {\n logger.setContext(config.otelContext)\n }\n \n const actionRegisterRef = useRef(new ActionRegister<T>({\n logger,\n logLevel: configLogLevel,\n useOtel: config?.useOtel,\n otelContext: config?.otelContext\n }));\n \n logger.debug('ActionContext Provider initialized', { \n logLevel: configLogLevel,\n useOtel: config?.useOtel ?? false,\n hasOtelContext: !!config?.otelContext\n })\n \n return (\n <ActionContext.Provider value={{ actionRegisterRef, logger }}>\n {children}\n </ActionContext.Provider>\n );\n };\n\n /**\n * Context 접근 hook\n * @returns ActionContextType - ActionRegister 참조를 포함한 컨텍스트\n * @throws Error - Provider 외부에서 사용될 경우\n */\n const useActionContext = () => {\n const context = useContext(ActionContext);\n if (!context) {\n throw new Error('useActionContext must be used within Provider');\n }\n return context;\n };\n\n /**\n * dispatch 함수 반환 hook\n * @returns ActionRegister의 dispatch 함수\n * @throws Error - Provider 외부에서 사용될 경우\n */\n const useAction = (): ActionRegister<T>['dispatch'] => {\n const context = useContext(ActionContext);\n \n if (!context) {\n throw new Error(\n 'useAction must be used within Provider. ' +\n 'Make sure your component is wrapped with the ActionContext Provider.'\n );\n }\n\n /** strict mode */\n if (!(context.actionRegisterRef.current instanceof ActionRegister)) {\n throw new Error(\n 'ActionRegister is not initialized. ' +\n 'Make sure the ActionContext Provider is properly set up.'\n );\n }\n\n const dispatch = useMemo(() => {\n if (context.actionRegisterRef.current instanceof ActionRegister) {\n const boundDispatch = context.actionRegisterRef.current.dispatch.bind(context.actionRegisterRef.current);\n \n // 로거를 포함한 dispatch 래퍼\n return ((action: any, payload?: any) => {\n context.logger.trace('useAction dispatch called', { action, payload });\n return boundDispatch(action, payload);\n }) as ActionRegister<T>['dispatch'];\n }\n\n return (...args: any[]) => {\n context.logger.error('ActionRegister is not initialized', { args });\n throw new Error(\n 'ActionRegister is not initialized. ' +\n 'Make sure the ActionContext Provider is properly set up.'\n );\n }\n }, [context.actionRegisterRef.current, context.logger]);\n\n return dispatch;\n };\n\n /**\n * Action Handler 등록 hook\n * @template K - 액션 키 타입\n * @param action - 등록할 액션 이름\n * @param handler - 액션 처리 함수\n * @param config - 핸들러 설정 (선택사항)\n * @description 성능 최적화를 위해 handler는 useCallback으로 메모이제이션하는 것을 권장합니다\n */\n const useActionHandler = <K extends keyof T>(\n action: K,\n handler: ActionHandler<T[K]>,\n config?: HandlerConfig\n ) => {\n const { actionRegisterRef, logger } = useActionContext();\n const componentId = useId();\n\n useEffect(() => {\n if (!actionRegisterRef.current) {\n logger.error('ActionRegister is not initialized in useActionHandler');\n throw new Error(\n 'ActionRegister is not initialized. ' +\n 'Make sure the ActionContext Provider is properly set up.'\n );\n }\n\n logger.debug('useActionHandler registering', {\n action: String(action),\n componentId,\n priority: config?.priority ?? 0,\n blocking: config?.blocking ?? false\n });\n \n const actionRegister = actionRegisterRef.current;\n const unregister = actionRegister.register(\n action,\n handler,\n { ...config, id: config?.id || componentId }\n );\n \n return () => {\n logger.debug('useActionHandler unregistering', {\n action: String(action),\n componentId\n });\n unregister();\n };\n }, [action, handler, config?.id, config?.priority, config?.blocking, componentId, actionRegisterRef.current, logger]);\n };\n\n return {\n Provider,\n useActionContext,\n useAction,\n useActionHandler,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8EA,SAAgB,oBAAmEA,QAAsD;CAEvI,MAAM,gBAAgB,cAA2C,KAAK;;;;;CAMtE,MAAM,WAAW,CAAC,EAAE,UAAmC,KAAK;EAE1D,MAAM,cAAcC,sBAAoB;EACxC,MAAM,iBAAiB,QAAQ,YAAY;EAE3C,IAAIC;AACJ,MAAI,QAAQ,QACV,SAAS,OAAO;WACP,QAAQ,SACjB,SAAS,IAAIC,oBAAkB;OAE/B,SAAS,IAAIC,gBAAc;AAI7B,MAAI,QAAQ,eAAe,kBAAkBD,qBAC3C,OAAO,WAAW,OAAO,YAAY;EAGvC,MAAM,oBAAoB,OAAO,IAAIE,iBAAkB;GACrD;GACA,UAAU;GACV,SAAS,QAAQ;GACjB,aAAa,QAAQ;EACtB,GAAE;EAEH,OAAO,MAAM,sCAAsC;GACjD,UAAU;GACV,SAAS,QAAQ,WAAW;GAC5B,gBAAgB,CAAC,CAAC,QAAQ;EAC3B,EAAC;AAEF,6BACG,cAAc;GAAS,OAAO;IAAE;IAAmB;GAAQ;GACzD;IACsB;CAE5B;;;;;;CAOD,MAAM,mBAAmB,MAAM;EAC7B,MAAM,UAAU,WAAW,cAAc;AACzC,MAAI,CAAC,QACH,OAAM,IAAI,MAAM;AAElB,SAAO;CACR;;;;;;CAOD,MAAM,YAAY,MAAqC;EACrD,MAAM,UAAU,WAAW,cAAc;AAEzC,MAAI,CAAC,QACH,OAAM,IAAI,MACR;;AAMJ,MAAI,EAAE,QAAQ,kBAAkB,mBAAmBA,kBACjD,OAAM,IAAI,MACR;EAKJ,MAAM,WAAW,QAAQ,MAAM;AAC7B,OAAI,QAAQ,kBAAkB,mBAAmBA,kBAAgB;IAC/D,MAAM,gBAAgB,QAAQ,kBAAkB,QAAQ,SAAS,KAAK,QAAQ,kBAAkB,QAAQ;AAGxG,YAAQ,CAACC,QAAaC,YAAkB;KACtC,QAAQ,OAAO,MAAM,6BAA6B;MAAE;MAAQ;KAAS,EAAC;AACtE,YAAO,cAAc,QAAQ,QAAQ;IACtC;GACF;AAED,UAAO,CAAC,GAAG,SAAgB;IACzB,QAAQ,OAAO,MAAM,qCAAqC,EAAE,KAAM,EAAC;AACnE,UAAM,IAAI,MACR;GAGH;EACF,GAAE,CAAC,QAAQ,kBAAkB,SAAS,QAAQ,MAAO,EAAC;AAEvD,SAAO;CACR;;;;;;;;;CAUD,MAAM,mBAAmB,CACvBC,QACAC,SACAC,aACG;EACH,MAAM,EAAE,mBAAmB,QAAQ,GAAG,kBAAkB;EACxD,MAAM,cAAc,OAAO;EAE3B,UAAU,MAAM;AACd,OAAI,CAAC,kBAAkB,SAAS;IAC9B,OAAO,MAAM,wDAAwD;AACrE,UAAM,IAAI,MACR;GAGH;GAED,OAAO,MAAM,gCAAgC;IAC3C,QAAQ,OAAO,OAAO;IACtB;IACA,UAAUC,UAAQ,YAAY;IAC9B,UAAUA,UAAQ,YAAY;GAC/B,EAAC;GAEF,MAAM,iBAAiB,kBAAkB;GACzC,MAAM,aAAa,eAAe,SAChC,QACA,SACA;IAAE,GAAGA;IAAQ,IAAIA,UAAQ,MAAM;GAAa,EAC7C;AAED,UAAO,MAAM;IACX,OAAO,MAAM,kCAAkC;KAC7C,QAAQ,OAAO,OAAO;KACtB;IACD,EAAC;IACF,YAAY;GACb;EACF,GAAE;GAAC;GAAQ;GAASA,UAAQ;GAAIA,UAAQ;GAAUA,UAAQ;GAAU;GAAa,kBAAkB;GAAS;EAAO,EAAC;CACtH;AAED,QAAO;EACL;EACA;EACA;EACA;CACD;AACF"} |
+3
-3
| { | ||
| "name": "@context-action/react", | ||
| "version": "0.0.2", | ||
| "version": "0.0.3", | ||
| "type": "module", | ||
@@ -51,3 +51,3 @@ "description": "React integration for @context-action/core - Context and hooks for type-safe action management", | ||
| "dependencies": { | ||
| "@context-action/core": "0.0.2" | ||
| "@context-action/core": "0.0.3" | ||
| }, | ||
@@ -75,3 +75,3 @@ "devDependencies": { | ||
| "build:watch": "tsdown --watch", | ||
| "test": "jest", | ||
| "test": "jest --passWithNoTests", | ||
| "test:watch": "jest --watch", | ||
@@ -78,0 +78,0 @@ "lint": "eslint src --ext .ts,.tsx", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
32622
137.01%460
189.31%1
Infinity%+ Added
- Removed
Updated