From ec4ff238479cd1c00981d34a3bcf10edb82a4724 Mon Sep 17 00:00:00 2001 From: Bori-github Date: Thu, 30 Oct 2025 20:50:29 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20playground=20store=EC=97=90=20?= =?UTF-8?q?=ED=94=8C=EB=A0=88=EC=9D=B4=EA=B7=B8=EB=9D=BC=EC=9A=B4=EB=93=9C?= =?UTF-8?q?=20=EB=B3=84=20=EC=BD=94=EB=93=9C=20=EC=8B=A4=ED=96=89=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/playground/store.ts | 69 ++++++++++++++++++- .../widgets/playground/playground-widget.tsx | 15 ++-- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/apps/executeJS/src/features/playground/store.ts b/apps/executeJS/src/features/playground/store.ts index 0e897c9..bbba803 100644 --- a/apps/executeJS/src/features/playground/store.ts +++ b/apps/executeJS/src/features/playground/store.ts @@ -12,8 +12,6 @@ export interface Playground { id: string; result: JsExecutionResult | null; isExecuting: boolean; - // setExecuting: (executing: boolean) => void; - // executeCode: (code: string) => void; // clearResult: () => void; } @@ -25,6 +23,10 @@ interface PlaygroundState { addTab: () => void; closeTab: (tabId: Tab['id']) => void; setActiveTab: (tabId: Tab['id']) => void; + executeCode: (params: { + playgroundId: Playground['id']; + code: string; + }) => void; } const INITIAL_TAB_TITLE = '✨New Playground'; @@ -120,6 +122,69 @@ export const usePlaygroundStore = create()( }; }); }, + + // 플레이그라운드 별 코드 실행 + executeCode: async ({ + playgroundId, + code, + }: { + playgroundId: Playground['id']; + code: string; + }) => { + set((state) => { + const playgrounds = new Map(state.playgrounds); + const playground = playgrounds.get(playgroundId); + + if (playground) { + playground.isExecuting = true; + } + + return { playgrounds }; + }); + + try { + // Tauri 백엔드의 execute_js 명령어 호출 + const { invoke } = await import('@tauri-apps/api/core'); + const result = await invoke('execute_js', { + code, + }); + + console.log('executeCode result -', result); + + set((state) => { + const playgrounds = new Map(state.playgrounds); + const playground = playgrounds.get(playgroundId); + + if (playground) { + playground.result = result; + playground.isExecuting = false; + } + + return { playgrounds }; + }); + } catch (error: any) { + //TODO: @ohah 에러 처리 더 명확하게 할 것 + const result: JsExecutionResult = { + code, + result: error?.result ?? '', + timestamp: new Date().toISOString(), + success: false, + error: error?.error ?? '알 수 없는 오류', + }; + + set((state) => { + const playgrounds = new Map(state.playgrounds); + const playground = playgrounds.get(playgroundId); + + if (playground) { + playground.result = result; + playground.isExecuting = false; + } + + return { playgrounds }; + }); + } + }, }), { name: 'executejs-playground-store', diff --git a/apps/executeJS/src/widgets/playground/playground-widget.tsx b/apps/executeJS/src/widgets/playground/playground-widget.tsx index a65b468..e5de227 100644 --- a/apps/executeJS/src/widgets/playground/playground-widget.tsx +++ b/apps/executeJS/src/widgets/playground/playground-widget.tsx @@ -5,8 +5,7 @@ import { PlayIcon, StopIcon } from '@radix-ui/react-icons'; import { CodeEditor } from '@/widgets/code-editor'; import { OutputPanel } from '@/widgets/output-panel'; -import { useExecutionStore } from '@/features/execute-code'; -import { Playground } from '@/features/playground'; +import { Playground, usePlaygroundStore } from '@/features/playground'; const getInitialCode = (): string => { try { @@ -36,22 +35,18 @@ interface PlaygroundProps { } export const PlaygroundWidget: React.FC = ({ playground }) => { - // TODO: playground prop 로직 추가 예정 @bori - console.log('PlaygroundWidget', playground); + const { isExecuting, result: executionResult } = playground; // FIXME: tab이 여러개 생기거나 global store로 상태가 이동되면 수정되어야함 const [code, setCode] = useState(getInitialCode); - const { - result: executionResult, - isExecuting, - executeCode, - } = useExecutionStore(); + + const { executeCode } = usePlaygroundStore(); // 코드 실행 핸들러 const handleExecuteCode = (codeToExecute?: string) => { const codeToRun = codeToExecute || code; if (codeToRun.trim()) { - executeCode(codeToRun); + executeCode({ code: codeToRun, playgroundId: playground.id }); } }; From a02e6c684f46a3acaf0e490fdef178283a009891 Mon Sep 17 00:00:00 2001 From: Bori-github Date: Thu, 30 Oct 2025 21:07:40 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=9D=BC=EC=9A=B4=EB=93=9C=20=EB=B3=84=20=EB=A1=9C?= =?UTF-8?q?=EC=BB=AC=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EC=A7=80=20=EB=82=B4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/playground/const.ts | 1 + .../src/features/playground/index.ts | 2 ++ .../src/features/playground/store.ts | 3 +- .../src/features/playground/utils.ts | 25 +++++++++++++ .../widgets/playground/playground-widget.tsx | 36 +++++-------------- 5 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 apps/executeJS/src/features/playground/const.ts create mode 100644 apps/executeJS/src/features/playground/utils.ts diff --git a/apps/executeJS/src/features/playground/const.ts b/apps/executeJS/src/features/playground/const.ts new file mode 100644 index 0000000..a8abf9f --- /dev/null +++ b/apps/executeJS/src/features/playground/const.ts @@ -0,0 +1 @@ +export const PLAYGROUND_STORAGE_KEY = 'executejs-playground-storage'; diff --git a/apps/executeJS/src/features/playground/index.ts b/apps/executeJS/src/features/playground/index.ts index d406816..6f24e3b 100644 --- a/apps/executeJS/src/features/playground/index.ts +++ b/apps/executeJS/src/features/playground/index.ts @@ -1 +1,3 @@ export * from './store'; +export * from './utils'; +export * from './const'; diff --git a/apps/executeJS/src/features/playground/store.ts b/apps/executeJS/src/features/playground/store.ts index bbba803..b66c923 100644 --- a/apps/executeJS/src/features/playground/store.ts +++ b/apps/executeJS/src/features/playground/store.ts @@ -1,6 +1,7 @@ import { JsExecutionResult } from '@/shared'; import { create } from 'zustand'; import { persist, createJSONStorage } from 'zustand/middleware'; +import { PLAYGROUND_STORAGE_KEY } from './const'; interface Tab { id: string; @@ -187,7 +188,7 @@ export const usePlaygroundStore = create()( }, }), { - name: 'executejs-playground-store', + name: PLAYGROUND_STORAGE_KEY, storage: createJSONStorage(() => localStorage, { replacer: (_, value) => { if (value instanceof Map) { diff --git a/apps/executeJS/src/features/playground/utils.ts b/apps/executeJS/src/features/playground/utils.ts new file mode 100644 index 0000000..451496c --- /dev/null +++ b/apps/executeJS/src/features/playground/utils.ts @@ -0,0 +1,25 @@ +import { PLAYGROUND_STORAGE_KEY } from './const'; +import { Playground } from './store'; + +export const getInitialCode = (playgroundId: string): string => { + try { + const playgroundStorage = localStorage.getItem(PLAYGROUND_STORAGE_KEY); + + if (playgroundStorage) { + const parsed = JSON.parse(playgroundStorage); + const playgrounds = new Map(parsed?.state?.playgrounds?.value); + const playground = playgrounds.get(playgroundId) as Playground; + const code = playground?.result?.code; + + if (code) { + console.log('result from playgroundStorage:', code); + + return code; + } + } + } catch (error) { + console.error('error from playgroundStorage:', error); + } + + return 'console.log("Hello, ExecuteJS!");'; +}; diff --git a/apps/executeJS/src/widgets/playground/playground-widget.tsx b/apps/executeJS/src/widgets/playground/playground-widget.tsx index e5de227..cbddece 100644 --- a/apps/executeJS/src/widgets/playground/playground-widget.tsx +++ b/apps/executeJS/src/widgets/playground/playground-widget.tsx @@ -5,40 +5,20 @@ import { PlayIcon, StopIcon } from '@radix-ui/react-icons'; import { CodeEditor } from '@/widgets/code-editor'; import { OutputPanel } from '@/widgets/output-panel'; -import { Playground, usePlaygroundStore } from '@/features/playground'; - -const getInitialCode = (): string => { - try { - const executionStorage = localStorage.getItem( - 'executejs-execution-storage' - ); - - if (executionStorage) { - const parsed = JSON.parse(executionStorage); - const code = parsed?.state?.result?.code; - - if (code) { - console.log('result from executionStorage:', code); - - return code; - } - } - } catch (error) { - console.error('error from executionStorage:', error); - } - - return 'console.log("Hello, ExecuteJS!");'; -}; +import { + getInitialCode, + Playground, + usePlaygroundStore, +} from '@/features/playground'; interface PlaygroundProps { playground: Playground; } export const PlaygroundWidget: React.FC = ({ playground }) => { - const { isExecuting, result: executionResult } = playground; + const { id, isExecuting, result: executionResult } = playground; - // FIXME: tab이 여러개 생기거나 global store로 상태가 이동되면 수정되어야함 - const [code, setCode] = useState(getInitialCode); + const [code, setCode] = useState(getInitialCode(id)); const { executeCode } = usePlaygroundStore(); @@ -46,7 +26,7 @@ export const PlaygroundWidget: React.FC = ({ playground }) => { const handleExecuteCode = (codeToExecute?: string) => { const codeToRun = codeToExecute || code; if (codeToRun.trim()) { - executeCode({ code: codeToRun, playgroundId: playground.id }); + executeCode({ code: codeToRun, playgroundId: id }); } }; From c25f379dac3aa3d1b219f218d5353228efd24122 Mon Sep 17 00:00:00 2001 From: Bori-github Date: Thu, 30 Oct 2025 21:30:10 +0900 Subject: [PATCH 3/4] =?UTF-8?q?chore:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=9D=BC=EC=9A=B4=EB=93=9C=20=EB=B3=84=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=8B=A4=ED=96=89=20=EB=A1=9C=EC=A7=81=20=EB=82=B4?= =?UTF-8?q?=20=EC=8B=A4=ED=96=89=20=EC=83=81=ED=83=9C,=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20set=ED=95=98=EB=8A=94=20=EC=BD=94=EB=93=9C=20Map=20?= =?UTF-8?q?set=20=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/executeJS/src/features/playground/store.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/executeJS/src/features/playground/store.ts b/apps/executeJS/src/features/playground/store.ts index b66c923..2959510 100644 --- a/apps/executeJS/src/features/playground/store.ts +++ b/apps/executeJS/src/features/playground/store.ts @@ -137,7 +137,7 @@ export const usePlaygroundStore = create()( const playground = playgrounds.get(playgroundId); if (playground) { - playground.isExecuting = true; + playgrounds.set(playgroundId, { ...playground, isExecuting: true }); } return { playgrounds }; @@ -157,8 +157,11 @@ export const usePlaygroundStore = create()( const playground = playgrounds.get(playgroundId); if (playground) { - playground.result = result; - playground.isExecuting = false; + playgrounds.set(playgroundId, { + ...playground, + result: result, + isExecuting: false, + }); } return { playgrounds }; @@ -178,8 +181,11 @@ export const usePlaygroundStore = create()( const playground = playgrounds.get(playgroundId); if (playground) { - playground.result = result; - playground.isExecuting = false; + playgrounds.set(playgroundId, { + ...playground, + result: result, + isExecuting: false, + }); } return { playgrounds }; From 211bbf4c5fa2b44dcacd9aa80808a76613b8b975 Mon Sep 17 00:00:00 2001 From: Bori-github Date: Thu, 30 Oct 2025 21:44:02 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor:=20=EC=B4=88=EA=B8=B0=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=8A=A4=ED=86=A0=EC=96=B4=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EB=94=94=ED=8F=B4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/features/playground/const.ts | 2 ++ .../src/features/playground/index.ts | 1 - .../src/features/playground/utils.ts | 25 ------------------- .../widgets/playground/playground-widget.tsx | 6 +++-- 4 files changed, 6 insertions(+), 28 deletions(-) delete mode 100644 apps/executeJS/src/features/playground/utils.ts diff --git a/apps/executeJS/src/features/playground/const.ts b/apps/executeJS/src/features/playground/const.ts index a8abf9f..e41648f 100644 --- a/apps/executeJS/src/features/playground/const.ts +++ b/apps/executeJS/src/features/playground/const.ts @@ -1 +1,3 @@ export const PLAYGROUND_STORAGE_KEY = 'executejs-playground-storage'; + +export const DEFAULT_PLAYGROUND_CODE = 'console.log("Hello, ExecuteJS!");'; diff --git a/apps/executeJS/src/features/playground/index.ts b/apps/executeJS/src/features/playground/index.ts index 6f24e3b..e221ce1 100644 --- a/apps/executeJS/src/features/playground/index.ts +++ b/apps/executeJS/src/features/playground/index.ts @@ -1,3 +1,2 @@ export * from './store'; -export * from './utils'; export * from './const'; diff --git a/apps/executeJS/src/features/playground/utils.ts b/apps/executeJS/src/features/playground/utils.ts deleted file mode 100644 index 451496c..0000000 --- a/apps/executeJS/src/features/playground/utils.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { PLAYGROUND_STORAGE_KEY } from './const'; -import { Playground } from './store'; - -export const getInitialCode = (playgroundId: string): string => { - try { - const playgroundStorage = localStorage.getItem(PLAYGROUND_STORAGE_KEY); - - if (playgroundStorage) { - const parsed = JSON.parse(playgroundStorage); - const playgrounds = new Map(parsed?.state?.playgrounds?.value); - const playground = playgrounds.get(playgroundId) as Playground; - const code = playground?.result?.code; - - if (code) { - console.log('result from playgroundStorage:', code); - - return code; - } - } - } catch (error) { - console.error('error from playgroundStorage:', error); - } - - return 'console.log("Hello, ExecuteJS!");'; -}; diff --git a/apps/executeJS/src/widgets/playground/playground-widget.tsx b/apps/executeJS/src/widgets/playground/playground-widget.tsx index cbddece..a4c0d25 100644 --- a/apps/executeJS/src/widgets/playground/playground-widget.tsx +++ b/apps/executeJS/src/widgets/playground/playground-widget.tsx @@ -6,7 +6,7 @@ import { PlayIcon, StopIcon } from '@radix-ui/react-icons'; import { CodeEditor } from '@/widgets/code-editor'; import { OutputPanel } from '@/widgets/output-panel'; import { - getInitialCode, + DEFAULT_PLAYGROUND_CODE, Playground, usePlaygroundStore, } from '@/features/playground'; @@ -18,7 +18,9 @@ interface PlaygroundProps { export const PlaygroundWidget: React.FC = ({ playground }) => { const { id, isExecuting, result: executionResult } = playground; - const [code, setCode] = useState(getInitialCode(id)); + const [code, setCode] = useState( + executionResult?.code || DEFAULT_PLAYGROUND_CODE + ); const { executeCode } = usePlaygroundStore();