@ionyx-apps/cli 0.4.7 → 0.4.9

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.
Files changed (51) hide show
  1. package/bin/ionyx.exe +0 -0
  2. package/ionyx-cli/src/templates/angular/src-ionyx/Cargo.toml +30 -0
  3. package/ionyx-cli/src/templates/angular/src-ionyx/build.rs +5 -0
  4. package/ionyx-cli/src/templates/angular/src-ionyx/main.rs +48 -0
  5. package/ionyx-cli/src/templates/angular/src-ionyx/src/lib.rs +267 -0
  6. package/ionyx-cli/src/templates/basic/index.html +3 -2
  7. package/ionyx-cli/src/templates/basic/ionyx-bridge.js +100 -0
  8. package/ionyx-cli/src/templates/basic/ionyx.config.json +3 -0
  9. package/ionyx-cli/src/templates/basic/package.json +6 -1
  10. package/ionyx-cli/src/templates/basic/src/App.tsx +14 -0
  11. package/ionyx-cli/src/templates/basic/src-ionyx/Cargo.toml +14 -12
  12. package/ionyx-cli/src/templates/basic/src-ionyx/main.rs +46 -3
  13. package/ionyx-cli/src/templates/leptos/index.html +2 -1
  14. package/ionyx-cli/src/templates/leptos/ionyx-bridge.js +100 -0
  15. package/ionyx-cli/src/templates/leptos/package.json +6 -1
  16. package/ionyx-cli/src/templates/leptos/src-ionyx/Cargo.toml +14 -8
  17. package/ionyx-cli/src/templates/leptos/src-ionyx/main.rs +46 -3
  18. package/ionyx-cli/src/templates/mod.rs +1 -5
  19. package/ionyx-cli/src/templates/react/index.html +1 -0
  20. package/ionyx-cli/src/templates/react/ionyx-bridge.js +100 -0
  21. package/ionyx-cli/src/templates/react/ionyx.config.json +4 -1
  22. package/ionyx-cli/src/templates/react/package.json +6 -1
  23. package/ionyx-cli/src/templates/react/src-ionyx/Cargo.toml +14 -12
  24. package/ionyx-cli/src/templates/react/src-ionyx/main.rs +46 -3
  25. package/ionyx-cli/src/templates/src-ionyx/Cargo.toml +15 -5
  26. package/ionyx-cli/src/templates/src-ionyx/bridge.rs +380 -0
  27. package/ionyx-cli/src/templates/src-ionyx/fusion.rs +47 -0
  28. package/ionyx-cli/src/templates/src-ionyx/ionyx.js +100 -0
  29. package/ionyx-cli/src/templates/src-ionyx/ipc_bridge.rs +206 -0
  30. package/ionyx-cli/src/templates/src-ionyx/lib.rs +204 -114
  31. package/ionyx-cli/src/templates/src-ionyx/main.rs +268 -3
  32. package/ionyx-cli/src/templates/src-ionyx/protocol.rs +98 -0
  33. package/ionyx-cli/src/templates/src-ionyx/window.rs +13 -0
  34. package/ionyx-cli/src/templates/svelte/index.html +1 -0
  35. package/ionyx-cli/src/templates/svelte/ionyx-bridge.js +100 -0
  36. package/ionyx-cli/src/templates/svelte/package.json +6 -1
  37. package/ionyx-cli/src/templates/svelte/src-ionyx/Cargo.toml +14 -12
  38. package/ionyx-cli/src/templates/svelte/src-ionyx/main.rs +46 -3
  39. package/ionyx-cli/src/templates/vanilla/index.html +1 -0
  40. package/ionyx-cli/src/templates/vanilla/ionyx-bridge.js +100 -0
  41. package/ionyx-cli/src/templates/vanilla/ionyx.config.json +3 -0
  42. package/ionyx-cli/src/templates/vanilla/package.json +6 -1
  43. package/ionyx-cli/src/templates/vanilla/src-ionyx/Cargo.toml +14 -12
  44. package/ionyx-cli/src/templates/vanilla/src-ionyx/main.rs +46 -3
  45. package/ionyx-cli/src/templates/vue/index.html +1 -0
  46. package/ionyx-cli/src/templates/vue/ionyx-bridge.js +100 -0
  47. package/ionyx-cli/src/templates/vue/ionyx.config.json +4 -1
  48. package/ionyx-cli/src/templates/vue/package.json +6 -1
  49. package/ionyx-cli/src/templates/vue/src-ionyx/Cargo.toml +14 -12
  50. package/ionyx-cli/src/templates/vue/src-ionyx/main.rs +46 -3
  51. package/package.json +1 -1
@@ -1,5 +1,270 @@
1
- //! my-ionyx-app backend - Ionyx Framework
1
+ use ionyx::{config, security, protocol};
2
+ use anyhow::Result;
3
+ use serde_json::json;
4
+ use std::env;
5
+ use std::path::PathBuf;
6
+ use std::sync::{Arc, Mutex};
7
+ use std::process::{Command, Stdio};
8
+ use std::io::{BufRead, BufReader};
9
+ use std::thread;
10
+ use std::time::Duration;
11
+ use tao::event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy};
12
+ use tracing::{error, info};
13
+ use wry::{WebContext, WebViewBuilder};
2
14
 
3
- fn main() -> anyhow::Result<()> {
4
- ionyx::Builder::default().run()
15
+ #[derive(Debug, Clone)]
16
+ struct IpcDispatcher {
17
+ proxy: EventLoopProxy<String>,
18
+ }
19
+
20
+ impl IpcDispatcher {
21
+ pub fn new(proxy: EventLoopProxy<String>) -> Self {
22
+ Self { proxy }
23
+ }
24
+
25
+ pub fn resolve_promise(
26
+ &self,
27
+ request_id: &str,
28
+ success: bool,
29
+ data: Option<serde_json::Value>,
30
+ error: Option<String>,
31
+ ) {
32
+ let response = json!({
33
+ "id": request_id,
34
+ "success": success,
35
+ "data": data,
36
+ "error": error
37
+ });
38
+
39
+ let js_code = format!(
40
+ "if (window.ionyx && window.ionyx.resolveResponse) {{ window.ionyx.resolveResponse('{}', {}); }}",
41
+ request_id,
42
+ response
43
+ );
44
+
45
+ if let Err(e) = self.proxy.send_event(js_code) {
46
+ error!("Failed to send IPC response to event loop: {}", e);
47
+ }
48
+ }
49
+ }
50
+
51
+ fn start_vite_dev_server() -> Result<std::process::Child> {
52
+ info!("🚀 Starting Vite dev server...");
53
+
54
+ // Get the project root (parent of src-ionyx directory)
55
+ let project_root = env::current_dir()
56
+ .map_err(|e| anyhow::anyhow!("Failed to get current directory: {}", e))?
57
+ .parent()
58
+ .unwrap_or(&env::current_dir().unwrap())
59
+ .to_path_buf();
60
+
61
+ info!("📁 Project root: {:?}", project_root);
62
+
63
+ let mut child = Command::new("npm")
64
+ .args(&["run", "dev", "--", "--host", "127.0.0.1", "--port", "5173"])
65
+ .current_dir(&project_root)
66
+ .stdout(Stdio::piped())
67
+ .stderr(Stdio::piped())
68
+ .spawn()
69
+ .map_err(|e| anyhow::anyhow!("Failed to start Vite dev server: {}", e))?;
70
+
71
+ Ok(child)
72
+ }
73
+
74
+ fn monitor_vite_server(mut child: std::process::Child) -> Result<()> {
75
+ info!("👀 Monitoring Vite dev server output...");
76
+
77
+ if let Some(stdout) = child.stdout.take() {
78
+ let reader = BufReader::new(stdout);
79
+ thread::spawn(move || {
80
+ for line in reader.lines() {
81
+ match line {
82
+ Ok(line) => {
83
+ println!("📝 Vite: {}", line);
84
+ // Check for ready indicators
85
+ if line.contains("ready") || line.contains("Ready") ||
86
+ line.contains("Local:") || line.contains("http://") {
87
+ info!("✅ Vite dev server is ready!");
88
+ }
89
+ }
90
+ Err(e) => error!("Error reading Vite output: {}", e),
91
+ }
92
+ }
93
+ });
94
+ }
95
+
96
+ // Also monitor stderr
97
+ if let Some(stderr) = child.stderr.take() {
98
+ let reader = BufReader::new(stderr);
99
+ thread::spawn(move || {
100
+ for line in reader.lines() {
101
+ match line {
102
+ Ok(line) => {
103
+ if !line.contains("webpack") && !line.contains("built in") {
104
+ eprintln!("⚠️ Vite stderr: {}", line);
105
+ }
106
+ }
107
+ Err(e) => error!("Error reading Vite stderr: {}", e),
108
+ }
109
+ }
110
+ });
111
+ }
112
+
113
+ Ok(())
114
+ }
115
+
116
+ #[tokio::main]
117
+ async fn main() -> Result<()> {
118
+ // Initialize logging
119
+ tracing_subscriber::fmt::init();
120
+
121
+ println!("🚀 Ionyx Application starting...");
122
+
123
+ // Load application configuration
124
+ let app_config = match config::Config::load().await {
125
+ Ok(config) => {
126
+ println!("✅ Configuration loaded successfully");
127
+ config
128
+ }
129
+ Err(e) => {
130
+ eprintln!("⚠️ Failed to load config, using defaults: {}", e);
131
+ config::Config::default()
132
+ }
133
+ };
134
+
135
+ // Display app information
136
+ println!("📱 App: {} v{}", app_config.app.name, app_config.app.version);
137
+ println!("🔧 Debug mode: {}", cfg!(debug_assertions));
138
+
139
+ // Initialize security manager for demonstration
140
+ // Explicitly use the security module to ensure the import is recognized
141
+ let security_manager: ionyx::security::SecurityManager = security::SecurityManager::new(app_config.clone());
142
+
143
+ // Demonstrate comprehensive security manager functionality
144
+ let test_paths = ["./app-data", "/system", "../outside"];
145
+ for &test_path in &test_paths {
146
+ let is_secure = security_manager.is_path_allowed(test_path);
147
+ println!("🔒 Security check: '{}' -> {}", test_path,
148
+ if is_secure { "ALLOWED" } else { "DENIED" });
149
+ }
150
+
151
+ // Demonstrate security validation
152
+ if let Ok(()) = security_manager.validate_path_operation("./app-data", "read") {
153
+ println!("🔒 Security validation: Path operation approved");
154
+ }
155
+
156
+ // Initialize protocol handler for demonstration
157
+ let _protocol_handler = protocol::CustomProtocolHandler::new();
158
+ println!("🌐 Protocol handler initialized");
159
+
160
+ // Start Vite dev server
161
+ let vite_child = start_vite_dev_server()?;
162
+ monitor_vite_server(vite_child)?;
163
+
164
+ // Wait for Vite to be ready
165
+ println!("⏳ Waiting for Vite dev server to be ready...");
166
+ thread::sleep(Duration::from_secs(5));
167
+
168
+ // Create event loop
169
+ let event_loop: EventLoop<String> = EventLoopBuilder::with_user_event().build();
170
+ let _web_context = WebContext::new(Some(Default::default()));
171
+
172
+ // Create window
173
+ let window = tao::window::WindowBuilder::new()
174
+ .with_title("my-ionyx-app")
175
+ .with_inner_size(tao::dpi::LogicalSize::new(1200.0, 800.0))
176
+ .with_resizable(true)
177
+ .build(&event_loop)?;
178
+
179
+ // Dev URL
180
+ let dev_url = "http://127.0.0.1:5173";
181
+ println!("🌐 Connecting to Vite dev server at {}", dev_url);
182
+
183
+ // Create IPC dispatcher
184
+ let ipc_dispatcher = Arc::new(IpcDispatcher::new(event_loop.create_proxy()));
185
+ let webview = Arc::new(Mutex::new(
186
+ WebViewBuilder::new()
187
+ .with_initialization_script(include_str!("ionyx.js"))
188
+ .with_ipc_handler(move |request| {
189
+ let dispatcher = ipc_dispatcher.clone();
190
+ let request_body = request.body().clone();
191
+ tokio::spawn(async move {
192
+ if let Ok(request_str) = String::from_utf8(request_body) {
193
+ if let Ok(ipc_request) = serde_json::from_str::<serde_json::Value>(&request_str) {
194
+ if let Some(command) = ipc_request.get("command").and_then(|c| c.as_str()) {
195
+ if let Some(id) = ipc_request.get("id").and_then(|i| i.as_str()) {
196
+ match command {
197
+ "app.getVersion" => {
198
+ let data = json!({
199
+ "name": "my-ionyx-app",
200
+ "version": "0.4.2",
201
+ "platform": std::env::consts::OS
202
+ });
203
+ dispatcher.resolve_promise(id, true, Some(data), None);
204
+ info!("✅ IPC response sent for: {}", command);
205
+ }
206
+ "os.info" => {
207
+ let data = json!({
208
+ "platform": std::env::consts::OS,
209
+ "arch": std::env::consts::ARCH,
210
+ "version": "1.0.0",
211
+ "hostname": "localhost"
212
+ });
213
+ dispatcher.resolve_promise(id, true, Some(data), None);
214
+ info!("✅ IPC response sent for: {}", command);
215
+ }
216
+ _ => {
217
+ let error = format!("Unknown command: {}", command);
218
+ dispatcher.resolve_promise(id, false, None, Some(error));
219
+ error!("Unknown IPC command: {}", command);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+ });
227
+ })
228
+ .with_navigation_handler(|url| {
229
+ url.starts_with("http://localhost:") ||
230
+ url.starts_with("https://localhost:") ||
231
+ url.starts_with("http://127.0.0.1:") ||
232
+ url.starts_with("https://127.0.0.1:") ||
233
+ url.starts_with("file://") ||
234
+ url.starts_with("ionyx://")
235
+ })
236
+ .with_url(dev_url)
237
+ .with_devtools(true)
238
+ .build(&window)?
239
+ ));
240
+
241
+ println!("✅ Ionyx application initialized successfully!");
242
+ println!("🎉 Both Vite dev server and Ionyx application are running!");
243
+ println!("🌐 Open http://127.0.0.1:5173 to access your application");
244
+
245
+ // Run event loop
246
+ event_loop.run(move |event, _, control_flow| {
247
+ *control_flow = ControlFlow::Wait;
248
+
249
+ match event {
250
+ tao::event::Event::UserEvent(js_code) => {
251
+ info!("Executing JavaScript code: {}", js_code);
252
+ if let Ok(webview_guard) = webview.lock() {
253
+ if let Err(e) = webview_guard.evaluate_script(&js_code) {
254
+ error!("Failed to execute JavaScript code: {}", e);
255
+ } else {
256
+ info!("JavaScript code executed successfully");
257
+ }
258
+ }
259
+ }
260
+ tao::event::Event::WindowEvent {
261
+ event: tao::event::WindowEvent::CloseRequested,
262
+ ..
263
+ } => {
264
+ println!("👋 Application closing...");
265
+ *control_flow = ControlFlow::Exit;
266
+ }
267
+ _ => (),
268
+ }
269
+ });
5
270
  }
@@ -0,0 +1,98 @@
1
+ use std::borrow::Cow;
2
+ use wry::http::{Request, Response, StatusCode};
3
+ use std::path::PathBuf;
4
+
5
+ #[cfg(not(debug_assertions))]
6
+ use include_dir::{include_dir, Dir};
7
+
8
+ // Configuration'dan frontendDist path'ini oku
9
+ fn get_frontend_dist_path() -> PathBuf {
10
+ // Önce Ionyx config dosyasını okumaya çalış
11
+ if let Ok(config_content) = std::fs::read_to_string("ionyx.config.toml") {
12
+ for line in config_content.lines() {
13
+ if line.trim().starts_with("frontendDist") {
14
+ if let Some(path_str) = line.split('=').nth(1) {
15
+ let clean_path = path_str.trim().trim_matches('"');
16
+ return PathBuf::from(clean_path);
17
+ }
18
+ }
19
+ }
20
+ }
21
+
22
+ PathBuf::from("../frontend/dist")
23
+ }
24
+
25
+ #[cfg(not(debug_assertions))]
26
+ static EMBEDDED_ASSETS: Dir<'static> = include_dir!("$CARGO_MANIFEST_DIR/../frontend/dist");
27
+
28
+ pub struct CustomProtocolHandler;
29
+
30
+ impl CustomProtocolHandler {
31
+ pub fn new() -> Self {
32
+ Self
33
+ }
34
+
35
+ pub fn handle_request(&self, request: Request<Vec<u8>>) -> Response<Cow<'static, [u8]>> {
36
+ let uri_path = request.uri().path();
37
+
38
+ #[cfg(debug_assertions)]
39
+ {
40
+ let _uri_path = uri_path;
41
+ let _dist_path = get_frontend_dist_path();
42
+ let _unused_ct = Self::get_content_type("index.html");
43
+ return Response::builder()
44
+ .status(StatusCode::NOT_FOUND)
45
+ .header("Content-Type", "text/plain")
46
+ .body(Cow::Borrowed(&b"Debug mode: Assets are served from Vite (localhost:5173)"[..]))
47
+ .unwrap();
48
+ }
49
+
50
+ #[cfg(not(debug_assertions))]
51
+ {
52
+ let clean_path = uri_path.trim_start_matches('/');
53
+ let file_path = if clean_path.is_empty() { "index.html" } else { clean_path };
54
+
55
+ match EMBEDDED_ASSETS.get_file(file_path) {
56
+ Some(file) => {
57
+ let content_type = Self::get_content_type(file_path);
58
+ Response::builder()
59
+ .status(StatusCode::OK)
60
+ .header("Content-Type", content_type)
61
+ .body(Cow::Borrowed(file.contents()))
62
+ .unwrap()
63
+ }
64
+ None => {
65
+ if let Some(index_file) = EMBEDDED_ASSETS.get_file("index.html") {
66
+ Response::builder()
67
+ .status(StatusCode::OK)
68
+ .header("Content-Type", "text/html")
69
+ .body(Cow::Borrowed(index_file.contents()))
70
+ .unwrap()
71
+ } else {
72
+ Response::builder()
73
+ .status(StatusCode::NOT_FOUND)
74
+ .body(Cow::Borrowed(&b"404 Not Found"[..]))
75
+ .unwrap()
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ fn get_content_type(file_path: &str) -> &'static str {
83
+ let path = std::path::Path::new(file_path);
84
+ match path.extension().and_then(|s| s.to_str()) {
85
+ Some("html") => "text/html",
86
+ Some("css") => "text/css",
87
+ Some("js") => "application/javascript",
88
+ Some("json") => "application/json",
89
+ Some("svg") => "image/svg+xml",
90
+ Some("png") => "image/png",
91
+ Some("jpg") | Some("jpeg") => "image/jpeg",
92
+ Some("gif") => "image/gif",
93
+ Some("woff") => "font/woff",
94
+ Some("woff2") => "font/woff2",
95
+ _ => "application/octet-stream",
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,13 @@
1
+ #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
2
+ pub struct WindowConfig {
3
+ pub title: String,
4
+ pub width: u32,
5
+ pub height: u32,
6
+ pub resizable: bool,
7
+ pub fullscreen: bool,
8
+ pub min_width: Option<u32>,
9
+ pub min_height: Option<u32>,
10
+ pub max_width: Option<u32>,
11
+ pub max_height: Option<u32>,
12
+ pub icon: Option<String>,
13
+ }
@@ -8,6 +8,7 @@
8
8
  </head>
9
9
  <body>
10
10
  <div id="app"></div>
11
+ <script src="ionyx-bridge.js"></script>
11
12
  <script type="module" src="frontend/src/main.ts"></script>
12
13
  </body>
13
14
  </html>
@@ -0,0 +1,100 @@
1
+ // Ionyx IPC Bridge JavaScript
2
+ (function() {
3
+ const _promises = {};
4
+ let _fusion_data = {};
5
+
6
+ window.ionyx = {
7
+ _promises,
8
+ _fusion_sync: (data) => {
9
+ console.log("🧬 Fusion Sync:", data);
10
+ _fusion_data = data;
11
+ },
12
+ resolveResponse: (responseId, response) => {
13
+ const promiseHandlers = _promises[responseId];
14
+ if (promiseHandlers) {
15
+ console.log("📥 Received IPC response:", response);
16
+ clearTimeout(promiseHandlers.timeoutId);
17
+ if (response.success) {
18
+ promiseHandlers.resolve(response.data);
19
+ } else {
20
+ promiseHandlers.reject(new Error(response.error));
21
+ }
22
+ delete _promises[responseId];
23
+ }
24
+ },
25
+ invoke: (command, payload = {}) => {
26
+ return new Promise((resolve, reject) => {
27
+ const id = `${Date.now()}_${Math.random().toString(36).substr(2, 9)}_${command}`;
28
+ const request = {
29
+ id,
30
+ command,
31
+ payload: payload || {}
32
+ };
33
+
34
+ console.log("🚀 Sending IPC request:", request);
35
+
36
+ const timeoutId = setTimeout(() => {
37
+ console.error("❌ IPC request timeout for:", command);
38
+ reject(new Error("IPC request timeout"));
39
+ delete _promises[id];
40
+ }, 15000);
41
+
42
+ _promises[id] = { resolve, reject, timeoutId };
43
+
44
+ if (window.ipc && typeof window.ipc.postMessage === 'function') {
45
+ console.log("📤 Sending via window.ipc.postMessage");
46
+ window.ipc.postMessage(JSON.stringify(request));
47
+ } else {
48
+ console.error("❌ window.ipc not available");
49
+ clearTimeout(timeoutId);
50
+ reject(new Error("IPC not available natively through window.ipc"));
51
+ delete _promises[id];
52
+ }
53
+ });
54
+ }
55
+ };
56
+
57
+ // Add Tauri-like namespaces
58
+ const invoke = window.ionyx.invoke;
59
+
60
+ window.ionyx.fs = {
61
+ readFile: (path) => invoke("fs.readFile", { path }),
62
+ writeFile: (path, content) => invoke("fs.writeFile", { path, content }),
63
+ exists: (path) => invoke("fs.exists", { path }),
64
+ readDir: (path) => invoke("fs.readdir", { path })
65
+ };
66
+
67
+ window.ionyx.os = {
68
+ info: () => invoke("os.info")
69
+ };
70
+
71
+ window.ionyx.dialog = {
72
+ openFile: () => invoke("dialog.openFile", {}),
73
+ saveFile: () => invoke("dialog.saveFile", {})
74
+ };
75
+
76
+ window.ionyx.app = {
77
+ getVersion: () => invoke("app.getVersion"),
78
+ getConfig: () => invoke("app.getConfig")
79
+ };
80
+
81
+ window.ionyx.network = {
82
+ request: (url, method = "GET", body = null) => invoke("network.request", { url, method, body })
83
+ };
84
+
85
+ // Inspired by NW.js Unified Context:
86
+ // Native Fusion allows direct access to shared state.
87
+ window.fusion = new Proxy({}, {
88
+ get: (target, prop) => {
89
+ return _fusion_data[prop];
90
+ },
91
+ set: (target, prop, value) => {
92
+ _fusion_data[prop] = value;
93
+ invoke("fusion.update", { key: prop, value });
94
+ return true;
95
+ }
96
+ });
97
+
98
+ })();
99
+
100
+ console.log("🔧 Ionyx IPC Bridge injected successfully.");
@@ -8,7 +8,12 @@
8
8
  "build": "vite build",
9
9
  "preview": "vite preview",
10
10
  "ionyx:dev": "cd src-ionyx && cargo run --bin my-ionyx-app",
11
- "ionyx:build": "cd src-ionyx && cargo build --release",
11
+ "ionyx:build": "cd src-ionyx && cargo build --release && npm run bundle:create",
12
+ "bundle:create": "node -e \"const fs=require('fs');const path=require('path');const dist=path.join(__dirname,'dist');if(!fs.existsSync(dist))fs.mkdirSync(dist);const target=path.join(__dirname,'src-ionyx','target','release','my-ionyx-app.exe');if(fs.existsSync(target)){const bundle=path.join(dist,'my-ionyx-app-v1.0.0.exe');fs.copyFileSync(target,bundle);console.log('✅ Bundle created:',bundle);}else{console.log('❌ Executable not found');}\"",
13
+ "bundle": "npm run bundle:create",
14
+ "bundle:windows": "npm run bundle:create",
15
+ "bundle:macos": "npm run bundle:create",
16
+ "bundle:linux": "npm run bundle:create",
12
17
  "ionyx": "npx ionyx",
13
18
  "ionyx:dev2": "npx ionyx dev",
14
19
  "ionyx:build2": "npx ionyx build",
@@ -4,22 +4,24 @@ name = "my-ionyx-app"
4
4
  version = "0.4.2"
5
5
  edition = "2021"
6
6
 
7
- [workspace]
8
-
9
- [lib]
10
- name = "my_ionyx_app"
11
- path = "src/lib.rs"
12
-
13
- [[bin]]
14
- name = "my-ionyx-app"
15
- path = "main.rs"
16
-
17
7
  [dependencies]
18
8
  include_dir = "0.7"
19
- ionyx = { path = "../../../../../../src-ionyx" }
20
- anyhow = "1.0"
9
+ # Web framework dependencies
21
10
  wry = "0.54"
22
11
  tao = "0.34"
12
+ tokio = { version = "1.50", features = ["full"] }
13
+ serde = { version = "1.0", features = ["derive"] }
14
+ serde_json = "1.0"
15
+ anyhow = "1.0"
16
+ toml = "0.8"
17
+ tracing = "0.1"
18
+ tracing-subscriber = "0.3"
19
+ os_info = "3"
20
+ gethostname = "0.4"
21
+
22
+ [[bin]]
23
+ name = "my-ionyx-app"
24
+ path = "main.rs"
23
25
 
24
26
  [profile.release]
25
27
  opt-level = 3
@@ -1,5 +1,48 @@
1
- //! my-ionyx-app backend - Ionyx Framework
1
+ use ionyx::{config, security, protocol};
2
2
 
3
- fn main() -> anyhow::Result<()> {
4
- ionyx::Builder::default().run()
3
+ #[tokio::main]
4
+ async fn main() {
5
+ println!("🚀 Ionyx Application starting...");
6
+
7
+ // Load application configuration
8
+ let app_config = match config::Config::load().await {
9
+ Ok(config) => {
10
+ println!("✅ Configuration loaded successfully");
11
+ config
12
+ }
13
+ Err(e) => {
14
+ eprintln!("⚠️ Failed to load config, using defaults: {}", e);
15
+ config::Config::default()
16
+ }
17
+ };
18
+
19
+ // Initialize security manager for demonstration
20
+ let security_manager: crate::security::SecurityManager = security::SecurityManager::new(app_config.clone());
21
+
22
+ // Demonstrate comprehensive security manager functionality
23
+ let test_paths = ["./app-data", "/system", "../outside"];
24
+ for &test_path in &test_paths {
25
+ let is_secure = security_manager.is_path_allowed(test_path);
26
+ println!("🔒 Security check: '{}' -> {}",
27
+ test_path,
28
+ if is_secure { "ALLOWED" } else { "DENIED" });
29
+ }
30
+
31
+ // Demonstrate security validation
32
+ if let Ok(()) = security_manager.validate_path_operation("./app-data", "read") {
33
+ println!("🔒 Security validation: Path operation approved");
34
+ }
35
+
36
+ // Initialize protocol handler for demonstration
37
+ let _protocol_handler = protocol::CustomProtocolHandler::new();
38
+ println!("🌐 Protocol handler initialized");
39
+
40
+ // Create and run the Ionyx application with automatic Vite server startup
41
+ println!("🚀 Launching Ionyx application...");
42
+ let builder = ionyx::Builder::new().config(app_config);
43
+
44
+ if let Err(e) = builder.run() {
45
+ eprintln!("❌ Application failed to start: {}", e);
46
+ std::process::exit(1);
47
+ }
5
48
  }
@@ -77,6 +77,7 @@
77
77
  </div>
78
78
  <p>Edit this file and reload to see changes!</p>
79
79
  </div>
80
+ <script src="ionyx-bridge.js"></script>
80
81
  <script type="module" src="frontend/main.js"></script>
81
82
  </body>
82
83
  </html>