From 6e9edd1c83deec210048976d9ad6901d1eab4dde Mon Sep 17 00:00:00 2001 From: ohah Date: Sat, 13 Dec 2025 03:21:26 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat(node-runtime):=20Deno=EC=97=90?= =?UTF-8?q?=EC=84=9C=20Node.js=20=EB=9F=B0=ED=83=80=EC=9E=84=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Deno Core 대신 Node.js 서브프로세스로 JavaScript 실행 - Node.js 바이너리 자동 다운로드 스크립트 추가 - lint_code 기능 제거 - deno-runtime 크레이트 제거 - hello-world 크레이트 제거 --- .cursorrules | 46 +- .gitignore | 7 + Cargo.lock | 894 +----------------- apps/executeJS/src-tauri/Cargo.toml | 16 +- .../src-tauri/capabilities/main.json | 13 +- apps/executeJS/src-tauri/src/commands.rs | 10 +- apps/executeJS/src-tauri/src/js_executor.rs | 14 +- apps/executeJS/src-tauri/src/lib.rs | 288 +++--- apps/executeJS/src-tauri/tauri.conf.json | 15 +- .../src/widgets/code-editor/code-editor.tsx | 143 ++- crates/node-runtime/Cargo.toml | 18 + crates/node-runtime/src/lib.rs | 504 ++++++++++ package.json | 4 +- scripts/download-node-binaries.js | 185 ++++ 14 files changed, 1015 insertions(+), 1142 deletions(-) create mode 100644 crates/node-runtime/Cargo.toml create mode 100644 crates/node-runtime/src/lib.rs create mode 100755 scripts/download-node-binaries.js diff --git a/.cursorrules b/.cursorrules index 0c34212..0a434bc 100644 --- a/.cursorrules +++ b/.cursorrules @@ -17,7 +17,7 @@ - **상태 관리**: Legend State - **코드 에디터**: Monaco Editor - **Backend**: Rust, Tauri 2.0 -- **JavaScript Engine**: Deno Core 0.323 (V8 기반) +- **JavaScript Engine**: Node.js v24.12.0 (V8 기반) - **Package Manager**: pnpm - **Linting**: oxlint (JavaScript) - **Formatting**: Prettier (JavaScript), rustfmt (Rust) @@ -25,32 +25,32 @@ ### JavaScript 런타임 아키텍처 -#### Deno Core 통합 -- **엔진**: `deno_core` 0.323 (V8 JavaScript 엔진) -- **실행 방식**: `tokio::task::spawn_blocking`으로 별도 스레드에서 실행 -- **호환성**: Tauri 2.0과 완전 호환 (Send 트레이트 문제 해결) +#### Node.js 통합 +- **엔진**: Node.js v24.12.0 (V8 JavaScript 엔진) +- **실행 방식**: `tokio::process::Command`로 서브프로세스 실행 +- **호환성**: Tauri 2.0과 완전 호환 #### 핵심 컴포넌트 ``` apps/executeJS/src-tauri/src/ -├── deno_runtime.rs # Deno Core 런타임 구현 -├── bootstrap.js # JavaScript API 정의 ├── js_executor.rs # 실행 결과 관리 └── commands.rs # Tauri 명령어 + +crates/node-runtime/ +├── src/lib.rs # Node.js 런타임 구현 +└── Cargo.toml ``` #### 실행 흐름 -1. **초기화**: `DenoExecutor::new()` - 출력 버퍼 설정 -2. **실행**: `execute_script()` - 별도 스레드에서 Deno Core 실행 -3. **API 연결**: `bootstrap.js` - console.log, alert 등 커스텀 API -4. **결과 처리**: 출력 버퍼에서 결과 수집 및 반환 +1. **초기화**: `NodeExecutor::new()` - Node.js 바이너리 경로 찾기 +2. **실행**: `execute_script()` - 서브프로세스로 Node.js 실행 +3. **결과 처리**: stdout/stderr에서 결과 수집 및 반환 #### 지원 기능 -- ✅ `console.log()` - 다중 인자, 객체 직렬화 -- ✅ `alert()` - 사용자 알림 +- ✅ `console.log()` - 표준 출력 - ✅ 변수 할당 및 계산 - ✅ 문법 오류 감지 (실제 JavaScript 엔진 수준) -- ✅ Chrome DevTools 수준의 출력 +- ✅ Node.js 표준 기능 지원 ## FSD 아키텍처 규칙 @@ -196,10 +196,9 @@ chore: 빌드 설정 변경 - 네이티브 로그 확인 ### JavaScript 런타임 -- `cargo test deno_runtime::tests` - 런타임 테스트 -- `bootstrap.js` 수정 시 재컴파일 필요 -- op 함수 추가 시 `extension!` 매크로 업데이트 -- 전역 상태(`OUTPUT_BUFFER`) 주의 +- `cargo test node_runtime::tests` - 런타임 테스트 +- Node.js 바이너리 경로 확인 필요 +- 리소스 번들링 확인 (`tauri.conf.json`) ## 주의사항 @@ -227,9 +226,8 @@ chore: 빌드 설정 변경 2. `cargo fmt` 실행 3. 수동으로 규칙에 맞게 수정 -### Deno Core 관련 문제 -1. **Send 트레이트 오류**: `tokio::task::spawn_blocking` 사용 확인 -2. **op 함수 오류**: `#[op2(fast)]` 속성 및 `extension!` 매크로 확인 -3. **bootstrap.js 오류**: `include_str!` 매크로로 올바르게 포함되었는지 확인 -4. **전역 상태 충돌**: 테스트 간 격리 락 사용 -5. **V8 엔진 오류**: `deno_core` 버전 호환성 확인 +### Node.js 런타임 관련 문제 +1. **바이너리 경로 오류**: 개발/프로덕션 모드 경로 확인 +2. **리소스 번들링 오류**: `tauri.conf.json`의 `resources` 설정 확인 +3. **권한 오류**: Unix 시스템에서 실행 권한 설정 확인 +4. **서브프로세스 오류**: `tokio::process::Command` 실행 확인 diff --git a/.gitignore b/.gitignore index 9e51e73..537bc29 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,10 @@ temp/ # Tauri generated files **/src-tauri/gen + +# Node.js 바이너리 (자동 다운로드됨) +apps/executeJS/src-tauri/resources/node-runtime/**/node +apps/executeJS/src-tauri/resources/node-runtime/**/node.exe + +# 임시 다운로드 디렉토리 +.temp-node-download/ diff --git a/Cargo.lock b/Cargo.lock index 1fc8830..f2c1e6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.1" @@ -262,29 +256,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "aws-lc-rs" -version = "1.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879b6c89592deb404ba4dc0ae6b58ffd1795c78991cbb5b8bc441c48a070440d" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "107a4e9d9cab9963e04e84bb8dee0e25f2a987f9a8bad5ed054abd439caa8f8c" -dependencies = [ - "bindgen 0.72.1", - "cc", - "cmake", - "dunce", - "fs_extra", -] - [[package]] name = "axum" version = "0.6.20" @@ -330,12 +301,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "az" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" - [[package]] name = "base64" version = "0.21.7" @@ -348,79 +313,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64-simd" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" -dependencies = [ - "simd-abstraction", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bindgen" -version = "0.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" -dependencies = [ - "bitflags 2.10.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.108", -] - -[[package]] -name = "bindgen" -version = "0.72.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" -dependencies = [ - "bitflags 2.10.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 2.1.1", - "shlex", - "syn 2.0.108", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" version = "1.3.2" @@ -436,18 +328,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block" version = "0.1.6" @@ -599,7 +479,7 @@ checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", - "semver 1.0.27", + "semver", "serde", "serde_json", "thiserror 2.0.17", @@ -622,8 +502,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] @@ -633,15 +511,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfb" version = "0.7.3" @@ -689,17 +558,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading 0.8.9", -] - [[package]] name = "clipboard-win" version = "5.4.1" @@ -709,15 +567,6 @@ dependencies = [ "error-code", ] -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - [[package]] name = "cocoa" version = "0.26.1" @@ -729,7 +578,7 @@ dependencies = [ "cocoa-foundation", "core-foundation 0.10.1", "core-graphics", - "foreign-types 0.5.0", + "foreign-types", "libc", "objc", ] @@ -782,12 +631,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "cooked-waker" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" - [[package]] name = "cookie" version = "0.18.1" @@ -852,7 +695,7 @@ dependencies = [ "bitflags 2.10.0", "core-foundation 0.10.1", "core-graphics-types", - "foreign-types 0.5.0", + "foreign-types", "libc", ] @@ -988,113 +831,12 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - [[package]] name = "data-url" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" -[[package]] -name = "debugid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" -dependencies = [ - "serde", - "uuid", -] - -[[package]] -name = "deno-runtime" -version = "0.1.0" -dependencies = [ - "anyhow", - "deno_core", - "dirs 5.0.1", - "flate2", - "futures", - "reqwest", - "serde", - "serde_json", - "tar", - "tokio", - "tracing", -] - -[[package]] -name = "deno_core" -version = "0.323.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a781bcfe1b5211b8497f45bf5b3dba73036b8d5d1533c1f05d26ccf0afb25a78" -dependencies = [ - "anyhow", - "az", - "bincode", - "bit-set", - "bit-vec", - "bytes", - "cooked-waker", - "deno_core_icudata", - "deno_ops", - "deno_unsync", - "futures", - "indexmap 2.12.0", - "libc", - "memoffset", - "parking_lot", - "percent-encoding", - "pin-project", - "serde", - "serde_json", - "serde_v8", - "smallvec", - "sourcemap", - "static_assertions", - "tokio", - "url", - "v8", - "wasm_dep_analyzer", -] - -[[package]] -name = "deno_core_icudata" -version = "0.74.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695" - -[[package]] -name = "deno_ops" -version = "0.199.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24a1f3e22029a57d3094b32070b8328eac793920b5a022027d360f085e6b245" -dependencies = [ - "proc-macro-rules", - "proc-macro2", - "quote", - "stringcase", - "strum", - "strum_macros", - "syn 2.0.108", - "thiserror 1.0.69", -] - -[[package]] -name = "deno_unsync" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6742a724e8becb372a74c650a1aefb8924a5b8107f7d75b3848763ea24b27a87" -dependencies = [ - "futures-util", - "parking_lot", - "tokio", -] - [[package]] name = "deranged" version = "0.5.5" @@ -1114,7 +856,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.1", + "rustc_version", "syn 2.0.108", ] @@ -1170,34 +912,13 @@ dependencies = [ "crypto-common", ] -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys 0.4.1", -] - [[package]] name = "dirs" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ - "dirs-sys 0.5.0", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users 0.4.6", - "windows-sys 0.48.0", + "dirs-sys", ] [[package]] @@ -1208,7 +929,7 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users 0.5.2", + "redox_users", "windows-sys 0.61.2", ] @@ -1327,7 +1048,7 @@ checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e" dependencies = [ "cc", "memchr", - "rustc_version 0.4.1", + "rustc_version", "toml 0.9.8", "vswhom", "winreg", @@ -1434,17 +1155,8 @@ name = "executeJS" version = "0.1.0" dependencies = [ "anyhow", - "bytes", "chrono", - "deno-runtime", - "flate2", - "futures-util", - "http-body-util", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "native-tls", - "regex", + "node-runtime", "serde", "serde_json", "tauri", @@ -1458,9 +1170,6 @@ dependencies = [ "tempfile", "thiserror 2.0.17", "tokio", - "tokio-native-tls", - "tokio-rustls", - "tokio-stream", "tracing", "tracing-appender", "tracing-subscriber", @@ -1508,19 +1217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ "memoffset", - "rustc_version 0.4.1", -] - -[[package]] -name = "filetime" -version = "0.2.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.60.2", + "rustc_version", ] [[package]] @@ -1542,7 +1239,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", - "miniz_oxide 0.8.9", + "miniz_oxide", ] [[package]] @@ -1551,15 +1248,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - [[package]] name = "foreign-types" version = "0.5.0" @@ -1567,7 +1255,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared 0.3.1", + "foreign-types-shared", ] [[package]] @@ -1581,12 +1269,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -1602,28 +1284,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "fslock" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futf" version = "0.1.5" @@ -2050,15 +1710,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "gzip-header" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2" -dependencies = [ - "crc32fast", -] - [[package]] name = "h2" version = "0.3.27" @@ -2132,10 +1783,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hello-world" -version = "0.1.0" - [[package]] name = "hermit-abi" version = "0.5.2" @@ -2148,15 +1795,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "html5ever" version = "0.29.1" @@ -2298,9 +1936,7 @@ dependencies = [ "http 1.3.1", "hyper 1.7.0", "hyper-util", - "log", "rustls", - "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", @@ -2320,22 +1956,6 @@ dependencies = [ "tokio-io-timeout", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.7.0", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.17" @@ -2509,12 +2129,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "if_chain" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" - [[package]] name = "image" version = "0.25.8" @@ -2605,15 +2219,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.15" @@ -2665,16 +2270,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - [[package]] name = "js-sys" version = "0.3.81" @@ -2756,7 +2351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading 0.7.4", + "libloading", "once_cell", ] @@ -2776,16 +2371,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link 0.2.1", -] - [[package]] name = "libredox" version = "0.1.10" @@ -2794,7 +2379,6 @@ checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.10.0", "libc", - "redox_syscall", ] [[package]] @@ -2942,15 +2526,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3003,23 +2578,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", -] - [[package]] name = "ndk" version = "0.9.0" @@ -3094,6 +2652,15 @@ dependencies = [ "memoffset", ] +[[package]] +name = "node-runtime" +version = "0.1.0" +dependencies = [ + "anyhow", + "tokio", + "tracing", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -3119,32 +2686,12 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", - "rand 0.8.5", -] - [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -3467,50 +3014,6 @@ dependencies = [ "pathdiff", ] -[[package]] -name = "openssl" -version = "0.10.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.108", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.110" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "option-ext" version = "0.2.0" @@ -3537,12 +3040,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "outref" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" - [[package]] name = "pango" version = "0.18.3" @@ -3597,12 +3094,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "pathdiff" version = "0.2.3" @@ -3831,7 +3322,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.9", + "miniz_oxide", ] [[package]] @@ -3844,7 +3335,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.9", + "miniz_oxide", ] [[package]] @@ -3906,16 +3397,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.108", -] - [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -3975,29 +3456,6 @@ version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" -[[package]] -name = "proc-macro-rules" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" -dependencies = [ - "proc-macro-rules-macros", - "proc-macro2", - "syn 2.0.108", -] - -[[package]] -name = "proc-macro-rules-macros" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "207fffb0fe655d1d47f6af98cc2793405e85929bdbc420d685554ff07be27ac7" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.108", -] - [[package]] name = "proc-macro2" version = "1.0.103" @@ -4024,7 +3482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools", "proc-macro2", "quote", "syn 2.0.108", @@ -4099,7 +3557,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", + "rustc-hash", "rustls", "socket2 0.6.1", "thiserror 2.0.17", @@ -4119,7 +3577,7 @@ dependencies = [ "lru-slab", "rand 0.9.2", "ring", - "rustc-hash 2.1.1", + "rustc-hash", "rustls", "rustls-pki-types", "slab", @@ -4158,12 +3616,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand" version = "0.7.3" @@ -4289,17 +3741,6 @@ dependencies = [ "bitflags 2.10.0", ] -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom 0.2.16", - "libredox", - "thiserror 1.0.69", -] - [[package]] name = "redox_users" version = "0.5.2" @@ -4379,12 +3820,10 @@ dependencies = [ "http-body-util", "hyper 1.7.0", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -4395,7 +3834,6 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.2", "tokio", - "tokio-native-tls", "tokio-rustls", "tokio-util", "tower 0.5.2", @@ -4434,34 +3872,19 @@ dependencies = [ "portable-atomic-util", ] -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.27", + "semver", ] [[package]] @@ -4496,8 +3919,6 @@ version = "0.23.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ - "aws-lc-rs", - "log", "once_cell", "ring", "rustls-pki-types", @@ -4506,18 +3927,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework 3.5.1", -] - [[package]] name = "rustls-pki-types" version = "1.12.0" @@ -4534,7 +3943,6 @@ version = "0.103.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -4561,15 +3969,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "schemars" version = "0.8.22" @@ -4627,42 +4026,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.10.1", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "selectors" version = "0.24.0" @@ -4681,15 +4044,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.27" @@ -4700,12 +4054,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.228" @@ -4765,7 +4113,6 @@ version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "indexmap 2.12.0", "itoa", "memchr", "ryu", @@ -4814,19 +4161,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_v8" -version = "0.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c9feae92f7293fcc1a32a86be1a399859c0637e55dad8991d5258c43f7ff4d2" -dependencies = [ - "num-bigint", - "serde", - "smallvec", - "thiserror 1.0.69", - "v8", -] - [[package]] name = "serde_with" version = "3.15.1" @@ -4925,15 +4259,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-abstraction" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" -dependencies = [ - "outref", -] - [[package]] name = "simd-adler32" version = "0.3.7" @@ -4993,7 +4318,7 @@ dependencies = [ "bytemuck", "cfg_aliases", "core-graphics", - "foreign-types 0.5.0", + "foreign-types", "js-sys", "log", "objc2 0.5.2", @@ -5032,25 +4357,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "sourcemap" -version = "8.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "208d40b9e8cad9f93613778ea295ed8f3c2b1824217c6cfc7219d3f6f45b96d4" -dependencies = [ - "base64-simd", - "bitvec", - "data-encoding", - "debugid", - "if_chain", - "rustc-hash 1.1.0", - "rustc_version 0.2.3", - "serde", - "serde_json", - "unicode-id-start", - "url", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -5088,40 +4394,12 @@ dependencies = [ "quote", ] -[[package]] -name = "stringcase" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04028eeb851ed08af6aba5caa29f2d59a13ed168cee4d6bd753aeefcf1d636b0" - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.108", -] - [[package]] name = "subtle" version = "2.6.1" @@ -5272,23 +4550,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tar" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "target-lexicon" version = "0.12.16" @@ -5304,7 +4565,7 @@ dependencies = [ "anyhow", "bytes", "cookie", - "dirs 6.0.0", + "dirs", "dunce", "embed_plist", "getrandom 0.3.4", @@ -5355,12 +4616,12 @@ checksum = "a924b6c50fe83193f0f8b14072afa7c25b7a72752a2a73d9549b463f5fe91a38" dependencies = [ "anyhow", "cargo_toml", - "dirs 6.0.0", + "dirs", "glob", "heck 0.5.0", "json-patch", "schemars 0.8.22", - "semver 1.0.27", + "semver", "serde", "serde_json", "tauri-utils", @@ -5383,7 +4644,7 @@ dependencies = [ "png 0.17.16", "proc-macro2", "quote", - "semver 1.0.27", + "semver", "serde", "serde_json", "sha2", @@ -5630,7 +4891,7 @@ dependencies = [ "quote", "regex", "schemars 0.8.22", - "semver 1.0.27", + "semver", "serde", "serde-untagged", "serde_json", @@ -5835,16 +5096,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" @@ -6199,7 +5450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d5572781bee8e3f994d7467084e1b1fd7a93ce66bd480f8156ba89dee55a2b" dependencies = [ "crossbeam-channel", - "dirs 6.0.0", + "dirs", "libappindicator", "muda", "objc2 0.6.3", @@ -6296,12 +5547,6 @@ dependencies = [ "unic-common", ] -[[package]] -name = "unicode-id-start" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" - [[package]] name = "unicode-ident" version = "1.0.20" @@ -6368,35 +5613,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "v8" -version = "130.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a511192602f7b435b0a241c1947aa743eb7717f20a9195f4b5e8ed1952e01db1" -dependencies = [ - "bindgen 0.70.1", - "bitflags 2.10.0", - "fslock", - "gzip-header", - "home", - "miniz_oxide 0.7.4", - "once_cell", - "paste", - "which", -] - [[package]] name = "valuable" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version-compare" version = "0.2.0" @@ -6554,15 +5776,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasm_dep_analyzer" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f270206a91783fd90625c8bb0d8fbd459d0b1d1bf209b656f713f01ae7c04b8" -dependencies = [ - "thiserror 1.0.69", -] - [[package]] name = "wayland-backend" version = "0.3.11" @@ -6748,18 +5961,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" -[[package]] -name = "which" -version = "6.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" -dependencies = [ - "either", - "home", - "rustix 0.38.44", - "winsafe", -] - [[package]] name = "winapi" version = "0.3.9" @@ -7299,12 +6500,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "winsafe" -version = "0.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" - [[package]] name = "wit-bindgen" version = "0.46.0" @@ -7346,7 +6541,7 @@ dependencies = [ "block2 0.6.2", "cookie", "crossbeam-channel", - "dirs 6.0.0", + "dirs", "dpi", "dunce", "gdkx11", @@ -7382,15 +6577,6 @@ dependencies = [ "x11-dl", ] -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "x11" version = "2.21.0" @@ -7429,16 +6615,6 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" -[[package]] -name = "xattr" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" -dependencies = [ - "libc", - "rustix 1.1.2", -] - [[package]] name = "yoke" version = "0.8.0" diff --git a/apps/executeJS/src-tauri/Cargo.toml b/apps/executeJS/src-tauri/Cargo.toml index 7b310da..8474957 100644 --- a/apps/executeJS/src-tauri/Cargo.toml +++ b/apps/executeJS/src-tauri/Cargo.toml @@ -31,22 +31,10 @@ chrono = { version = "0.4", features = ["serde"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["fmt", "registry", "env-filter"] } tracing-appender = "0.2" -regex = "1.0" -bytes = "1.0" -futures-util = "0.3" -http-body-util = "0.1" -hyper-util = "0.1" -hyper-tls = "0.6" -hyper-rustls = "0.27" -tokio-native-tls = "0.3" -native-tls = "0.2" -tokio-rustls = "0.26" -tokio-stream = "0.1" -flate2 = "1.1" tempfile = "3.23.0" -# JavaScript 런타임 의존성 (Deno Core) -deno-runtime = { path = "../../../crates/deno-runtime" } +# JavaScript 런타임 의존성 (Node.js) +node-runtime = { path = "../../../crates/node-runtime" } [features] # this feature is used for production builds or when `devPath` points to the filesystem diff --git a/apps/executeJS/src-tauri/capabilities/main.json b/apps/executeJS/src-tauri/capabilities/main.json index 294da43..a600c92 100644 --- a/apps/executeJS/src-tauri/capabilities/main.json +++ b/apps/executeJS/src-tauri/capabilities/main.json @@ -1,9 +1,16 @@ { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "main", - "windows": ["main", "settings"], + "windows": [ + "main", + "settings" + ], "permissions": [ - "core:window:allow-set-title" + "core:window:allow-set-title", + "http:default", + "opener:default", + "fs:default", + "clipboard-manager:default", + "store:default" ] } - diff --git a/apps/executeJS/src-tauri/src/commands.rs b/apps/executeJS/src-tauri/src/commands.rs index e632eea..e3581ae 100644 --- a/apps/executeJS/src-tauri/src/commands.rs +++ b/apps/executeJS/src-tauri/src/commands.rs @@ -1,6 +1,7 @@ use crate::js_executor::{execute_javascript_code, JsExecutionResult}; use serde::{Deserialize, Serialize}; -use std::process::Command; +// 비활성화: Command import (lint_code가 주석 처리되어 사용 안 함) +// use std::process::Command; #[derive(Debug, Serialize, Deserialize)] pub struct AppInfo { @@ -10,6 +11,8 @@ pub struct AppInfo { pub author: String, } +// 비활성화: 린트 관련 구조체 +/* // 린트 결과를 나타내는 구조체 #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] @@ -60,6 +63,7 @@ struct OxlintSpan { #[serde(default)] length: usize, } +*/ #[tauri::command] pub async fn execute_js(code: &str) -> Result { @@ -92,7 +96,8 @@ pub fn get_app_info() -> AppInfo { } } -// JavaScript 코드를 oxlint로 린트하고 결과를 반환 +// 비활성화: JavaScript 코드를 oxlint로 린트하고 결과를 반환 +/* #[tauri::command] pub async fn lint_code(code: String) -> Result, String> { use std::io::Write; @@ -239,3 +244,4 @@ fn parse_oxlint_output(stdout: &str, stderr: &str) -> Vec { } } } +*/ diff --git a/apps/executeJS/src-tauri/src/js_executor.rs b/apps/executeJS/src-tauri/src/js_executor.rs index a5997be..4ec10c1 100644 --- a/apps/executeJS/src-tauri/src/js_executor.rs +++ b/apps/executeJS/src-tauri/src/js_executor.rs @@ -1,4 +1,4 @@ -use deno_runtime::DenoExecutor; +use node_runtime::NodeExecutor; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -24,8 +24,8 @@ pub async fn execute_javascript_code(code: &str) -> JsExecutionResult { }; } - // DenoExecutor를 사용한 실제 JavaScript 실행 - match execute_with_deno(code).await { + // NodeExecutor를 사용한 실제 JavaScript 실행 + match execute_with_node(code).await { Ok(output) => JsExecutionResult { code: code.to_string(), result: output, @@ -43,10 +43,10 @@ pub async fn execute_javascript_code(code: &str) -> JsExecutionResult { } } -/// Deno를 사용한 JavaScript 코드 실행 -async fn execute_with_deno(code: &str) -> Result> { - // DenoExecutor 생성 - let mut executor = DenoExecutor::new().await.map_err(|e| format!("{}", e))?; +/// Node.js를 사용한 JavaScript 코드 실행 +async fn execute_with_node(code: &str) -> Result> { + // NodeExecutor 생성 + let executor = NodeExecutor::new().map_err(|e| format!("{}", e))?; // 코드 실행 let result = executor diff --git a/apps/executeJS/src-tauri/src/lib.rs b/apps/executeJS/src-tauri/src/lib.rs index a1f6f00..11a3d23 100644 --- a/apps/executeJS/src-tauri/src/lib.rs +++ b/apps/executeJS/src-tauri/src/lib.rs @@ -12,167 +12,155 @@ use tauri::{Manager, WebviewUrl, WebviewWindowBuilder}; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { + let mut builder = tauri::Builder::default() + .plugin(tauri_plugin_http::init()) + .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_fs::init()) + .plugin(tauri_plugin_clipboard_manager::init()) + .plugin(tauri_plugin_store::Builder::default().build()); + + // DevTools 플러그인 추가 (개발 빌드에서만) #[cfg(debug_assertions)] { - let mut builder = tauri::Builder::default() - .plugin(tauri_plugin_http::init()) - .plugin(tauri_plugin_opener::init()) - .plugin(tauri_plugin_fs::init()) - .plugin(tauri_plugin_clipboard_manager::init()) - .plugin(tauri_plugin_store::Builder::default().build()); - - // DevTools 플러그인 추가 (개발 빌드에서만) - #[cfg(debug_assertions)] - { - builder = builder.plugin(tauri_plugin_devtools::init()); - } - - builder - .setup(|app_handle| { - // Window Menu - let about_menu = SubmenuBuilder::new(app_handle, "About") - .text("about", "About ExecuteJS") - .separator() - .text("settings", "Settings...") - .separator() - .text("quit", "Quit ExecuteJS") - .build()?; - - let file_menu = SubmenuBuilder::new(app_handle, "File") - .text("new_tab", "New Tab") - .separator() - .text("close_tab", "Close Tab") - .build()?; - - let edit_menu = SubmenuBuilder::new(app_handle, "Edit") - .undo() - .redo() - .separator() - .cut() - .copy() - .paste() - .separator() - .select_all() - .build()?; - - let view_menu = SubmenuBuilder::new(app_handle, "View") - .text("reload", "Reload") - .text("toggle_devtools", "Toggle Developer Tools") - .build()?; - - // Main Menu - let menu = MenuBuilder::new(app_handle) - .items(&[&about_menu, &file_menu, &edit_menu, &view_menu]) - .build()?; - - app_handle.set_menu(menu)?; - - // Menu Event - app_handle.on_menu_event(move |app_handle, event| { - match event.id().0.as_str() { - // About Menu - "about" => { - // TODO: About ExecuteJS 다이얼로그 표시 - eprintln!("About ExecuteJS 메뉴 클릭됨"); - } - "settings" => { - // Settings 창이 이미 열려있는지 확인 - if let Some(existing_window) = app_handle.get_webview_window("settings") - { - existing_window.set_focus().unwrap_or_default(); + builder = builder.plugin(tauri_plugin_devtools::init()); + } + + builder + .setup(|app_handle| { + // Window Menu + let about_menu = SubmenuBuilder::new(app_handle, "About") + .text("about", "About ExecuteJS") + .separator() + .text("settings", "Settings...") + .separator() + .text("quit", "Quit ExecuteJS") + .build()?; + + let file_menu = SubmenuBuilder::new(app_handle, "File") + .text("new_tab", "New Tab") + .separator() + .text("close_tab", "Close Tab") + .build()?; + + let edit_menu = SubmenuBuilder::new(app_handle, "Edit") + .undo() + .redo() + .separator() + .cut() + .copy() + .paste() + .separator() + .select_all() + .build()?; + + let view_menu = SubmenuBuilder::new(app_handle, "View") + .text("reload", "Reload") + .text("toggle_devtools", "Toggle Developer Tools") + .build()?; + + // Main Menu + let menu = MenuBuilder::new(app_handle) + .items(&[&about_menu, &file_menu, &edit_menu, &view_menu]) + .build()?; + + app_handle.set_menu(menu)?; + + // Menu Event + app_handle.on_menu_event(move |app_handle, event| { + match event.id().0.as_str() { + // About Menu + "about" => { + // TODO: About ExecuteJS 다이얼로그 표시 + eprintln!("About ExecuteJS 메뉴 클릭됨"); + } + "settings" => { + // Settings 창이 이미 열려있는지 확인 + if let Some(existing_window) = app_handle.get_webview_window("settings") { + existing_window.set_focus().unwrap_or_default(); + } else { + // 새 Settings 창 생성 + // 개발 모드에서는 devUrl 사용, 프로덕션에서는 App 경로 사용 + let url = if cfg!(debug_assertions) { + WebviewUrl::External( + "http://localhost:1420/settings" + .parse() + .expect("failed to parse dev settings URL"), + ) } else { - // 새 Settings 창 생성 - // 개발 모드에서는 devUrl 사용, 프로덕션에서는 App 경로 사용 - let url = if cfg!(debug_assertions) { - WebviewUrl::External( - "http://localhost:1420/settings" - .parse() - .expect("failed to parse dev settings URL"), - ) - } else { - // TODO: 해시 라우팅을 사용하여 Settings 페이지로 이동 처리. 다른 방법으로 수정 필요 - WebviewUrl::App("index.html#/settings".into()) - }; - - match WebviewWindowBuilder::new(app_handle, "settings", url) - .title("General") - .inner_size(800.0, 600.0) - .min_inner_size(600.0, 400.0) - .resizable(true) - .build() - { - Ok(settings_window) => { - // Settings 창에서 개발자 도구 자동 열기 - #[cfg(debug_assertions)] - { - settings_window.open_devtools(); - } - } - Err(e) => { - eprintln!("Settings 창 생성 실패: {:?}", e); - } + // TODO: 해시 라우팅을 사용하여 Settings 페이지로 이동 처리. 다른 방법으로 수정 필요 + WebviewUrl::App("index.html#/settings".into()) + }; + + match WebviewWindowBuilder::new(app_handle, "settings", url) + .title("General") + .inner_size(800.0, 600.0) + .min_inner_size(600.0, 400.0) + .resizable(true) + .build() + { + Ok(_settings_window) => { + // Settings 창 생성 완료 + // DevTools는 플러그인을 통해 자동으로 관리됨 + } + Err(e) => { + eprintln!("Settings 창 생성 실패: {:?}", e); } } } - "quit" => { - app_handle.exit(0); - } + } + "quit" => { + app_handle.exit(0); + } - // File Menu - "new_tab" => { - // TODO: 새 탭 추가 - eprintln!("New Tab 메뉴 클릭됨"); - } - "close_tab" => { - // TODO: 현재 탭 닫기 - eprintln!("Close Tab 메뉴 클릭됨"); - } + // File Menu + "new_tab" => { + // TODO: 새 탭 추가 + eprintln!("New Tab 메뉴 클릭됨"); + } + "close_tab" => { + // TODO: 현재 탭 닫기 + eprintln!("Close Tab 메뉴 클릭됨"); + } - // View Menu - "reload" => { - if let Some(window) = app_handle.get_webview_window("main") { - window.eval("window.location.reload()").unwrap(); - } + // View Menu + "reload" => { + if let Some(window) = app_handle.get_webview_window("main") { + window.eval("window.location.reload()").unwrap(); } - "toggle_devtools" => { - if let Some(window) = app_handle.get_webview_window("main") { - window.open_devtools(); - window.close_devtools(); + } + "toggle_devtools" => { + // Tauri 2.0에서는 DevTools 플러그인을 통해 제어 + #[cfg(debug_assertions)] + { + if app_handle.get_webview_window("main").is_some() { + // DevTools는 플러그인을 통해 자동으로 관리됨 + eprintln!("DevTools 토글 (플러그인 사용)"); } } - _ => { - eprintln!("메뉴 이벤트: {:?}", event.id()); - } } - }); - - // JavaScript 실행기 상태 관리 - #[cfg(debug_assertions)] - { - let window = app_handle.get_webview_window("main").unwrap(); - window.open_devtools(); - window.close_devtools(); - } - - // 앱 시작 시 초기화 작업 - tauri::async_runtime::spawn(async { - tracing::info!("ExecuteJS 애플리케이션이 시작되었습니다."); - }); - - Ok(()) - }) - .on_window_event(|_window, event| { - // 앱 종료 시 정리 작업 - if let tauri::WindowEvent::CloseRequested { .. } = event { - tracing::info!("ExecuteJS 애플리케이션이 종료됩니다."); + _ => { + eprintln!("메뉴 이벤트: {:?}", event.id()); + } } - }) - .invoke_handler(tauri::generate_handler![ - execute_js, - get_app_info, - lint_code - ]) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); - } + }); + + // JavaScript 실행기 상태 관리 + // DevTools는 플러그인을 통해 자동으로 관리됨 + + // 앱 시작 시 초기화 작업 + tauri::async_runtime::spawn(async { + tracing::info!("ExecuteJS 애플리케이션이 시작되었습니다."); + }); + + Ok(()) + }) + .on_window_event(|_window, event| { + // 앱 종료 시 정리 작업 + if let tauri::WindowEvent::CloseRequested { .. } = event { + tracing::info!("ExecuteJS 애플리케이션이 종료됩니다."); + } + }) + .invoke_handler(tauri::generate_handler![execute_js, get_app_info]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); } diff --git a/apps/executeJS/src-tauri/tauri.conf.json b/apps/executeJS/src-tauri/tauri.conf.json index 6d7a0ce..9f34e5a 100644 --- a/apps/executeJS/src-tauri/tauri.conf.json +++ b/apps/executeJS/src-tauri/tauri.conf.json @@ -23,13 +23,24 @@ ], "security": { "csp": null, - "capabilities": ["main"] + "capabilities": [ + "main" + ] } }, "bundle": { "active": true, - "targets": ["msi", "nsis", "dmg", "app"], + "targets": [ + "msi", + "nsis", + "dmg", + "app" + ], "icon": [], + "resources": [ + "resources/node-runtime/node-v24.12.0-darwin-arm64/node", + "resources/node-runtime/node-v24.12.0-win-arm64/node.exe" + ], "macOS": { "entitlements": null, "exceptionDomain": "", diff --git a/apps/executeJS/src/widgets/code-editor/code-editor.tsx b/apps/executeJS/src/widgets/code-editor/code-editor.tsx index 046a339..4e85209 100644 --- a/apps/executeJS/src/widgets/code-editor/code-editor.tsx +++ b/apps/executeJS/src/widgets/code-editor/code-editor.tsx @@ -1,6 +1,5 @@ -import React, { useCallback, useEffect, useRef } from 'react'; +import React, { useEffect, useRef } from 'react'; -import { invoke } from '@tauri-apps/api/core'; import { Editor, EditorProps, Monaco } from '@monaco-editor/react'; import type { Options as PrettierOptions } from 'prettier'; import prettier from 'prettier/standalone'; @@ -8,7 +7,7 @@ import babel from 'prettier/plugins/babel'; import estree from 'prettier/plugins/estree'; import typescript from 'prettier/plugins/typescript'; -import { CodeEditorProps, LintResult, LintSeverity } from '@/shared'; +import { CodeEditorProps } from '@/shared'; const prettierOptions: PrettierOptions = { semi: true, @@ -19,6 +18,8 @@ const prettierOptions: PrettierOptions = { useTabs: false, }; +// 비활성화: lint 관련 함수 +/* const severityToMarkerSeverity = (severity: LintSeverity, monaco: Monaco) => { switch (severity) { case 'error': @@ -35,6 +36,7 @@ const severityToMarkerSeverity = (severity: LintSeverity, monaco: Monaco) => { return monaco.MarkerSeverity.Warning; } }; +*/ export const CodeEditor: React.FC = ({ value, @@ -46,62 +48,62 @@ export const CodeEditor: React.FC = ({ const editorRef = useRef(null); const monacoRef = useRef(null); const disposablesRef = useRef>([]); - const debounceTimeoutRef = useRef(null); - - const validateCode = useCallback(async (model: any, version: number) => { - if (debounceTimeoutRef.current) { - clearTimeout(debounceTimeoutRef.current); - } - - debounceTimeoutRef.current = setTimeout(async () => { - if (!model || !monacoRef.current) return; - - try { - const code = model.getValue(); - - // Tauri 백엔드에서 oxlint 실행 - const lintResults = await invoke>('lint_code', { - code, - }); - - // setModelMarkers 사용 - const monaco = monacoRef.current; - if (monaco && model.getVersionId() === version) { - const markers = lintResults.map((result) => { - // Monaco는 1-based 인덱스 사용 - const startColumn = Math.max(1, result.column); - const endColumn = Math.max(startColumn + 1, result.end_column); - - // severity를 소문자로 비교하여 MarkerSeverity enum 사용 - const severity = severityToMarkerSeverity(result.severity, monaco); - - return { - message: `${result.message} (${result.rule_id})`, - severity, - startLineNumber: result.line, - startColumn: startColumn, - endLineNumber: result.end_line, - endColumn: endColumn, - source: 'oxlint', - code: result.rule_id, - }; - }); - - monaco.editor.setModelMarkers(model, 'oxlint', markers); - } - } catch (error) { - console.error('oxlint validation error:', error); - // 에러 발생 시 마커 초기화 - const monaco = monacoRef.current; - if (monaco) { - const model = editorRef.current?.getModel(); - if (model && model.getVersionId() === version) { - monaco.editor.setModelMarkers(model, 'oxlint', []); - } - } - } - }, 500); - }, []); + // const debounceTimeoutRef = useRef(null); + + // const validateCode = useCallback(async (model: any, version: number) => { + // if (debounceTimeoutRef.current) { + // clearTimeout(debounceTimeoutRef.current); + // } + + // debounceTimeoutRef.current = setTimeout(async () => { + // if (!model || !monacoRef.current) return; + + // try { + // const code = model.getValue(); + + // // Tauri 백엔드에서 oxlint 실행 + // const lintResults = await invoke>('lint_code', { + // code, + // }); + + // // setModelMarkers 사용 + // const monaco = monacoRef.current; + // if (monaco && model.getVersionId() === version) { + // const markers = lintResults.map((result) => { + // // Monaco는 1-based 인덱스 사용 + // const startColumn = Math.max(1, result.column); + // const endColumn = Math.max(startColumn + 1, result.end_column); + + // // severity를 소문자로 비교하여 MarkerSeverity enum 사용 + // const severity = severityToMarkerSeverity(result.severity, monaco); + + // return { + // message: `${result.message} (${result.rule_id})`, + // severity, + // startLineNumber: result.line, + // startColumn: startColumn, + // endLineNumber: result.end_line, + // endColumn: endColumn, + // source: 'oxlint', + // code: result.rule_id, + // }; + // }); + + // monaco.editor.setModelMarkers(model, 'oxlint', markers); + // } + // } catch (error) { + // console.error('oxlint validation error:', error); + // // 에러 발생 시 마커 초기화 + // const monaco = monacoRef.current; + // if (monaco) { + // const model = editorRef.current?.getModel(); + // if (model && model.getVersionId() === version) { + // monaco.editor.setModelMarkers(model, 'oxlint', []); + // } + // } + // } + // }, 500); + // }, []); // Monaco Editor 설정 const handleEditorDidMount: EditorProps['onMount'] = (editor, monaco) => { @@ -198,24 +200,8 @@ export const CodeEditor: React.FC = ({ const model = editor.getModel(); if (model) { - // 모델 변경 시 validation - const contentChangeDisposable = model.onDidChangeContent(() => { - // Reset the markers - monaco.editor.setModelMarkers(model, 'oxlint', []); - - // Send the code to the backend for validation - validateCode(model, model.getVersionId()); - }); - - // model이 있는 경우 포맷터 + 이벤트 리스너 저장 - disposablesRef.current = [ - jsDisposable, - tsDisposable, - contentChangeDisposable, - ]; - - // 초기 validation - validateCode(model, model.getVersionId()); + // model이 있는 경우 포맷터만 저장 + disposablesRef.current = [jsDisposable, tsDisposable]; } else { // model이 없는 경우 포맷터만 저장 disposablesRef.current = [jsDisposable, tsDisposable]; @@ -273,9 +259,6 @@ export const CodeEditor: React.FC = ({ // Cleanup: unmount 시 포맷터 등록 해제 useEffect(() => { return () => { - if (debounceTimeoutRef.current) { - clearTimeout(debounceTimeoutRef.current); - } // 모든 disposable 해제 disposablesRef.current.forEach((disposable) => { disposable.dispose(); diff --git a/crates/node-runtime/Cargo.toml b/crates/node-runtime/Cargo.toml new file mode 100644 index 0000000..bd73f81 --- /dev/null +++ b/crates/node-runtime/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "node-runtime" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true +description = "Node.js 기반 JavaScript 런타임" + +[dependencies] +# Workspace dependencies +anyhow.workspace = true +tokio.workspace = true +tracing.workspace = true + +[dev-dependencies] +tokio.workspace = true + diff --git a/crates/node-runtime/src/lib.rs b/crates/node-runtime/src/lib.rs new file mode 100644 index 0000000..465b62a --- /dev/null +++ b/crates/node-runtime/src/lib.rs @@ -0,0 +1,504 @@ +use anyhow::{Context, Result}; +use std::path::{Path, PathBuf}; +use std::process::Stdio; +use tokio::io::{AsyncReadExt, BufReader}; +use tokio::process::Command; + +/// JavaScript 실행 결과를 저장하는 구조체 +#[derive(Debug, Clone)] +pub struct ExecutionOutput { + pub stdout: String, + pub stderr: String, +} + +impl ExecutionOutput { + pub fn new() -> Self { + Self { + stdout: String::new(), + stderr: String::new(), + } + } + + pub fn get_output(&self) -> String { + let mut output = Vec::new(); + + if !self.stdout.is_empty() { + output.push(self.stdout.clone()); + } + + if !self.stderr.is_empty() { + output.push(format!("[ERROR] {}", self.stderr)); + } + + output.join("\n") + } +} + +/// JavaScript 실행기 (Node.js 기반) +pub struct NodeExecutor { + node_path: PathBuf, +} + +impl NodeExecutor { + /// 새로운 NodeExecutor 인스턴스 생성 + pub fn new() -> Result { + let node_path = Self::find_node_binary().map_err(|e| { + tracing::error!("Node.js 바이너리를 찾을 수 없습니다: {}", e); + e + })?; + tracing::info!("NodeExecutor 초기화 완료: {}", node_path.display()); + Ok(Self { node_path }) + } + + /// OS별 Node.js 바이너리 경로 찾기 + fn find_node_binary() -> Result { + let (os_name, binary_name) = if cfg!(target_os = "windows") { + ("win-arm64", "node.exe") + } else if cfg!(target_os = "macos") { + if cfg!(target_arch = "aarch64") { + ("darwin-arm64", "node") + } else { + ("darwin-x64", "node") + } + } else if cfg!(target_os = "linux") { + if cfg!(target_arch = "aarch64") { + ("linux-arm64", "node") + } else { + ("linux-x64", "node") + } + } else { + anyhow::bail!("지원하지 않는 운영체제입니다: {}", std::env::consts::OS); + }; + + // 1. 개발 모드: src-tauri/resources/ 폴더에서 찾기 + // CARGO_MANIFEST_DIR에서 src-tauri로 이동 (crates/node-runtime -> 프로젝트 루트 -> apps/executeJS/src-tauri) + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let crate_root = Path::new(manifest_dir); + // crates/node-runtime -> 프로젝트 루트 -> apps/executeJS/src-tauri + let src_tauri_dir = crate_root + .parent() + .and_then(|p| p.parent()) + .map(|p| p.join("apps").join("executeJS").join("src-tauri")); + + if let Some(ref tauri_dir) = src_tauri_dir { + let resources_node_dir = tauri_dir + .join("resources") + .join("node-runtime") + .join(format!("node-v24.12.0-{}", os_name)); + let resources_node_path = resources_node_dir.join(binary_name); + + if resources_node_path.exists() { + tracing::debug!( + "개발 모드: Node.js 바이너리 경로: {}", + resources_node_path.display() + ); + return Self::set_permissions_if_needed(resources_node_path); + } + } + + // 2. 프로덕션 모드: 실행 파일 위치 기준으로 리소스 찾기 + // Tauri 앱의 경우 실행 파일과 같은 디렉토리나 리소스 디렉토리에서 찾기 + if let Ok(exe_path) = std::env::current_exe() { + eprintln!("[NodeExecutor] 실행 파일 경로: {}", exe_path.display()); + + // macOS .app 번들 구조: .app/Contents/MacOS/executeJS -> .app/Contents/Resources/ + #[cfg(target_os = "macos")] + { + // .app/Contents/Resources/ 경로 확인 + if let Some(macos_dir) = exe_path.parent() { + eprintln!("[NodeExecutor] MacOS 디렉토리: {}", macos_dir.display()); + + // MacOS 디렉토리에서 Contents로 이동 + if macos_dir.ends_with("MacOS") + || macos_dir.file_name().and_then(|n| n.to_str()) == Some("MacOS") + { + if let Some(contents_dir) = macos_dir.parent() { + eprintln!( + "[NodeExecutor] Contents 디렉토리: {}", + contents_dir.display() + ); + let resources_dir = contents_dir.join("Resources"); + eprintln!( + "[NodeExecutor] Resources 디렉토리 확인: {}", + resources_dir.display() + ); + + // Tauri가 리소스를 포함할 때의 경로 구조 확인 + // tauri.conf.json 설정: "resources/node-runtime/": "node-runtime/" + // 따라서 Resources/node-runtime/... 경로에 있음 + + // 1. node-runtime/node-v24.12.0-*/node (우선 확인 - tauri.conf.json 설정에 따라) + let resource_path = resources_dir + .join("node-runtime") + .join(format!("node-v24.12.0-{}", os_name)) + .join(binary_name); + eprintln!( + "[NodeExecutor] 경로 1 확인 (우선): {}", + resource_path.display() + ); + if resource_path.exists() { + eprintln!("[NodeExecutor] ✅ 경로 1에서 발견!"); + return Self::set_permissions_if_needed(resource_path); + } + + // 2. resources/node-runtime/node-v24.12.0-*/node (다른 구조) + let resource_path2 = resources_dir + .join("resources") + .join("node-runtime") + .join(format!("node-v24.12.0-{}", os_name)) + .join(binary_name); + eprintln!("[NodeExecutor] 경로 2 확인: {}", resource_path2.display()); + if resource_path2.exists() { + eprintln!("[NodeExecutor] ✅ 경로 2에서 발견!"); + return Self::set_permissions_if_needed(resource_path2); + } + + // 3. _up_/_up_/_up_/resources/node-runtime/... (이전 설정 호환성) + let tauri_resource_path = resources_dir + .join("_up_") + .join("_up_") + .join("_up_") + .join("resources") + .join("node-runtime") + .join(format!("node-v24.12.0-{}", os_name)) + .join(binary_name); + eprintln!( + "[NodeExecutor] 경로 3 확인 (이전 호환): {}", + tauri_resource_path.display() + ); + if tauri_resource_path.exists() { + eprintln!("[NodeExecutor] ✅ 경로 3에서 발견!"); + return Self::set_permissions_if_needed(tauri_resource_path); + } + + // Resources 디렉토리 전체 구조 확인 (디버깅용) + eprintln!("[NodeExecutor] Resources 디렉토리 전체 구조:"); + if let Ok(entries) = std::fs::read_dir(&resources_dir) { + for entry in entries.flatten() { + let path = entry.path(); + if path.is_dir() { + eprintln!(" [DIR] {}", path.display()); + // 하위 디렉토리도 확인 + if let Ok(sub_entries) = std::fs::read_dir(&path) { + for sub_entry in sub_entries.flatten() { + eprintln!(" - {}", sub_entry.path().display()); + } + } + } else { + eprintln!(" [FILE] {}", path.display()); + } + } + } + + // 4. 직접 Resources에 있는 경우 + let direct_resource_path = resources_dir.join(binary_name); + eprintln!( + "[NodeExecutor] 경로 4 확인: {}", + direct_resource_path.display() + ); + if direct_resource_path.exists() { + eprintln!("[NodeExecutor] ✅ 경로 4에서 발견!"); + return Self::set_permissions_if_needed(direct_resource_path); + } + + // Resources 디렉토리 내용 확인 (디버깅용) + if let Ok(entries) = std::fs::read_dir(&resources_dir) { + eprintln!("[NodeExecutor] Resources 디렉토리 내용:"); + for entry in entries.flatten() { + eprintln!(" - {}", entry.path().display()); + } + } + } + } + } + } + + // 실행 파일의 부모 디렉토리들에서 resources 폴더 찾기 + let mut search_path = exe_path.parent(); + for depth in 0..10 { + if let Some(path) = search_path { + // 일반 resources 폴더 + let resource_path = path + .join("resources") + .join("node-runtime") + .join(format!("node-v24.12.0-{}", os_name)) + .join(binary_name); + if resource_path.exists() { + tracing::info!( + "프로덕션 모드 (depth {}): Node.js 바이너리 경로: {}", + depth, + resource_path.display() + ); + return Self::set_permissions_if_needed(resource_path); + } + + // 리소스가 직접 있는 경우 (폴더 구조 없이) + let direct_resource_path = path + .join("node-runtime") + .join(format!("node-v24.12.0-{}", os_name)) + .join(binary_name); + if direct_resource_path.exists() { + tracing::info!( + "프로덕션 모드 (직접, depth {}): Node.js 바이너리 경로: {}", + depth, + direct_resource_path.display() + ); + return Self::set_permissions_if_needed(direct_resource_path); + } + + // Windows/Linux: 실행 파일과 같은 디렉토리 + let same_dir_path = path.join(binary_name); + if same_dir_path.exists() && path != exe_path.parent().unwrap() { + // 실행 파일과 같은 디렉토리가 아닌 경우만 (이미 확인했으므로) + // 이건 실제로는 필요 없을 수 있음 + } + + search_path = path.parent(); + } else { + break; + } + } + } + + // 에러 메시지용 경로 생성 + let error_path = if let Some(ref tauri_dir) = src_tauri_dir { + tauri_dir + .join("resources") + .join("node-runtime") + .join(format!("node-v24.12.0-{}", os_name)) + .join(binary_name) + } else { + PathBuf::from("apps/executeJS/src-tauri/resources/node-runtime/...") + }; + + // 디버깅을 위한 상세 정보 + let exe_info = std::env::current_exe() + .map(|p| format!("{}", p.display())) + .unwrap_or_else(|_| "알 수 없음".to_string()); + + anyhow::bail!( + "Node.js 바이너리를 찾을 수 없습니다.\n\ + - 개발 모드 경로: {}\n\ + - 실행 파일 경로: {}\n\ + - OS: {}, Arch: {}\n\ + - 바이너리 이름: {}\n\ + src-tauri/resources/node-runtime/ 폴더에 Node.js 바이너리가 있는지 확인하세요.", + error_path.display(), + exe_info, + std::env::consts::OS, + std::env::consts::ARCH, + binary_name + ); + } + + /// 실행 권한 설정 (필요한 경우) + fn set_permissions_if_needed(node_path: PathBuf) -> Result { + // 실행 권한 확인 (Unix 계열) - 이미 실행 가능한 경우 스킵하여 파일 변경 방지 + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let metadata = std::fs::metadata(&node_path).with_context(|| { + format!( + "파일 메타데이터를 읽을 수 없습니다: {}", + node_path.display() + ) + })?; + let perms = metadata.permissions(); + // 이미 실행 권한이 있는 경우 스킵 (파일 변경 방지) + if perms.mode() & 0o111 == 0 { + // 실행 권한이 없는 경우에만 설정 + let mut new_perms = perms.clone(); + new_perms.set_mode(0o755); + std::fs::set_permissions(&node_path, new_perms).with_context(|| { + format!("실행 권한을 설정할 수 없습니다: {}", node_path.display()) + })?; + } + } + + Ok(node_path) + } + + /// JavaScript 코드 실행 + pub async fn execute_script(&self, _filename: &str, code: &str) -> Result { + tracing::debug!("Node.js 코드 실행 시작, 코드 길이: {} bytes", code.len()); + + // 임시 디렉토리를 working directory로 설정하여 프로젝트 폴더 변경 방지 + let temp_dir = std::env::temp_dir(); + + // Node.js subprocess 실행 (stdin으로 코드 전달) + let mut child = Command::new(&self.node_path) + .current_dir(&temp_dir) // 임시 디렉토리에서 실행하여 프로젝트 폴더 변경 방지 + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .with_context(|| { + format!( + "Node.js 프로세스를 시작할 수 없습니다: {}", + self.node_path.display() + ) + })?; + + // stdin에 코드 쓰기 + let mut stdin = child.stdin.take().expect("stdin이 설정되지 않았습니다"); + use tokio::io::AsyncWriteExt; + stdin + .write_all(code.as_bytes()) + .await + .context("stdin에 코드 쓰기 실패")?; + drop(stdin); // stdin 닫기 + + // stdout와 stderr를 비동기로 읽기 + let stdout = child.stdout.take().expect("stdout가 설정되지 않았습니다"); + let stderr = child.stderr.take().expect("stderr가 설정되지 않았습니다"); + + let mut stdout_reader = BufReader::new(stdout); + let mut stderr_reader = BufReader::new(stderr); + + let mut stdout_buf = String::new(); + let mut stderr_buf = String::new(); + + // stdout와 stderr를 동시에 읽기 + let (stdout_result, stderr_result) = tokio::join!( + stdout_reader.read_to_string(&mut stdout_buf), + stderr_reader.read_to_string(&mut stderr_buf) + ); + + stdout_result.context("stdout 읽기 실패")?; + stderr_result.context("stderr 읽기 실패")?; + + // 프로세스 종료 대기 + let status = child.wait().await.context("프로세스 종료 대기 실패")?; + + // 출력 버퍼 생성 + let mut output = ExecutionOutput::new(); + output.stdout = stdout_buf.trim().to_string(); + output.stderr = stderr_buf.trim().to_string(); + + // 프로세스가 실패한 경우 (0이 아닌 종료 코드) + if !status.success() { + let error_msg = if !output.stderr.is_empty() { + output.stderr.clone() + } else { + format!( + "프로세스가 종료 코드 {}로 종료되었습니다", + status.code().unwrap_or(-1) + ) + }; + return Err(anyhow::anyhow!("{}", error_msg)); + } + + let result_text = output.get_output(); + + if result_text.is_empty() { + Ok("코드가 실행되었습니다.".to_string()) + } else { + Ok(result_text) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Mutex; + + // 테스트 간 격리를 위한 락 + static TEST_LOCK: Mutex<()> = Mutex::new(()); + + #[tokio::test] + async fn test_console_log() { + let _lock = TEST_LOCK.lock().unwrap(); + let executor = NodeExecutor::new().unwrap(); + let result = executor + .execute_script("test.js", "console.log('Hello World');") + .await; + assert!(result.is_ok()); + let output = result.unwrap(); + println!("실제 출력: '{}'", output); + assert!(output.contains("Hello World")); + } + + #[tokio::test] + async fn test_variable_assignment() { + let _lock = TEST_LOCK.lock().unwrap(); + let executor = NodeExecutor::new().unwrap(); + let result = executor + .execute_script("test.js", "let a = 5; console.log(a);") + .await; + assert!(result.is_ok()); + let output = result.unwrap(); + println!("실제 출력: '{}'", output); + assert!(output.contains("5")); + } + + #[tokio::test] + async fn test_calculation() { + let _lock = TEST_LOCK.lock().unwrap(); + let executor = NodeExecutor::new().unwrap(); + let result = executor + .execute_script("test.js", "let a = 1; let b = 2; console.log(a + b);") + .await; + assert!(result.is_ok()); + let output = result.unwrap(); + println!("실제 출력: '{}'", output); + assert!(output.contains("3")); + } + + #[tokio::test] + async fn test_syntax_error() { + let _lock = TEST_LOCK.lock().unwrap(); + let executor = NodeExecutor::new().unwrap(); + let result = executor.execute_script("test.js", "alert('adf'(;").await; + // 문법 오류는 실행 실패를 반환해야 함 + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_multiple_statements() { + let _lock = TEST_LOCK.lock().unwrap(); + let executor = NodeExecutor::new().unwrap(); + let result = executor + .execute_script( + "test.js", + "let x = 5; let y = 3; console.log('result:', x + y);", + ) + .await; + assert!(result.is_ok()); + let output = result.unwrap(); + println!("실제 출력: '{}'", output); + assert!(output.contains("result: 8")); + } + + #[tokio::test] + async fn test_multiple_console_logs() { + let _lock = TEST_LOCK.lock().unwrap(); + let executor = NodeExecutor::new().unwrap(); + let result = executor + .execute_script( + "test.js", + "console.log('First'); console.log('Second'); console.log('Third');", + ) + .await; + assert!(result.is_ok()); + let output = result.unwrap(); + println!("실제 출력: '{}'", output); + assert!(output.contains("First")); + assert!(output.contains("Second")); + assert!(output.contains("Third")); + } + + #[tokio::test] + async fn test_object_logging() { + let _lock = TEST_LOCK.lock().unwrap(); + let executor = NodeExecutor::new().unwrap(); + let result = executor + .execute_script("test.js", "console.log({ name: 'Test', value: 42 });") + .await; + assert!(result.is_ok()); + let output = result.unwrap(); + println!("실제 출력: '{}'", output); + // Node.js는 객체를 자동으로 직렬화하여 출력 + assert!(output.contains("name") || output.contains("Test")); + } +} diff --git a/package.json b/package.json index b293e81..853e857 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,9 @@ "docs:build": "pnpm --filter @executeJS/docs build", "docs:preview": "pnpm --filter @executeJS/docs preview", "clean": "pnpm -r clean && cargo clean", - "type-check": "pnpm -r type-check" + "type-check": "pnpm -r type-check", + "download-node": "node scripts/download-node-binaries.js", + "postinstall": "pnpm download-node" }, "devDependencies": { "@types/node": "latest", diff --git a/scripts/download-node-binaries.js b/scripts/download-node-binaries.js new file mode 100755 index 0000000..293b430 --- /dev/null +++ b/scripts/download-node-binaries.js @@ -0,0 +1,185 @@ +#!/usr/bin/env node + +const https = require('https'); +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); +const { createWriteStream } = require('fs'); + +const NODE_VERSION = 'v24.12.0'; +const BASE_URL = `https://nodejs.org/dist/${NODE_VERSION}/`; + +// OS 및 아키텍처 매핑 +const getPlatformInfo = () => { + const platform = process.platform; + const arch = process.arch; + + if (platform === 'darwin') { + return { + os: 'darwin', + arch: arch === 'arm64' ? 'arm64' : 'x64', + extension: 'tar.xz', // 더 작은 파일 크기 + binaryName: 'node', + }; + } else if (platform === 'win32') { + return { + os: 'win', + arch: arch === 'arm64' ? 'arm64' : 'x64', + extension: 'zip', + binaryName: 'node.exe', + }; + } else { + throw new Error(`Unsupported platform: ${platform}. Only macOS and Windows are supported.`); + } +}; + +// 파일 다운로드 +const downloadFile = async (url, destPath) => { + return new Promise((resolve, reject) => { + console.log(`다운로드 중: ${url}`); + const file = createWriteStream(destPath); + + https + .get(url, (response) => { + if (response.statusCode === 302 || response.statusCode === 301) { + // 리다이렉트 처리 + return downloadFile(response.headers.location, destPath).then(resolve).catch(reject); + } + + if (response.statusCode !== 200) { + reject(new Error(`다운로드 실패: ${response.statusCode}`)); + return; + } + + const totalSize = parseInt(response.headers['content-length'], 10); + let downloadedSize = 0; + + response.on('data', (chunk) => { + downloadedSize += chunk.length; + const percent = totalSize ? ((downloadedSize / totalSize) * 100).toFixed(1) : '0.0'; + const downloadedMB = (downloadedSize / 1024 / 1024).toFixed(2); + const totalMB = totalSize ? (totalSize / 1024 / 1024).toFixed(2) : '?'; + process.stdout.write(`\r진행률: ${percent}% (${downloadedMB} MB / ${totalMB} MB)`); + }); + + response.pipe(file); + + file.on('finish', () => { + file.close(); + console.log('\n다운로드 완료!'); + resolve(); + }); + + file.on('error', (err) => { + fs.unlink(destPath, () => {}); + reject(err); + }); + }) + .on('error', (err) => { + reject(err); + }); + }); +}; + +// 압축 해제 +const extractArchive = async (archivePath, extractDir) => { + const ext = path.extname(archivePath); + const platform = process.platform; + + console.log(`압축 해제 중: ${archivePath}`); + + if (ext === '.zip') { + // Windows: unzip 사용 + try { + execSync(`unzip -q "${archivePath}" -d "${extractDir}"`, { stdio: 'inherit' }); + } catch (error) { + // unzip이 없으면 PowerShell 사용 + execSync(`powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${extractDir}' -Force"`, { + stdio: 'inherit', + }); + } + } else if (ext === '.xz' || archivePath.endsWith('.tar.xz')) { + // tar.xz 압축 해제 + execSync(`tar -xJf "${archivePath}" -C "${extractDir}"`, { stdio: 'inherit' }); + } else if (ext === '.gz' || archivePath.endsWith('.tar.gz')) { + // tar.gz 압축 해제 + execSync(`tar -xzf "${archivePath}" -C "${extractDir}"`, { stdio: 'inherit' }); + } + + console.log('압축 해제 완료!'); +}; + +// 바이너리 복사 +const copyBinary = async (platformInfo, extractDir) => { + const { os, arch, binaryName } = platformInfo; + const nodeDir = `node-${NODE_VERSION}-${os}-${arch}`; + // Windows는 루트에, macOS/Linux는 bin/ 디렉토리에 있습니다 + const sourcePath = + os === 'win' ? path.join(extractDir, nodeDir, binaryName) : path.join(extractDir, nodeDir, 'bin', binaryName); + // src-tauri/resources/에만 복사 (개발/빌드 모두 동일 경로 사용) + const targetDirs = [ + path.join(__dirname, '..', 'apps', 'executeJS', 'src-tauri', 'resources', 'node-runtime', nodeDir), + ]; + + // 소스 파일 확인 + if (!fs.existsSync(sourcePath)) { + throw new Error(`바이너리 파일을 찾을 수 없습니다: ${sourcePath}`); + } + + // 각 타겟 디렉토리에 복사 + for (const targetDir of targetDirs) { + fs.mkdirSync(targetDir, { recursive: true }); + const targetPath = path.join(targetDir, binaryName); + fs.copyFileSync(sourcePath, targetPath); + + // Unix 시스템에서 실행 권한 설정 + if (process.platform !== 'win32') { + fs.chmodSync(targetPath, 0o755); + } + + console.log(`복사 완료: ${targetPath}`); + } +}; + +// 메인 함수 +const main = async () => { + try { + const platformInfo = getPlatformInfo(); + const { os, arch, extension } = platformInfo; + + const fileName = `node-${NODE_VERSION}-${os}-${arch}.${extension}`; + const downloadUrl = `${BASE_URL}${fileName}`; + + console.log(`Node.js ${NODE_VERSION} 바이너리 다운로드 시작`); + console.log(`플랫폼: ${os}-${arch}`); + console.log(`파일: ${fileName}`); + console.log(`URL: ${downloadUrl}\n`); + + // 임시 디렉토리 생성 + const tempDir = path.join(__dirname, '..', '.temp-node-download'); + fs.mkdirSync(tempDir, { recursive: true }); + const archivePath = path.join(tempDir, fileName); + const extractDir = path.join(tempDir, 'extracted'); + + // 다운로드 + await downloadFile(downloadUrl, archivePath); + + // 압축 해제 + fs.mkdirSync(extractDir, { recursive: true }); + await extractArchive(archivePath, extractDir); + + // 바이너리 복사 + await copyBinary(platformInfo, extractDir); + + // 임시 파일 정리 + console.log('\n임시 파일 정리 중...'); + fs.rmSync(tempDir, { recursive: true, force: true }); + + console.log('\n✅ 모든 작업 완료!'); + } catch (error) { + console.error('\n❌ 오류 발생:', error.message); + process.exit(1); + } +}; + +main(); From 3fcc9c236501ca057057afb542c140a0ec53b3e0 Mon Sep 17 00:00:00 2001 From: ohah Date: Sat, 13 Dec 2025 03:24:46 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix(scripts):=20CI=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=A7=80=EC=9B=90=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=ED=94=8C=EB=9E=AB=ED=8F=BC=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub Actions의 Linux 환경에서 postinstall 스크립트 실행 시 에러가 발생하지 않도록 지원하지 않는 플랫폼에서 조용히 종료하도록 수정 --- scripts/download-node-binaries.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/download-node-binaries.js b/scripts/download-node-binaries.js index 293b430..9755d78 100755 --- a/scripts/download-node-binaries.js +++ b/scripts/download-node-binaries.js @@ -29,7 +29,9 @@ const getPlatformInfo = () => { binaryName: 'node.exe', }; } else { - throw new Error(`Unsupported platform: ${platform}. Only macOS and Windows are supported.`); + // CI 환경이거나 지원하지 않는 플랫폼인 경우 조용히 종료 + // GitHub Actions는 Linux에서 실행되지만 바이너리는 필요 없음 + return null; } }; @@ -145,6 +147,13 @@ const copyBinary = async (platformInfo, extractDir) => { const main = async () => { try { const platformInfo = getPlatformInfo(); + + // 지원하지 않는 플랫폼이거나 CI 환경인 경우 조용히 종료 + if (!platformInfo) { + console.log(`현재 플랫폼(${process.platform})에서는 Node.js 바이너리 다운로드가 필요하지 않습니다.`); + return; + } + const { os, arch, extension } = platformInfo; const fileName = `node-${NODE_VERSION}-${os}-${arch}.${extension}`; From aec8f3ecea7300e0bb97341f29cd86ee438f5fbe Mon Sep 17 00:00:00 2001 From: ohah Date: Sat, 13 Dec 2025 03:26:54 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20downloadFile=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=EC=9D=98=20=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EB=88=84=EC=88=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 리다이렉트 및 에러 발생 시 파일 스트림이 닫히지 않는 문제 해결 - cleanup 헬퍼 함수 추가하여 파일 스트림 안전하게 정리 - 모든 early return 경로에서 파일 스트림 닫기 및 임시 파일 삭제 보장 --- Cargo.lock | 760 +++++++++++++++++++++++++++++- scripts/download-node-binaries.js | 33 +- 2 files changed, 763 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2c1e6a..90aa45e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "adler2" version = "2.0.1" @@ -301,6 +307,12 @@ dependencies = [ "tower-service", ] +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "base64" version = "0.21.7" @@ -313,6 +325,59 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" +dependencies = [ + "simd-abstraction", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.108", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -328,6 +393,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block" version = "0.1.6" @@ -479,7 +556,7 @@ checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.27", "serde", "serde_json", "thiserror 2.0.17", @@ -511,6 +588,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfb" version = "0.7.3" @@ -558,6 +644,17 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading 0.8.9", +] + [[package]] name = "clipboard-win" version = "5.4.1" @@ -578,7 +675,7 @@ dependencies = [ "cocoa-foundation", "core-foundation 0.10.1", "core-graphics", - "foreign-types", + "foreign-types 0.5.0", "libc", "objc", ] @@ -631,6 +728,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "cooked-waker" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" + [[package]] name = "cookie" version = "0.18.1" @@ -695,7 +798,7 @@ dependencies = [ "bitflags 2.10.0", "core-foundation 0.10.1", "core-graphics-types", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -831,12 +934,113 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + [[package]] name = "data-url" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + +[[package]] +name = "deno-runtime" +version = "0.1.0" +dependencies = [ + "anyhow", + "deno_core", + "dirs 5.0.1", + "flate2", + "futures", + "reqwest", + "serde", + "serde_json", + "tar", + "tokio", + "tracing", +] + +[[package]] +name = "deno_core" +version = "0.323.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a781bcfe1b5211b8497f45bf5b3dba73036b8d5d1533c1f05d26ccf0afb25a78" +dependencies = [ + "anyhow", + "az", + "bincode", + "bit-set", + "bit-vec", + "bytes", + "cooked-waker", + "deno_core_icudata", + "deno_ops", + "deno_unsync", + "futures", + "indexmap 2.12.0", + "libc", + "memoffset", + "parking_lot", + "percent-encoding", + "pin-project", + "serde", + "serde_json", + "serde_v8", + "smallvec", + "sourcemap", + "static_assertions", + "tokio", + "url", + "v8", + "wasm_dep_analyzer", +] + +[[package]] +name = "deno_core_icudata" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695" + +[[package]] +name = "deno_ops" +version = "0.199.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24a1f3e22029a57d3094b32070b8328eac793920b5a022027d360f085e6b245" +dependencies = [ + "proc-macro-rules", + "proc-macro2", + "quote", + "stringcase", + "strum", + "strum_macros", + "syn 2.0.108", + "thiserror 1.0.69", +] + +[[package]] +name = "deno_unsync" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6742a724e8becb372a74c650a1aefb8924a5b8107f7d75b3848763ea24b27a87" +dependencies = [ + "futures-util", + "parking_lot", + "tokio", +] + [[package]] name = "deranged" version = "0.5.5" @@ -856,7 +1060,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.1", "syn 2.0.108", ] @@ -912,13 +1116,34 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys 0.4.1", +] + [[package]] name = "dirs" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ - "dirs-sys", + "dirs-sys 0.5.0", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.4.6", + "windows-sys 0.48.0", ] [[package]] @@ -929,7 +1154,7 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users", + "redox_users 0.5.2", "windows-sys 0.61.2", ] @@ -1048,7 +1273,7 @@ checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e" dependencies = [ "cc", "memchr", - "rustc_version", + "rustc_version 0.4.1", "toml 0.9.8", "vswhom", "winreg", @@ -1217,7 +1442,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ "memoffset", - "rustc_version", + "rustc_version 0.4.1", +] + +[[package]] +name = "filetime" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.60.2", ] [[package]] @@ -1239,7 +1476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] @@ -1248,6 +1485,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -1255,7 +1501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -1269,6 +1515,12 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -1284,6 +1536,22 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fslock" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -1710,6 +1978,15 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "gzip-header" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2" +dependencies = [ + "crc32fast", +] + [[package]] name = "h2" version = "0.3.27" @@ -1783,6 +2060,10 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hello-world" +version = "0.1.0" + [[package]] name = "hermit-abi" version = "0.5.2" @@ -1795,6 +2076,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "html5ever" version = "0.29.1" @@ -1956,6 +2246,22 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.7.0", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.17" @@ -2129,6 +2435,12 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "if_chain" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" + [[package]] name = "image" version = "0.25.8" @@ -2351,7 +2663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading", + "libloading 0.7.4", "once_cell", ] @@ -2371,6 +2683,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + [[package]] name = "libredox" version = "0.1.10" @@ -2379,6 +2701,7 @@ checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.10.0", "libc", + "redox_syscall", ] [[package]] @@ -2526,6 +2849,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -2578,6 +2910,23 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndk" version = "0.9.0" @@ -2686,12 +3035,32 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "rand 0.8.5", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -3014,6 +3383,50 @@ dependencies = [ "pathdiff", ] +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -3040,6 +3453,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "outref" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" + [[package]] name = "pango" version = "0.18.3" @@ -3094,6 +3513,12 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pathdiff" version = "0.2.3" @@ -3322,7 +3747,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] @@ -3335,7 +3760,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] @@ -3397,6 +3822,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.108", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -3456,6 +3891,29 @@ version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +[[package]] +name = "proc-macro-rules" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" +dependencies = [ + "proc-macro-rules-macros", + "proc-macro2", + "syn 2.0.108", +] + +[[package]] +name = "proc-macro-rules-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "207fffb0fe655d1d47f6af98cc2793405e85929bdbc420d685554ff07be27ac7" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "proc-macro2" version = "1.0.103" @@ -3557,7 +4015,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 2.1.1", "rustls", "socket2 0.6.1", "thiserror 2.0.17", @@ -3577,7 +4035,7 @@ dependencies = [ "lru-slab", "rand 0.9.2", "ring", - "rustc-hash", + "rustc-hash 2.1.1", "rustls", "rustls-pki-types", "slab", @@ -3616,6 +4074,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -3741,6 +4205,17 @@ dependencies = [ "bitflags 2.10.0", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -3820,10 +4295,12 @@ dependencies = [ "http-body-util", "hyper 1.7.0", "hyper-rustls", + "hyper-tls", "hyper-util", "js-sys", "log", "mime", + "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -3834,6 +4311,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.2", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-util", "tower 0.5.2", @@ -3872,19 +4350,34 @@ dependencies = [ "portable-atomic-util", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.27", ] [[package]] @@ -3969,6 +4462,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "schemars" version = "0.8.22" @@ -4026,6 +4528,29 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "selectors" version = "0.24.0" @@ -4044,6 +4569,15 @@ dependencies = [ "smallvec", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.27" @@ -4054,6 +4588,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.228" @@ -4113,6 +4653,7 @@ version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ + "indexmap 2.12.0", "itoa", "memchr", "ryu", @@ -4161,6 +4702,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_v8" +version = "0.232.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c9feae92f7293fcc1a32a86be1a399859c0637e55dad8991d5258c43f7ff4d2" +dependencies = [ + "num-bigint", + "serde", + "smallvec", + "thiserror 1.0.69", + "v8", +] + [[package]] name = "serde_with" version = "3.15.1" @@ -4259,6 +4813,15 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-abstraction" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" +dependencies = [ + "outref", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -4318,7 +4881,7 @@ dependencies = [ "bytemuck", "cfg_aliases", "core-graphics", - "foreign-types", + "foreign-types 0.5.0", "js-sys", "log", "objc2 0.5.2", @@ -4357,6 +4920,25 @@ dependencies = [ "system-deps", ] +[[package]] +name = "sourcemap" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "208d40b9e8cad9f93613778ea295ed8f3c2b1824217c6cfc7219d3f6f45b96d4" +dependencies = [ + "base64-simd", + "bitvec", + "data-encoding", + "debugid", + "if_chain", + "rustc-hash 1.1.0", + "rustc_version 0.2.3", + "serde", + "serde_json", + "unicode-id-start", + "url", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -4394,12 +4976,40 @@ dependencies = [ "quote", ] +[[package]] +name = "stringcase" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04028eeb851ed08af6aba5caa29f2d59a13ed168cee4d6bd753aeefcf1d636b0" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.108", +] + [[package]] name = "subtle" version = "2.6.1" @@ -4550,6 +5160,23 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "target-lexicon" version = "0.12.16" @@ -4565,7 +5192,7 @@ dependencies = [ "anyhow", "bytes", "cookie", - "dirs", + "dirs 6.0.0", "dunce", "embed_plist", "getrandom 0.3.4", @@ -4616,12 +5243,12 @@ checksum = "a924b6c50fe83193f0f8b14072afa7c25b7a72752a2a73d9549b463f5fe91a38" dependencies = [ "anyhow", "cargo_toml", - "dirs", + "dirs 6.0.0", "glob", "heck 0.5.0", "json-patch", "schemars 0.8.22", - "semver", + "semver 1.0.27", "serde", "serde_json", "tauri-utils", @@ -4644,7 +5271,7 @@ dependencies = [ "png 0.17.16", "proc-macro2", "quote", - "semver", + "semver 1.0.27", "serde", "serde_json", "sha2", @@ -4891,7 +5518,7 @@ dependencies = [ "quote", "regex", "schemars 0.8.22", - "semver", + "semver 1.0.27", "serde", "serde-untagged", "serde_json", @@ -5096,6 +5723,16 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" @@ -5450,7 +6087,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d5572781bee8e3f994d7467084e1b1fd7a93ce66bd480f8156ba89dee55a2b" dependencies = [ "crossbeam-channel", - "dirs", + "dirs 6.0.0", "libappindicator", "muda", "objc2 0.6.3", @@ -5547,6 +6184,12 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicode-id-start" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" + [[package]] name = "unicode-ident" version = "1.0.20" @@ -5613,12 +6256,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "v8" +version = "130.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a511192602f7b435b0a241c1947aa743eb7717f20a9195f4b5e8ed1952e01db1" +dependencies = [ + "bindgen", + "bitflags 2.10.0", + "fslock", + "gzip-header", + "home", + "miniz_oxide 0.7.4", + "once_cell", + "paste", + "which", +] + [[package]] name = "valuable" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.2.0" @@ -5776,6 +6442,15 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm_dep_analyzer" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f270206a91783fd90625c8bb0d8fbd459d0b1d1bf209b656f713f01ae7c04b8" +dependencies = [ + "thiserror 1.0.69", +] + [[package]] name = "wayland-backend" version = "0.3.11" @@ -5961,6 +6636,18 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix 0.38.44", + "winsafe", +] + [[package]] name = "winapi" version = "0.3.9" @@ -6500,6 +7187,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "wit-bindgen" version = "0.46.0" @@ -6541,7 +7234,7 @@ dependencies = [ "block2 0.6.2", "cookie", "crossbeam-channel", - "dirs", + "dirs 6.0.0", "dpi", "dunce", "gdkx11", @@ -6577,6 +7270,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11" version = "2.21.0" @@ -6615,6 +7317,16 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix 1.1.2", +] + [[package]] name = "yoke" version = "0.8.0" diff --git a/scripts/download-node-binaries.js b/scripts/download-node-binaries.js index 9755d78..c620b8c 100755 --- a/scripts/download-node-binaries.js +++ b/scripts/download-node-binaries.js @@ -41,15 +41,30 @@ const downloadFile = async (url, destPath) => { console.log(`다운로드 중: ${url}`); const file = createWriteStream(destPath); + // 파일 스트림 정리 헬퍼 함수 + const cleanup = (callback) => { + file.close(() => { + fs.unlink(destPath, () => { + callback(); + }); + }); + }; + https .get(url, (response) => { if (response.statusCode === 302 || response.statusCode === 301) { - // 리다이렉트 처리 - return downloadFile(response.headers.location, destPath).then(resolve).catch(reject); + // 리다이렉트 처리 - 파일 스트림 정리 후 재귀 호출 + cleanup(() => { + downloadFile(response.headers.location, destPath).then(resolve).catch(reject); + }); + return; } if (response.statusCode !== 200) { - reject(new Error(`다운로드 실패: ${response.statusCode}`)); + // 비-200 상태 코드 - 파일 스트림 정리 후 reject + cleanup(() => { + reject(new Error(`다운로드 실패: ${response.statusCode}`)); + }); return; } @@ -73,12 +88,18 @@ const downloadFile = async (url, destPath) => { }); file.on('error', (err) => { - fs.unlink(destPath, () => {}); - reject(err); + file.close(() => { + fs.unlink(destPath, () => { + reject(err); + }); + }); }); }) .on('error', (err) => { - reject(err); + // HTTP 요청 에러 - 파일 스트림 정리 후 reject + cleanup(() => { + reject(err); + }); }); }); };