Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 12 additions & 57 deletions apps/executeJS/src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::js_executor::{execute_javascript_code, JsExecutionResult, JsExecutorState};
use crate::js_executor::{execute_javascript_code, JsExecutionResult};
use serde::{Deserialize, Serialize};
use tauri::State;

Expand All @@ -10,70 +10,25 @@ pub struct AppInfo {
pub author: String,
}

// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
pub fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}

#[tauri::command]
pub async fn execute_js(
code: &str,
state: State<'_, JsExecutorState>,
) -> Result<JsExecutionResult, String> {
pub async fn execute_js(code: &str) -> Result<JsExecutionResult, JsExecutionResult> {
let result = execute_javascript_code(code).await;

// 실행 결과를 히스토리에 추가
state.add_execution(result.clone());

if result.success {
Ok(result)
} else {
Err(result
let error_message = result
.error
.unwrap_or_else(|| "알 수 없는 오류".to_string()))
}
}

#[tauri::command]
pub fn get_js_execution_history(state: State<JsExecutorState>) -> Vec<JsExecutionResult> {
state.get_history()
}

#[tauri::command]
pub fn clear_js_execution_history(state: State<JsExecutorState>) -> Result<(), String> {
state.clear_history();
Ok(())
}

#[tauri::command]
pub fn save_js_code(code: &str, filename: &str) -> Result<String, String> {
use std::fs;
use std::path::Path;

let code_dir = Path::new("saved_codes");
if !code_dir.exists() {
fs::create_dir_all(code_dir).map_err(|e| format!("디렉토리 생성 실패: {}", e))?;
}

let file_path = code_dir.join(filename);
fs::write(&file_path, code).map_err(|e| format!("파일 저장 실패: {}", e))?;

Ok(format!("코드가 {}에 저장되었습니다", file_path.display()))
}

#[tauri::command]
pub fn load_js_code(filename: &str) -> Result<String, String> {
use std::fs;
use std::path::Path;

let file_path = Path::new("saved_codes").join(filename);

if !file_path.exists() {
return Err("파일을 찾을 수 없습니다".to_string());
.unwrap_or_else(|| "알 수 없는 오류".to_string());

Err(JsExecutionResult {
code: code.to_string(),
result: error_message.clone(),
timestamp: chrono::Utc::now(),
success: false,
error: Some(error_message.clone()),
})
}

fs::read_to_string(&file_path).map_err(|e| format!("파일 읽기 실패: {}", e))
}

#[tauri::command]
Expand Down
16 changes: 1 addition & 15 deletions apps/executeJS/src-tauri/src/deno_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,22 +146,8 @@ impl DenoExecutor {
return Err(anyhow::anyhow!("Bootstrap 실행 실패: {}", e));
}

// JavaScript 코드를 즉시 실행 함수로 래핑
let wrapped_code = format!(
r#"
(async () => {{
try {{
{}
}} catch (error) {{
console.error('Error:', error.message);
}}
}})();
"#,
code
);

// 코드 실행
let result = js_runtime.execute_script("[executejs:user_code]", wrapped_code)?;
let result = js_runtime.execute_script("[executejs:user_code]", code)?;

// 이벤트 루프 실행 (Promise 처리) - 블로킹 방식으로 변경
let rt = tokio::runtime::Handle::current();
Expand Down
52 changes: 3 additions & 49 deletions apps/executeJS/src-tauri/src/js_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,50 +12,6 @@ pub struct JsExecutionResult {
pub error: Option<String>,
}

#[derive(Debug)]
pub struct JsExecutorState {
pub history: Mutex<VecDeque<JsExecutionResult>>,
pub max_history: usize,
}

impl JsExecutorState {
pub fn new(max_history: usize) -> Self {
Self {
history: Mutex::new(VecDeque::new()),
max_history,
}
}

pub fn add_execution(&self, result: JsExecutionResult) {
if let Ok(mut history) = self.history.lock() {
history.push_back(result);
if history.len() > self.max_history {
history.pop_front();
}
}
}

pub fn get_history(&self) -> Vec<JsExecutionResult> {
if let Ok(history) = self.history.lock() {
history.iter().cloned().collect()
} else {
vec![]
}
}

pub fn clear_history(&self) {
if let Ok(mut history) = self.history.lock() {
history.clear();
}
}
}

impl Default for JsExecutorState {
fn default() -> Self {
Self::new(100) // 최대 100개의 실행 기록 보관
}
}

pub async fn execute_javascript_code(code: &str) -> JsExecutionResult {
let timestamp = chrono::Utc::now();

Expand Down Expand Up @@ -84,23 +40,21 @@ pub async fn execute_javascript_code(code: &str) -> JsExecutionResult {
result: String::new(),
timestamp,
success: false,
error: Some(format!("JavaScript 실행 오류: {}", error)),
error: Some(format!("{}", error)),
},
}
}

/// Deno를 사용한 JavaScript 코드 실행
async fn execute_with_deno(code: &str) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
// DenoExecutor 생성
let mut executor = DenoExecutor::new()
.await
.map_err(|e| format!("Deno 런타임 초기화 실패: {}", e))?;
let mut executor = DenoExecutor::new().await.map_err(|e| format!("{}", e))?;

// 코드 실행
let result = executor
.execute_script("index.js", code)
.await
.map_err(|e| format!("JavaScript 실행 실패: {}", e))?;
.map_err(|e| format!("{}", e))?;

Ok(result)
}
12 changes: 1 addition & 11 deletions apps/executeJS/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ pub fn run() {
window.close_devtools();
}

app_handle.manage(js_executor::JsExecutorState::default());

// 앱 시작 시 초기화 작업
tauri::async_runtime::spawn(async {
tracing::info!("ExecuteJS 애플리케이션이 시작되었습니다.");
Expand All @@ -52,15 +50,7 @@ pub fn run() {
tracing::info!("ExecuteJS 애플리케이션이 종료됩니다.");
}
})
.invoke_handler(tauri::generate_handler![
greet,
execute_js,
get_js_execution_history,
clear_js_execution_history,
save_js_code,
load_js_code,
get_app_info
])
.invoke_handler(tauri::generate_handler![execute_js, get_app_info])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Expand Down
10 changes: 4 additions & 6 deletions apps/executeJS/src/features/execute-code/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ export const useExecutionStore = create<ExecutionState>()(

// 코드 실행
executeCode: async (code: string) => {
console.log('executeCode called -', code);

set({ isExecuting: true });

try {
Expand All @@ -37,15 +35,15 @@ export const useExecutionStore = create<ExecutionState>()(
result,
isExecuting: false,
});
} catch (error) {
} catch (error: any) {
//TODO: @ohah 에러 처리 더 명확하게 할 것
const result: JsExecutionResult = {
code,
result: '',
result: error?.result ?? '',
timestamp: new Date().toISOString(),
success: false,
error: error instanceof Error ? error.message : '알 수 없는 오류',
error: error?.error ?? '알 수 없는 오류',
};

set({
result,
isExecuting: false,
Expand Down
127 changes: 6 additions & 121 deletions docs/docs/api/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,141 +4,26 @@ ExecuteJS에서 사용할 수 있는 모든 Tauri 명령어를 확인하세요.

## 기본 명령어

### greet

인사말을 반환하는 기본 명령어입니다.

```typescript
import { invoke } from '@tauri-apps/api/core';

const message = await invoke('greet', { name: 'World' });
console.log(message); // "Hello World! You've been greeted from Rust!"
```

**매개변수:**
- `name` (string): 인사할 이름

**반환값:**
- `string`: 인사 메시지

### execute_js

JavaScript 코드를 실행합니다.
자바스크립트에 실행을 요청하는 명령어입니다.

```typescript
import { invoke } from '@tauri-apps/api/core';

const result = await invoke('execute_js', {
code: 'console.log("Hello, World!");'
const result = await invoke('execute_js', {
code: 'console.log("Hello, World!");',
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The trailing comma on line 15 creates inconsistency with the removed code, which didn't have a trailing comma. For single-parameter invocations in the documentation examples, the trailing comma is unnecessary and should be removed for consistency.

Suggested change
code: 'console.log("Hello, World!");',
code: 'console.log("Hello, World!")'

Copilot uses AI. Check for mistakes.
});
console.log(result);
```

**매개변수:**
- `code` (string): 실행할 JavaScript 코드

**반환값:**
- `JsExecutionResult`: 실행 결과 객체

## 실행 기록 관리

### get_js_execution_history

JavaScript 실행 기록을 가져옵니다.

```typescript
import { invoke } from '@tauri-apps/api/core';

const history = await invoke('get_js_execution_history');
console.log(history); // JsExecutionResult[]
```

**반환값:**
- `JsExecutionResult[]`: 실행 기록 배열

### clear_js_execution_history

JavaScript 실행 기록을 모두 삭제합니다.

```typescript
import { invoke } from '@tauri-apps/api/core';

await invoke('clear_js_execution_history');
```

## 코드 저장/로드

### save_js_code

JavaScript 코드를 로컬에 저장합니다.

```typescript
import { invoke } from '@tauri-apps/api/core';

await invoke('save_js_code', {
code: 'console.log("Saved code");'
});
```

**매개변수:**
- `code` (string): 저장할 JavaScript 코드

### load_js_code

저장된 JavaScript 코드를 불러옵니다.

```typescript
import { invoke } from '@tauri-apps/api/core';

const code = await invoke('load_js_code');
console.log(code); // string
```

**반환값:**
- `string`: 저장된 JavaScript 코드

## 앱 정보

### get_app_info

애플리케이션 정보를 가져옵니다.

```typescript
import { invoke } from '@tauri-apps/api/core';

const appInfo = await invoke('get_app_info');
console.log(appInfo);
```
- `code` (string): 실행할 JavaScript 코드

**반환값:**
- `AppInfo`: 애플리케이션 정보 객체

## 타입 정의

### JsExecutionResult

```typescript
interface JsExecutionResult {
id: string;
code: string;
result: string;
success: boolean;
timestamp: string;
executionTime: number;
}
```

### AppInfo

```typescript
interface AppInfo {
name: string;
version: string;
tauriVersion: string;
platform: string;
arch: string;
}
```
- `JsExecutionResult`: 실행 결과 객체

## 에러 처리

Expand All @@ -150,4 +35,4 @@ try {
} catch (error) {
console.error('Execution failed:', error);
}
```
```
Loading