titanpl 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -6
- package/packages/cli/index.js +25 -11
- package/packages/cli/package.json +4 -4
- package/packages/cli/src/commands/build-ext.js +157 -0
- package/packages/cli/src/commands/build.js +12 -0
- package/packages/cli/src/commands/create.js +160 -0
- package/packages/cli/src/commands/init.js +5 -11
- package/packages/cli/src/commands/run-ext.js +104 -0
- package/{titanpl-sdk → packages/core-source}/LICENSE +1 -1
- package/packages/core-source/README.md +128 -0
- package/packages/core-source/V8_SERIALIZATION.md +125 -0
- package/packages/core-source/configure.js +50 -0
- package/packages/core-source/globals.d.ts +2238 -0
- package/packages/core-source/index.d.ts +515 -0
- package/packages/core-source/index.js +639 -0
- package/packages/core-source/jsconfig.json +12 -0
- package/packages/core-source/mkctx.config.json +7 -0
- package/packages/core-source/native/Cargo.lock +1559 -0
- package/packages/core-source/native/Cargo.toml +30 -0
- package/packages/core-source/native/src/crypto_impl.rs +139 -0
- package/packages/core-source/native/src/lib.rs +702 -0
- package/packages/core-source/native/src/storage_impl.rs +73 -0
- package/packages/core-source/native/src/v8_impl.rs +93 -0
- package/packages/core-source/package-lock.json +1464 -0
- package/packages/core-source/package.json +53 -0
- package/packages/core-source/tests/buffer.test.js +78 -0
- package/packages/core-source/tests/cookies.test.js +117 -0
- package/packages/core-source/tests/crypto.test.js +142 -0
- package/packages/core-source/tests/fs.test.js +176 -0
- package/packages/core-source/tests/ls.test.js +149 -0
- package/packages/core-source/tests/net.test.js +84 -0
- package/packages/core-source/tests/os.test.js +81 -0
- package/packages/core-source/tests/path.test.js +102 -0
- package/packages/core-source/tests/response.test.js +146 -0
- package/packages/core-source/tests/session.test.js +110 -0
- package/packages/core-source/tests/setup.js +325 -0
- package/packages/core-source/tests/time.test.js +57 -0
- package/packages/core-source/tests/url.test.js +82 -0
- package/packages/core-source/titan-ext.d.ts +2 -0
- package/packages/core-source/titan.json +9 -0
- package/packages/core-source/vitest.config.js +8 -0
- package/packages/engine-darwin-arm64/README.md +0 -2
- package/packages/engine-darwin-arm64/package.json +1 -1
- package/packages/engine-linux-x64/README.md +0 -2
- package/packages/engine-linux-x64/package.json +1 -1
- package/packages/engine-win32-x64/README.md +0 -1
- package/packages/engine-win32-x64/bin/titan-server.exe +0 -0
- package/packages/engine-win32-x64/package.json +1 -1
- package/packages/native/README.md +0 -1
- package/packages/native/index.d.ts +25 -4
- package/packages/native/index.js +7 -0
- package/packages/native/package.json +2 -2
- package/packages/native/t.native.d.ts +167 -2
- package/packages/packet/index.js +103 -94
- package/packages/packet/package.json +1 -1
- package/packages/route/package.json +1 -1
- package/packages/sdk/index.js +2 -0
- package/packages/sdk/package.json +18 -0
- package/packages/sdk/test/index.js +120 -0
- package/templates/common/_tanfig.json +19 -13
- package/templates/extension/index.d.ts +26 -22
- package/templates/extension/index.js +15 -15
- package/templates/extension/native/Cargo.toml +5 -3
- package/templates/extension/native/src/lib.rs +2 -3
- package/templates/extension/package.json +10 -20
- package/templates/extension/titan.json +5 -16
- package/templates/extension/utils/registerExtension.js +44 -0
- package/templates/js/package.json +8 -8
- package/templates/rust-js/package.json +5 -5
- package/templates/rust-ts/package.json +5 -5
- package/templates/ts/package.json +8 -8
- package/packages/packet/node_modules/typescript/LICENSE.txt +0 -55
- package/packages/packet/node_modules/typescript/README.md +0 -50
- package/packages/packet/node_modules/typescript/SECURITY.md +0 -41
- package/packages/packet/node_modules/typescript/ThirdPartyNoticeText.txt +0 -193
- package/packages/packet/node_modules/typescript/bin/tsc +0 -2
- package/packages/packet/node_modules/typescript/bin/tsserver +0 -2
- package/packages/packet/node_modules/typescript/lib/_tsc.js +0 -133818
- package/packages/packet/node_modules/typescript/lib/_tsserver.js +0 -659
- package/packages/packet/node_modules/typescript/lib/_typingsInstaller.js +0 -222
- package/packages/packet/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/de/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/es/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/it/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/lib.d.ts +0 -22
- package/packages/packet/node_modules/typescript/lib/lib.decorators.d.ts +0 -384
- package/packages/packet/node_modules/typescript/lib/lib.decorators.legacy.d.ts +0 -22
- package/packages/packet/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +0 -41
- package/packages/packet/node_modules/typescript/lib/lib.dom.d.ts +0 -39429
- package/packages/packet/node_modules/typescript/lib/lib.dom.iterable.d.ts +0 -571
- package/packages/packet/node_modules/typescript/lib/lib.es2015.collection.d.ts +0 -147
- package/packages/packet/node_modules/typescript/lib/lib.es2015.core.d.ts +0 -597
- package/packages/packet/node_modules/typescript/lib/lib.es2015.d.ts +0 -28
- package/packages/packet/node_modules/typescript/lib/lib.es2015.generator.d.ts +0 -77
- package/packages/packet/node_modules/typescript/lib/lib.es2015.iterable.d.ts +0 -605
- package/packages/packet/node_modules/typescript/lib/lib.es2015.promise.d.ts +0 -81
- package/packages/packet/node_modules/typescript/lib/lib.es2015.proxy.d.ts +0 -128
- package/packages/packet/node_modules/typescript/lib/lib.es2015.reflect.d.ts +0 -144
- package/packages/packet/node_modules/typescript/lib/lib.es2015.symbol.d.ts +0 -46
- package/packages/packet/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +0 -326
- package/packages/packet/node_modules/typescript/lib/lib.es2016.array.include.d.ts +0 -116
- package/packages/packet/node_modules/typescript/lib/lib.es2016.d.ts +0 -21
- package/packages/packet/node_modules/typescript/lib/lib.es2016.full.d.ts +0 -23
- package/packages/packet/node_modules/typescript/lib/lib.es2016.intl.d.ts +0 -31
- package/packages/packet/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +0 -21
- package/packages/packet/node_modules/typescript/lib/lib.es2017.d.ts +0 -26
- package/packages/packet/node_modules/typescript/lib/lib.es2017.date.d.ts +0 -31
- package/packages/packet/node_modules/typescript/lib/lib.es2017.full.d.ts +0 -23
- package/packages/packet/node_modules/typescript/lib/lib.es2017.intl.d.ts +0 -44
- package/packages/packet/node_modules/typescript/lib/lib.es2017.object.d.ts +0 -49
- package/packages/packet/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +0 -135
- package/packages/packet/node_modules/typescript/lib/lib.es2017.string.d.ts +0 -45
- package/packages/packet/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +0 -53
- package/packages/packet/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +0 -77
- package/packages/packet/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +0 -53
- package/packages/packet/node_modules/typescript/lib/lib.es2018.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2018.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2018.intl.d.ts +0 -83
- package/packages/packet/node_modules/typescript/lib/lib.es2018.promise.d.ts +0 -30
- package/packages/packet/node_modules/typescript/lib/lib.es2018.regexp.d.ts +0 -37
- package/packages/packet/node_modules/typescript/lib/lib.es2019.array.d.ts +0 -79
- package/packages/packet/node_modules/typescript/lib/lib.es2019.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2019.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2019.intl.d.ts +0 -23
- package/packages/packet/node_modules/typescript/lib/lib.es2019.object.d.ts +0 -33
- package/packages/packet/node_modules/typescript/lib/lib.es2019.string.d.ts +0 -37
- package/packages/packet/node_modules/typescript/lib/lib.es2019.symbol.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2020.bigint.d.ts +0 -765
- package/packages/packet/node_modules/typescript/lib/lib.es2020.d.ts +0 -27
- package/packages/packet/node_modules/typescript/lib/lib.es2020.date.d.ts +0 -42
- package/packages/packet/node_modules/typescript/lib/lib.es2020.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2020.intl.d.ts +0 -474
- package/packages/packet/node_modules/typescript/lib/lib.es2020.number.d.ts +0 -28
- package/packages/packet/node_modules/typescript/lib/lib.es2020.promise.d.ts +0 -47
- package/packages/packet/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +0 -99
- package/packages/packet/node_modules/typescript/lib/lib.es2020.string.d.ts +0 -44
- package/packages/packet/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +0 -41
- package/packages/packet/node_modules/typescript/lib/lib.es2021.d.ts +0 -23
- package/packages/packet/node_modules/typescript/lib/lib.es2021.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2021.intl.d.ts +0 -166
- package/packages/packet/node_modules/typescript/lib/lib.es2021.promise.d.ts +0 -48
- package/packages/packet/node_modules/typescript/lib/lib.es2021.string.d.ts +0 -33
- package/packages/packet/node_modules/typescript/lib/lib.es2021.weakref.d.ts +0 -78
- package/packages/packet/node_modules/typescript/lib/lib.es2022.array.d.ts +0 -121
- package/packages/packet/node_modules/typescript/lib/lib.es2022.d.ts +0 -25
- package/packages/packet/node_modules/typescript/lib/lib.es2022.error.d.ts +0 -75
- package/packages/packet/node_modules/typescript/lib/lib.es2022.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2022.intl.d.ts +0 -145
- package/packages/packet/node_modules/typescript/lib/lib.es2022.object.d.ts +0 -26
- package/packages/packet/node_modules/typescript/lib/lib.es2022.regexp.d.ts +0 -39
- package/packages/packet/node_modules/typescript/lib/lib.es2022.string.d.ts +0 -25
- package/packages/packet/node_modules/typescript/lib/lib.es2023.array.d.ts +0 -924
- package/packages/packet/node_modules/typescript/lib/lib.es2023.collection.d.ts +0 -21
- package/packages/packet/node_modules/typescript/lib/lib.es2023.d.ts +0 -22
- package/packages/packet/node_modules/typescript/lib/lib.es2023.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2023.intl.d.ts +0 -56
- package/packages/packet/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +0 -65
- package/packages/packet/node_modules/typescript/lib/lib.es2024.collection.d.ts +0 -29
- package/packages/packet/node_modules/typescript/lib/lib.es2024.d.ts +0 -26
- package/packages/packet/node_modules/typescript/lib/lib.es2024.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.es2024.object.d.ts +0 -29
- package/packages/packet/node_modules/typescript/lib/lib.es2024.promise.d.ts +0 -35
- package/packages/packet/node_modules/typescript/lib/lib.es2024.regexp.d.ts +0 -25
- package/packages/packet/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +0 -68
- package/packages/packet/node_modules/typescript/lib/lib.es2024.string.d.ts +0 -29
- package/packages/packet/node_modules/typescript/lib/lib.es5.d.ts +0 -4601
- package/packages/packet/node_modules/typescript/lib/lib.es6.d.ts +0 -23
- package/packages/packet/node_modules/typescript/lib/lib.esnext.array.d.ts +0 -35
- package/packages/packet/node_modules/typescript/lib/lib.esnext.collection.d.ts +0 -96
- package/packages/packet/node_modules/typescript/lib/lib.esnext.d.ts +0 -29
- package/packages/packet/node_modules/typescript/lib/lib.esnext.decorators.d.ts +0 -28
- package/packages/packet/node_modules/typescript/lib/lib.esnext.disposable.d.ts +0 -193
- package/packages/packet/node_modules/typescript/lib/lib.esnext.error.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.esnext.float16.d.ts +0 -445
- package/packages/packet/node_modules/typescript/lib/lib.esnext.full.d.ts +0 -24
- package/packages/packet/node_modules/typescript/lib/lib.esnext.intl.d.ts +0 -21
- package/packages/packet/node_modules/typescript/lib/lib.esnext.iterator.d.ts +0 -148
- package/packages/packet/node_modules/typescript/lib/lib.esnext.promise.d.ts +0 -34
- package/packages/packet/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +0 -25
- package/packages/packet/node_modules/typescript/lib/lib.scripthost.d.ts +0 -322
- package/packages/packet/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +0 -41
- package/packages/packet/node_modules/typescript/lib/lib.webworker.d.ts +0 -13150
- package/packages/packet/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +0 -23
- package/packages/packet/node_modules/typescript/lib/lib.webworker.iterable.d.ts +0 -340
- package/packages/packet/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/tsc.js +0 -8
- package/packages/packet/node_modules/typescript/lib/tsserver.js +0 -8
- package/packages/packet/node_modules/typescript/lib/tsserverlibrary.d.ts +0 -17
- package/packages/packet/node_modules/typescript/lib/tsserverlibrary.js +0 -21
- package/packages/packet/node_modules/typescript/lib/typesMap.json +0 -497
- package/packages/packet/node_modules/typescript/lib/typescript.d.ts +0 -11437
- package/packages/packet/node_modules/typescript/lib/typescript.js +0 -200276
- package/packages/packet/node_modules/typescript/lib/typingsInstaller.js +0 -8
- package/packages/packet/node_modules/typescript/lib/watchGuard.js +0 -53
- package/packages/packet/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +0 -2122
- package/packages/packet/node_modules/typescript/package.json +0 -120
- package/titanpl-sdk/README.md +0 -111
- package/titanpl-sdk/assets/titanpl-sdk.png +0 -0
- package/titanpl-sdk/bin/run.js +0 -274
- package/titanpl-sdk/index.js +0 -5
- package/titanpl-sdk/package-lock.json +0 -28
- package/titanpl-sdk/package.json +0 -40
- package/titanpl-sdk/templates/app/actions/hello.js +0 -5
- package/titanpl-sdk/templates/app/app.js +0 -7
- package/titanpl-sdk/templates/jsconfig.json +0 -19
- package/titanpl-sdk/templates/server/Cargo.toml +0 -52
- package/titanpl-sdk/templates/server/src/action_management.rs +0 -175
- package/titanpl-sdk/templates/server/src/errors.rs +0 -12
- package/titanpl-sdk/templates/server/src/extensions/builtin.rs +0 -1060
- package/titanpl-sdk/templates/server/src/extensions/external.rs +0 -338
- package/titanpl-sdk/templates/server/src/extensions/mod.rs +0 -580
- package/titanpl-sdk/templates/server/src/extensions/titan_core.js +0 -249
- package/titanpl-sdk/templates/server/src/fast_path.rs +0 -719
- package/titanpl-sdk/templates/server/src/main.rs +0 -607
- package/titanpl-sdk/templates/server/src/runtime.rs +0 -284
- package/titanpl-sdk/templates/server/src/utils.rs +0 -33
- package/titanpl-sdk/templates/titan/bundle.js +0 -259
- package/titanpl-sdk/templates/titan/dev.js +0 -390
- package/titanpl-sdk/templates/titan/error-box.js +0 -277
- package/titanpl-sdk/templates/titan/titan.js +0 -129
|
@@ -0,0 +1,702 @@
|
|
|
1
|
+
use std::ffi::{CStr, CString};
|
|
2
|
+
use std::os::raw::c_char;
|
|
3
|
+
use std::ptr;
|
|
4
|
+
use std::thread;
|
|
5
|
+
use std::time::Duration;
|
|
6
|
+
use base64::{Engine as _, engine::general_purpose};
|
|
7
|
+
|
|
8
|
+
// Force rebuild 2
|
|
9
|
+
mod storage_impl;
|
|
10
|
+
mod crypto_impl;
|
|
11
|
+
mod v8_impl;
|
|
12
|
+
|
|
13
|
+
// --- V8 Serialization ---
|
|
14
|
+
|
|
15
|
+
#[no_mangle]
|
|
16
|
+
pub extern "C" fn native_serialize(
|
|
17
|
+
scope: &mut v8::HandleScope,
|
|
18
|
+
args: v8::FunctionCallbackArguments,
|
|
19
|
+
retval: v8::ReturnValue,
|
|
20
|
+
) {
|
|
21
|
+
v8_impl::native_serialize(scope, args, retval)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#[no_mangle]
|
|
25
|
+
pub extern "C" fn native_deserialize(
|
|
26
|
+
scope: &mut v8::HandleScope,
|
|
27
|
+
args: v8::FunctionCallbackArguments,
|
|
28
|
+
retval: v8::ReturnValue,
|
|
29
|
+
) {
|
|
30
|
+
v8_impl::native_deserialize(scope, args, retval)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// --- Helper Functions ---
|
|
34
|
+
|
|
35
|
+
fn ptr_to_string(ptr: *const c_char) -> String {
|
|
36
|
+
if ptr.is_null() {
|
|
37
|
+
return String::new();
|
|
38
|
+
}
|
|
39
|
+
unsafe {
|
|
40
|
+
CStr::from_ptr(ptr).to_string_lossy().into_owned()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fn string_to_ptr(s: String) -> *mut c_char {
|
|
45
|
+
match CString::new(s) {
|
|
46
|
+
Ok(c_str) => c_str.into_raw(),
|
|
47
|
+
Err(_) => ptr::null_mut(),
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fn safe_string(bytes: &[u8]) -> String {
|
|
52
|
+
match std::str::from_utf8(bytes) {
|
|
53
|
+
Ok(s) => s.to_string(),
|
|
54
|
+
Err(_) => general_purpose::STANDARD.encode(bytes),
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// --- File System ---
|
|
59
|
+
|
|
60
|
+
#[no_mangle]
|
|
61
|
+
pub extern "C" fn fs_read_file(path: *const c_char) -> *mut c_char {
|
|
62
|
+
let path_str = ptr_to_string(path);
|
|
63
|
+
match std::fs::read(path_str) {
|
|
64
|
+
Ok(bytes) => string_to_ptr(String::from_utf8_lossy(&bytes).into_owned()),
|
|
65
|
+
Err(e) => string_to_ptr(format!("ERROR: {}", e)),
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[no_mangle]
|
|
70
|
+
pub extern "C" fn fs_write_file(path: *const c_char, content: *const c_char) {
|
|
71
|
+
let path_str = ptr_to_string(path);
|
|
72
|
+
let content_str = ptr_to_string(content);
|
|
73
|
+
let _ = std::fs::write(path_str, content_str);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#[no_mangle]
|
|
77
|
+
pub extern "C" fn fs_readdir(path: *const c_char) -> *mut c_char {
|
|
78
|
+
let path_str = ptr_to_string(path);
|
|
79
|
+
match std::fs::read_dir(path_str) {
|
|
80
|
+
Ok(entries) => {
|
|
81
|
+
let files: Vec<String> = entries
|
|
82
|
+
.filter_map(|entry| entry.ok().and_then(|e| e.file_name().into_string().ok()))
|
|
83
|
+
.collect();
|
|
84
|
+
let json = serde_json::to_string(&files).unwrap_or_else(|_| "[]".to_string());
|
|
85
|
+
string_to_ptr(json)
|
|
86
|
+
},
|
|
87
|
+
Err(_) => string_to_ptr("[]".to_string()),
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#[no_mangle]
|
|
92
|
+
pub extern "C" fn fs_mkdir(path: *const c_char) {
|
|
93
|
+
let path_str = ptr_to_string(path);
|
|
94
|
+
let _ = std::fs::create_dir_all(path_str);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
#[no_mangle]
|
|
98
|
+
pub extern "C" fn fs_exists(path: *const c_char) -> bool {
|
|
99
|
+
let path_str = ptr_to_string(path);
|
|
100
|
+
std::path::Path::new(&path_str).exists()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#[no_mangle]
|
|
104
|
+
pub extern "C" fn fs_stat(path: *const c_char) -> *mut c_char {
|
|
105
|
+
let path_str = ptr_to_string(path);
|
|
106
|
+
match std::fs::metadata(path_str) {
|
|
107
|
+
Ok(meta) => {
|
|
108
|
+
let stat = serde_json::json!({
|
|
109
|
+
"size": meta.len(),
|
|
110
|
+
"isFile": meta.is_file(),
|
|
111
|
+
"isDir": meta.is_dir(),
|
|
112
|
+
"modified": meta.modified().ok().and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok()).map(|d| d.as_millis()).unwrap_or(0),
|
|
113
|
+
});
|
|
114
|
+
string_to_ptr(stat.to_string())
|
|
115
|
+
},
|
|
116
|
+
Err(_) => string_to_ptr("{}".to_string()),
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#[no_mangle]
|
|
121
|
+
pub extern "C" fn fs_remove(path: *const c_char) {
|
|
122
|
+
let path_str = ptr_to_string(path);
|
|
123
|
+
let p = std::path::Path::new(&path_str);
|
|
124
|
+
if p.is_dir() {
|
|
125
|
+
let _ = std::fs::remove_dir_all(p);
|
|
126
|
+
} else {
|
|
127
|
+
let _ = std::fs::remove_file(p);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#[no_mangle]
|
|
132
|
+
pub extern "C" fn path_cwd() -> *mut c_char {
|
|
133
|
+
match std::env::current_dir() {
|
|
134
|
+
Ok(p) => string_to_ptr(p.to_string_lossy().into_owned()),
|
|
135
|
+
Err(_) => string_to_ptr(String::new()),
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// --- Proc ---
|
|
140
|
+
#[no_mangle]
|
|
141
|
+
pub extern "C" fn proc_info() -> *mut c_char {
|
|
142
|
+
let info = serde_json::json!({
|
|
143
|
+
"pid": std::process::id(),
|
|
144
|
+
"uptime": 0, // difficult to get comfortably x-platform without more crates
|
|
145
|
+
});
|
|
146
|
+
string_to_ptr(info.to_string())
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#[no_mangle]
|
|
150
|
+
pub extern "C" fn proc_run(
|
|
151
|
+
command: *const c_char,
|
|
152
|
+
options_json: *const c_char,
|
|
153
|
+
) -> *mut c_char {
|
|
154
|
+
let cmd = ptr_to_string(command);
|
|
155
|
+
let options_str = ptr_to_string(options_json);
|
|
156
|
+
|
|
157
|
+
let options: serde_json::Value =
|
|
158
|
+
serde_json::from_str(&options_str).unwrap_or(serde_json::json!({}));
|
|
159
|
+
|
|
160
|
+
let args: Vec<String> = options["args"]
|
|
161
|
+
.as_array()
|
|
162
|
+
.map(|arr| arr.iter().map(|v| v.as_str().unwrap_or("").to_string()).collect())
|
|
163
|
+
.unwrap_or_default();
|
|
164
|
+
|
|
165
|
+
let cwd_str = options["cwd"].as_str().unwrap_or("");
|
|
166
|
+
|
|
167
|
+
let cwd_res = if cwd_str.is_empty() {
|
|
168
|
+
std::env::current_dir()
|
|
169
|
+
} else {
|
|
170
|
+
let p = std::path::Path::new(cwd_str);
|
|
171
|
+
if p.is_absolute() {
|
|
172
|
+
Ok(p.to_path_buf())
|
|
173
|
+
} else {
|
|
174
|
+
std::env::current_dir().map(|d| d.join(p))
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
let cwd = match cwd_res {
|
|
179
|
+
Ok(c) => c,
|
|
180
|
+
Err(e) => return string_to_ptr(format!("ERROR: Failed to resolve CWD: {}", e)),
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
let mut command = std::process::Command::new(cmd);
|
|
184
|
+
command.args(args);
|
|
185
|
+
command.current_dir(&cwd);
|
|
186
|
+
command.stdin(std::process::Stdio::null());
|
|
187
|
+
command.stdout(std::process::Stdio::null());
|
|
188
|
+
command.stderr(std::process::Stdio::null());
|
|
189
|
+
|
|
190
|
+
match command.spawn() {
|
|
191
|
+
Ok(child) => {
|
|
192
|
+
let res = serde_json::json!({
|
|
193
|
+
"ok": true,
|
|
194
|
+
"pid": child.id(),
|
|
195
|
+
"cwd": cwd
|
|
196
|
+
});
|
|
197
|
+
string_to_ptr(res.to_string())
|
|
198
|
+
}
|
|
199
|
+
Err(e) => {
|
|
200
|
+
string_to_ptr(format!("ERROR: Spawn failed: {}", e))
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#[no_mangle]
|
|
206
|
+
pub extern "C" fn proc_kill(pid: f64) -> bool {
|
|
207
|
+
let pid_int = pid as usize;
|
|
208
|
+
use sysinfo::{System, Pid};
|
|
209
|
+
let s = System::new_all();
|
|
210
|
+
let pid = Pid::from(pid_int);
|
|
211
|
+
if let Some(process) = s.process(pid) {
|
|
212
|
+
process.kill()
|
|
213
|
+
} else {
|
|
214
|
+
false
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#[no_mangle]
|
|
219
|
+
pub extern "C" fn proc_list() -> *mut c_char {
|
|
220
|
+
use sysinfo::System;
|
|
221
|
+
let mut s = System::new_all();
|
|
222
|
+
s.refresh_processes();
|
|
223
|
+
let processes: Vec<serde_json::Value> = s.processes().iter().map(|(pid, process)| {
|
|
224
|
+
serde_json::json!({
|
|
225
|
+
"pid": pid.as_u32(),
|
|
226
|
+
"name": process.name(),
|
|
227
|
+
"cmd": process.cmd(),
|
|
228
|
+
"memory": process.memory(),
|
|
229
|
+
"cpu": process.cpu_usage(),
|
|
230
|
+
})
|
|
231
|
+
}).collect();
|
|
232
|
+
string_to_ptr(serde_json::to_string(&processes).unwrap_or("[]".to_string()))
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// --- Crypto ---
|
|
236
|
+
|
|
237
|
+
#[no_mangle]
|
|
238
|
+
pub extern "C" fn crypto_hash(algo: *const c_char, data: *const c_char) -> *mut c_char {
|
|
239
|
+
let algo_str = ptr_to_string(algo);
|
|
240
|
+
let data_str = ptr_to_string(data);
|
|
241
|
+
|
|
242
|
+
let res = crypto_impl::hash_keyed(&algo_str, "", &data_str); // Re-use hash_keyed with empty key? Or implement simple hash logic?
|
|
243
|
+
// Wait, crypto_impl doesn't have simple hash. It has hash_keyed (HMAC).
|
|
244
|
+
// I should check crypto_impl content again.
|
|
245
|
+
// It has `hash_keyed`. It imports sha2::{Sha256, Sha512}.
|
|
246
|
+
// I will implement simple hash here or add it to crypto_impl.
|
|
247
|
+
// For now, I'll use Sha256 directly here to save time editing crypto_impl.
|
|
248
|
+
let res = match algo_str.as_str() {
|
|
249
|
+
"sha256" => {
|
|
250
|
+
use sha2::Digest;
|
|
251
|
+
let mut hasher = sha2::Sha256::new();
|
|
252
|
+
hasher.update(data_str);
|
|
253
|
+
Ok(hex::encode(hasher.finalize()))
|
|
254
|
+
},
|
|
255
|
+
"sha512" => {
|
|
256
|
+
use sha2::Digest;
|
|
257
|
+
let mut hasher = sha2::Sha512::new();
|
|
258
|
+
hasher.update(data_str);
|
|
259
|
+
Ok(hex::encode(hasher.finalize()))
|
|
260
|
+
},
|
|
261
|
+
_ => Err("Unsupported algorithm".to_string())
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
match res {
|
|
265
|
+
Ok(s) => string_to_ptr(s),
|
|
266
|
+
Err(e) => string_to_ptr(format!("ERROR: {}", e)),
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
#[no_mangle]
|
|
271
|
+
pub extern "C" fn crypto_random_bytes(size: f64) -> *mut c_char {
|
|
272
|
+
let size = size as usize;
|
|
273
|
+
let mut bytes = vec![0u8; size];
|
|
274
|
+
// let _ = getrandom::getrandom(&mut bytes);
|
|
275
|
+
// crypto_impl uses rand::thread_rng().
|
|
276
|
+
let mut rng = rand::thread_rng();
|
|
277
|
+
use rand::RngCore;
|
|
278
|
+
rng.fill_bytes(&mut bytes);
|
|
279
|
+
string_to_ptr(hex::encode(bytes))
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
#[no_mangle]
|
|
283
|
+
pub extern "C" fn crypto_uuid() -> *mut c_char {
|
|
284
|
+
string_to_ptr(uuid::Uuid::new_v4().to_string())
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#[no_mangle]
|
|
288
|
+
pub extern "C" fn crypto_encrypt(algo: *const c_char, json_args: *const c_char) -> *mut c_char {
|
|
289
|
+
let algo_str = ptr_to_string(algo);
|
|
290
|
+
let args_str = ptr_to_string(json_args);
|
|
291
|
+
|
|
292
|
+
// Parse JSON args {key, plaintext}
|
|
293
|
+
let args: serde_json::Value = match serde_json::from_str(&args_str) {
|
|
294
|
+
Ok(v) => v,
|
|
295
|
+
Err(_) => return string_to_ptr("ERROR: Invalid JSON".to_string()),
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
let key = args["key"].as_str().unwrap_or("");
|
|
299
|
+
let plaintext = args["plaintext"].as_str().unwrap_or("");
|
|
300
|
+
|
|
301
|
+
match crypto_impl::encrypt(&algo_str, key, plaintext) {
|
|
302
|
+
Ok(s) => string_to_ptr(s),
|
|
303
|
+
Err(e) => string_to_ptr(format!("ERROR: {}", e)),
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
#[no_mangle]
|
|
308
|
+
pub extern "C" fn crypto_decrypt(algo: *const c_char, json_args: *const c_char) -> *mut c_char {
|
|
309
|
+
let algo_str = ptr_to_string(algo);
|
|
310
|
+
let args_str = ptr_to_string(json_args);
|
|
311
|
+
|
|
312
|
+
let args: serde_json::Value = match serde_json::from_str(&args_str) {
|
|
313
|
+
Ok(v) => v,
|
|
314
|
+
Err(_) => return string_to_ptr("ERROR: Invalid JSON".to_string()),
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
let key = args["key"].as_str().unwrap_or("");
|
|
318
|
+
let ciphertext = args["ciphertext"].as_str().unwrap_or("");
|
|
319
|
+
|
|
320
|
+
match crypto_impl::decrypt(&algo_str, key, ciphertext) {
|
|
321
|
+
Ok(bytes) => string_to_ptr(safe_string(&bytes)),
|
|
322
|
+
Err(e) => string_to_ptr(format!("ERROR: {}", e)),
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
#[no_mangle]
|
|
327
|
+
pub extern "C" fn crypto_hash_keyed(algo: *const c_char, json_args: *const c_char) -> *mut c_char {
|
|
328
|
+
let algo_str = ptr_to_string(algo);
|
|
329
|
+
let args_str = ptr_to_string(json_args);
|
|
330
|
+
|
|
331
|
+
let args: serde_json::Value = match serde_json::from_str(&args_str) {
|
|
332
|
+
Ok(v) => v,
|
|
333
|
+
Err(_) => return string_to_ptr("ERROR: Invalid JSON".to_string()),
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
let key = args["key"].as_str().unwrap_or("");
|
|
337
|
+
let message = args["message"].as_str().unwrap_or("");
|
|
338
|
+
|
|
339
|
+
match crypto_impl::hash_keyed(&algo_str, key, message) {
|
|
340
|
+
Ok(s) => string_to_ptr(s),
|
|
341
|
+
Err(e) => string_to_ptr(format!("ERROR: {}", e)),
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
#[no_mangle]
|
|
346
|
+
pub extern "C" fn crypto_compare(a: *const c_char, b: *const c_char) -> bool {
|
|
347
|
+
let a_str = ptr_to_string(a);
|
|
348
|
+
let b_str = ptr_to_string(b);
|
|
349
|
+
crypto_impl::compare(&a_str, &b_str)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
// --- OS ---
|
|
354
|
+
#[no_mangle]
|
|
355
|
+
pub extern "C" fn os_info() -> *mut c_char {
|
|
356
|
+
let info = serde_json::json!({
|
|
357
|
+
"platform": std::env::consts::OS,
|
|
358
|
+
"cpus": std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1),
|
|
359
|
+
// sys-info = "0.9"
|
|
360
|
+
"totalMemory": sys_info::mem_info().map(|m| m.total * 1024).unwrap_or(0),
|
|
361
|
+
"freeMemory": sys_info::mem_info().map(|m| m.free * 1024).unwrap_or(0),
|
|
362
|
+
"tempDir": std::env::temp_dir(),
|
|
363
|
+
});
|
|
364
|
+
string_to_ptr(info.to_string())
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// --- Net ---
|
|
368
|
+
#[no_mangle]
|
|
369
|
+
pub extern "C" fn net_resolve(hostname: *const c_char) -> *mut c_char {
|
|
370
|
+
let host = ptr_to_string(hostname);
|
|
371
|
+
// dns-lookup crate
|
|
372
|
+
match dns_lookup::lookup_host(&host) {
|
|
373
|
+
Ok(ips) => {
|
|
374
|
+
let ip_strs: Vec<String> = ips.iter().map(|ip| ip.to_string()).collect();
|
|
375
|
+
string_to_ptr(serde_json::to_string(&ip_strs).unwrap_or("[]".into()))
|
|
376
|
+
},
|
|
377
|
+
Err(_) => string_to_ptr("[]".to_string()),
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
#[no_mangle]
|
|
382
|
+
pub extern "C" fn net_ip() -> *mut c_char {
|
|
383
|
+
// local-ip-address crate
|
|
384
|
+
use local_ip_address::local_ip;
|
|
385
|
+
match local_ip() {
|
|
386
|
+
Ok(ip) => string_to_ptr(ip.to_string()),
|
|
387
|
+
Err(_) => string_to_ptr("127.0.0.1".to_string()),
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// --- Time ---
|
|
392
|
+
#[no_mangle]
|
|
393
|
+
pub extern "C" fn time_sleep(ms: f64) {
|
|
394
|
+
thread::sleep(Duration::from_millis(ms as u64));
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// --- Local Storage (THE FIX) ---
|
|
398
|
+
|
|
399
|
+
#[no_mangle]
|
|
400
|
+
pub extern "C" fn ls_get(key: *const c_char) -> *mut c_char {
|
|
401
|
+
let key_str = ptr_to_string(key);
|
|
402
|
+
match storage_impl::ls_get(&key_str) {
|
|
403
|
+
Some(val) => string_to_ptr(safe_string(val.as_bytes())),
|
|
404
|
+
None => string_to_ptr(String::new()),
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
#[no_mangle]
|
|
409
|
+
pub extern "C" fn ls_set(key: *const c_char, value: *const c_char) {
|
|
410
|
+
let key_str = ptr_to_string(key);
|
|
411
|
+
let val_str = ptr_to_string(value);
|
|
412
|
+
let _ = storage_impl::ls_set(&key_str, &val_str);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
#[no_mangle]
|
|
416
|
+
pub extern "C" fn ls_remove(key: *const c_char) {
|
|
417
|
+
let key_str = ptr_to_string(key);
|
|
418
|
+
let _ = storage_impl::ls_remove(&key_str);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
#[no_mangle]
|
|
422
|
+
pub extern "C" fn ls_clear() {
|
|
423
|
+
let _ = storage_impl::ls_clear();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
#[no_mangle]
|
|
427
|
+
pub extern "C" fn ls_keys() -> *mut c_char {
|
|
428
|
+
match storage_impl::ls_keys() {
|
|
429
|
+
Ok(keys) => {
|
|
430
|
+
let json = serde_json::to_string(&keys).unwrap_or("[]".to_string());
|
|
431
|
+
string_to_ptr(json)
|
|
432
|
+
},
|
|
433
|
+
Err(_) => string_to_ptr("[]".to_string()),
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// --- Sessions ---
|
|
438
|
+
|
|
439
|
+
#[no_mangle]
|
|
440
|
+
pub extern "C" fn session_get(sid: *const c_char, key: *const c_char) -> *mut c_char {
|
|
441
|
+
let sid_str = ptr_to_string(sid);
|
|
442
|
+
let key_str = ptr_to_string(key);
|
|
443
|
+
match storage_impl::session_get(&sid_str, &key_str) {
|
|
444
|
+
Some(v) => string_to_ptr(v),
|
|
445
|
+
None => string_to_ptr(String::new()),
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
#[no_mangle]
|
|
450
|
+
pub extern "C" fn session_set(sid: *const c_char, key: *const c_char) { // Value?
|
|
451
|
+
// Wait, titan.json says session_set(string, string).
|
|
452
|
+
// And storage_impl::session_set takes (sid, key, value).
|
|
453
|
+
// titan.json signatures are limited to 2 args in the user's snippet?
|
|
454
|
+
// "session_set": parameters: ["string", "string"].
|
|
455
|
+
// But index.js says: native_session_set(sessionId, JSON.stringify({ key, value }))
|
|
456
|
+
// Ah! It packs key and value into the second argument.
|
|
457
|
+
// So I need to unpack it here.
|
|
458
|
+
let sid_str = ptr_to_string(sid);
|
|
459
|
+
let args_str = ptr_to_string(key); // This is actually the "packed" arg
|
|
460
|
+
|
|
461
|
+
// BUT! index.js line 360: native_session_set(sessionId, JSON.stringify({ key, value }))
|
|
462
|
+
// So Rust needs to parse that JSON.
|
|
463
|
+
|
|
464
|
+
if let Ok(json) = serde_json::from_str::<serde_json::Value>(&args_str) {
|
|
465
|
+
let real_key = json["key"].as_str().unwrap_or("");
|
|
466
|
+
let real_val = json["value"].as_str().unwrap_or("");
|
|
467
|
+
let _ = storage_impl::session_set(&sid_str, real_key, real_val);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
#[no_mangle]
|
|
472
|
+
pub extern "C" fn session_delete(sid: *const c_char, key: *const c_char) {
|
|
473
|
+
let sid_str = ptr_to_string(sid);
|
|
474
|
+
let key_str = ptr_to_string(key);
|
|
475
|
+
let _ = storage_impl::session_delete(&sid_str, &key_str);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
#[no_mangle]
|
|
479
|
+
pub extern "C" fn session_clear(sid: *const c_char) {
|
|
480
|
+
let sid_str = ptr_to_string(sid);
|
|
481
|
+
let _ = storage_impl::session_clear(&sid_str);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// --- TITAN ABI: Unified JSON Export ---
|
|
485
|
+
// All native calls pass through this single entry point.
|
|
486
|
+
// Request: { "function": "fn_name", "params": [...args] }
|
|
487
|
+
// Response: any JSON value
|
|
488
|
+
|
|
489
|
+
#[no_mangle]
|
|
490
|
+
pub extern "C" fn titan_export(request_json: *const c_char) -> *const c_char {
|
|
491
|
+
let request_str = ptr_to_string(request_json);
|
|
492
|
+
let request: serde_json::Value = match serde_json::from_str(&request_str) {
|
|
493
|
+
Ok(v) => v,
|
|
494
|
+
Err(_) => return string_to_ptr(serde_json::json!({"error": "Invalid request JSON"}).to_string()),
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
let function = request["function"].as_str().unwrap_or("");
|
|
498
|
+
let params = request["params"].as_array();
|
|
499
|
+
|
|
500
|
+
let res = match function {
|
|
501
|
+
|
|
502
|
+
// ── File System ──────────────────────────────────────────────────
|
|
503
|
+
"fs_read_file" => {
|
|
504
|
+
let path = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
505
|
+
match std::fs::read(path) {
|
|
506
|
+
Ok(bytes) => serde_json::json!(String::from_utf8_lossy(&bytes).to_string()),
|
|
507
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
"fs_write_file" => {
|
|
511
|
+
let path = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
512
|
+
let content = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("");
|
|
513
|
+
match std::fs::write(path, content) {
|
|
514
|
+
Ok(_) => serde_json::json!(true),
|
|
515
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
"fs_exists" => {
|
|
519
|
+
let path = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
520
|
+
serde_json::json!(std::path::Path::new(path).exists())
|
|
521
|
+
},
|
|
522
|
+
"fs_readdir" => {
|
|
523
|
+
let path = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
524
|
+
match std::fs::read_dir(path) {
|
|
525
|
+
Ok(entries) => {
|
|
526
|
+
let files: Vec<String> = entries
|
|
527
|
+
.filter_map(|e| e.ok().and_then(|e| e.file_name().into_string().ok()))
|
|
528
|
+
.collect();
|
|
529
|
+
serde_json::json!(files)
|
|
530
|
+
},
|
|
531
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
"fs_mkdir" => {
|
|
535
|
+
let path = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
536
|
+
match std::fs::create_dir_all(path) {
|
|
537
|
+
Ok(_) => serde_json::json!(true),
|
|
538
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
539
|
+
}
|
|
540
|
+
},
|
|
541
|
+
"fs_stat" => {
|
|
542
|
+
let path = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
543
|
+
match std::fs::metadata(path) {
|
|
544
|
+
Ok(m) => serde_json::json!({
|
|
545
|
+
"size": m.len(),
|
|
546
|
+
"isFile": m.is_file(),
|
|
547
|
+
"isDir": m.is_dir(),
|
|
548
|
+
}),
|
|
549
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
"fs_remove" => {
|
|
553
|
+
let path = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
554
|
+
let p = std::path::Path::new(path);
|
|
555
|
+
let res = if p.is_dir() { std::fs::remove_dir_all(p) } else { std::fs::remove_file(p) };
|
|
556
|
+
match res {
|
|
557
|
+
Ok(_) => serde_json::json!(true),
|
|
558
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
559
|
+
}
|
|
560
|
+
},
|
|
561
|
+
|
|
562
|
+
// ── Crypto ──────────────────────────────────────────────────────
|
|
563
|
+
"crypto_uuid" => serde_json::json!(uuid::Uuid::new_v4().to_string()),
|
|
564
|
+
"crypto_hash" => {
|
|
565
|
+
let algo = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("sha256");
|
|
566
|
+
let data = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("");
|
|
567
|
+
serde_json::json!(crypto_impl::hash(algo, data))
|
|
568
|
+
},
|
|
569
|
+
"crypto_random_bytes" => {
|
|
570
|
+
let size = params.and_then(|p| p.get(0)).and_then(|v| v.as_u64()).unwrap_or(32) as usize;
|
|
571
|
+
serde_json::json!(crypto_impl::random_bytes(size))
|
|
572
|
+
},
|
|
573
|
+
"crypto_encrypt" => {
|
|
574
|
+
let algo = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("aes-256-gcm");
|
|
575
|
+
let payload_str = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("{}");
|
|
576
|
+
let payload: serde_json::Value = serde_json::from_str(payload_str).unwrap_or(serde_json::json!({}));
|
|
577
|
+
let key = payload["key"].as_str().unwrap_or("");
|
|
578
|
+
let plaintext = payload["plaintext"].as_str().unwrap_or("");
|
|
579
|
+
match crypto_impl::encrypt(algo, key, plaintext) {
|
|
580
|
+
Ok(s) => serde_json::json!(s),
|
|
581
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
"crypto_decrypt" => {
|
|
585
|
+
let algo = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("aes-256-gcm");
|
|
586
|
+
let payload_str = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("{}");
|
|
587
|
+
let payload: serde_json::Value = serde_json::from_str(payload_str).unwrap_or(serde_json::json!({}));
|
|
588
|
+
let key = payload["key"].as_str().unwrap_or("");
|
|
589
|
+
let ciphertext = payload["ciphertext"].as_str().unwrap_or("");
|
|
590
|
+
match crypto_impl::decrypt(algo, key, ciphertext) {
|
|
591
|
+
Ok(bytes) => serde_json::json!(String::from_utf8_lossy(&bytes).to_string()),
|
|
592
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
"crypto_hash_keyed" => {
|
|
596
|
+
let algo = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("sha256");
|
|
597
|
+
let payload_str = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("{}");
|
|
598
|
+
let payload: serde_json::Value = serde_json::from_str(payload_str).unwrap_or(serde_json::json!({}));
|
|
599
|
+
let key = payload["key"].as_str().unwrap_or("");
|
|
600
|
+
let message = payload["message"].as_str().unwrap_or("");
|
|
601
|
+
match crypto_impl::hash_keyed(algo, key, message) {
|
|
602
|
+
Ok(s) => serde_json::json!(s),
|
|
603
|
+
Err(e) => serde_json::json!(format!("ERROR: {}", e)),
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
"crypto_compare" => {
|
|
607
|
+
let a = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
608
|
+
let b = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("");
|
|
609
|
+
serde_json::json!(crypto_impl::compare(a, b))
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
// ── Local Storage ───────────────────────────────────────────────
|
|
613
|
+
"ls_get" => {
|
|
614
|
+
let key = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
615
|
+
serde_json::json!(storage_impl::ls_get(key))
|
|
616
|
+
},
|
|
617
|
+
"ls_set" => {
|
|
618
|
+
let key = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
619
|
+
let value = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("");
|
|
620
|
+
storage_impl::ls_set(key, value);
|
|
621
|
+
serde_json::json!(true)
|
|
622
|
+
},
|
|
623
|
+
"ls_remove" => {
|
|
624
|
+
let key = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
625
|
+
storage_impl::ls_remove(key);
|
|
626
|
+
serde_json::json!(true)
|
|
627
|
+
},
|
|
628
|
+
"ls_clear" => { storage_impl::ls_clear(); serde_json::json!(true) },
|
|
629
|
+
"ls_keys" => serde_json::json!(storage_impl::ls_keys()),
|
|
630
|
+
"serialize" => {
|
|
631
|
+
// In IPC mode, we can't really do native V8 serialization of handles easily.
|
|
632
|
+
// But for compatibility with the Proxy, we can return an error or a placeholder.
|
|
633
|
+
// Actually, the JS side should use t.serialize if available.
|
|
634
|
+
// If we are here, it means we are in the NativeHost process, which has NO V8 scope.
|
|
635
|
+
// So we CANNOT perform native V8 serialization here.
|
|
636
|
+
serde_json::json!({"error": "Native V8 serialization requires engine-level built-ins. Please update titan-server."})
|
|
637
|
+
},
|
|
638
|
+
"deserialize" => {
|
|
639
|
+
serde_json::json!({"error": "Native V8 deserialization requires engine-level built-ins. Please update titan-server."})
|
|
640
|
+
},
|
|
641
|
+
|
|
642
|
+
// ── Sessions ────────────────────────────────────────────────────
|
|
643
|
+
"session_get" => {
|
|
644
|
+
let sid = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
645
|
+
let key = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("");
|
|
646
|
+
serde_json::json!(storage_impl::session_get(sid, key))
|
|
647
|
+
},
|
|
648
|
+
"session_set" => {
|
|
649
|
+
let sid = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
650
|
+
let key = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("");
|
|
651
|
+
let value = params.and_then(|p| p.get(2)).and_then(|v| v.as_str()).unwrap_or("");
|
|
652
|
+
storage_impl::session_set(sid, key, value);
|
|
653
|
+
serde_json::json!(true)
|
|
654
|
+
},
|
|
655
|
+
"session_delete" => {
|
|
656
|
+
let sid = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
657
|
+
let key = params.and_then(|p| p.get(1)).and_then(|v| v.as_str()).unwrap_or("");
|
|
658
|
+
storage_impl::session_delete(sid, key);
|
|
659
|
+
serde_json::json!(true)
|
|
660
|
+
},
|
|
661
|
+
"session_clear" => {
|
|
662
|
+
let sid = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
663
|
+
storage_impl::session_clear(sid);
|
|
664
|
+
serde_json::json!(true)
|
|
665
|
+
},
|
|
666
|
+
|
|
667
|
+
// ── System / OS ─────────────────────────────────────────────────
|
|
668
|
+
"os_info" => {
|
|
669
|
+
serde_json::json!({
|
|
670
|
+
"platform": std::env::consts::OS,
|
|
671
|
+
"arch": std::env::consts::ARCH,
|
|
672
|
+
"cpus": thread::available_parallelism().map(|n| n.get()).unwrap_or(1),
|
|
673
|
+
"totalMemory": sys_info::mem_info().map(|m| m.total * 1024).unwrap_or(0),
|
|
674
|
+
"freeMemory": sys_info::mem_info().map(|m| m.free * 1024).unwrap_or(0),
|
|
675
|
+
"tempDir": std::env::temp_dir().to_string_lossy().to_string(),
|
|
676
|
+
})
|
|
677
|
+
},
|
|
678
|
+
"proc_info" => {
|
|
679
|
+
serde_json::json!({
|
|
680
|
+
"pid": std::process::id(),
|
|
681
|
+
"uptime": 0,
|
|
682
|
+
})
|
|
683
|
+
},
|
|
684
|
+
"path_cwd" => {
|
|
685
|
+
serde_json::json!(std::env::current_dir()
|
|
686
|
+
.map(|p| p.to_string_lossy().to_string())
|
|
687
|
+
.unwrap_or_default())
|
|
688
|
+
},
|
|
689
|
+
"net_resolve" => {
|
|
690
|
+
let host = params.and_then(|p| p.get(0)).and_then(|v| v.as_str()).unwrap_or("");
|
|
691
|
+
use std::net::ToSocketAddrs;
|
|
692
|
+
match (host, 80u16).to_socket_addrs() {
|
|
693
|
+
Ok(mut addrs) => serde_json::json!(addrs.next().map(|a| a.ip().to_string())),
|
|
694
|
+
Err(_) => serde_json::json!(null),
|
|
695
|
+
}
|
|
696
|
+
},
|
|
697
|
+
|
|
698
|
+
_ => serde_json::json!({"error": format!("Function '{}' not found in @titanpl/core", function)}),
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
string_to_ptr(res.to_string())
|
|
702
|
+
}
|