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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/new/templates/rust/ui/hyperapp-skeleton/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ panic = "abort"

[workspace]
members = [
"skeleton-app",
"hyperapp-skeleton",
"target/hyperapp-skeleton-caller-util?",
]
resolver = "2"
12 changes: 6 additions & 6 deletions src/new/templates/rust/ui/hyperapp-skeleton/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ kit build --hyperapp
hyperapp-skeleton/
├── Cargo.toml # Workspace configuration
├── metadata.json # App metadata
├── skeleton-app/ # Main Rust process
├── hyperapp-skeleton/ # Main Rust process
│ ├── Cargo.toml # Process dependencies
│ └── src/
│ ├── lib.rs # Main app logic (well-commented)
Expand Down Expand Up @@ -127,7 +127,7 @@ Your app's state is automatically persisted based on the `save_config` option:

### 1. Modify App State

Edit `AppState` in `skeleton-app/src/lib.rs`:
Edit `AppState` in `hyperapp-skeleton/src/lib.rs`:
```rust
#[derive(Default, Serialize, Deserialize)]
pub struct AppState {
Expand Down Expand Up @@ -163,8 +163,8 @@ There is also a `request_networking` field that must be true to send messages ov

### 4. Update Frontend

1. Add types in `ui/src/types/skeleton.ts`
2. Update store in `ui/src/store/skeleton.ts`
1. Add types in `ui/src/types/hyperapp-skeleton.ts`
2. Update store in `ui/src/store/hyperapp-skeleton.ts`
3. Modify UI in `ui/src/App.tsx`

### 5. Rename as appropriate
Expand Down Expand Up @@ -209,7 +209,7 @@ In particular, note the example applications `resources/example-apps/sign/`, `re
`file-explorer` demonstrates VFS interactions.

Expand the prompt and/or `instructions.md` into a detailed implementation plan.
The implementor will be starting from this existing template that exists at `skeleton-app/` and `ui/`.
The implementor will be starting from this existing template that exists at `hyperapp-skeleton/` and `ui/`.

Note in particular that bindings for the UI will be generated when the app is built with `kit build --hyperapp`.
As such, first design and implement the backend; the interface will be generated from the backend; finally design and implement the frontend to consume the interface.
Expand All @@ -229,7 +229,7 @@ Look carefully at `IMPLEMENTATION_PLAN.md` and in the `resources/` directory, if
In particular, note the example applications `resources/example-apps/sign/`, `resources/example-apps/id/`, and `resources/example-apps/file-explorer`.
Use them if useful.

Work from the existing template that exists at `skeleton-app/` and `ui/`.
Work from the existing template that exists at `hyperapp-skeleton/` and `ui/`.

Note in particular that bindings for the UI will be generated when the app is built with `kit build --hyperapp`.
As such, first design and implement the backend; the interface will be generated from the backend; finally design and implement the frontend to consume the interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ crate-type = ["cdylib"]

[package]
edition = "2021"
name = "skeleton-app"
name = "hyperapp-skeleton"
version = "0.1.0"

[package.metadata.component]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct Status {
// STEP 2: IMPLEMENT YOUR APP LOGIC
// The #[hyperprocess] attribute goes HERE, before the impl block
#[hyperprocess(
name = "Skeleton App",
name = "HyperappSkeleton App",
ui = Some(hyperware_process_lib::http::server::HttpBindingConfig::default()),
endpoints = vec![
hyperware_process_lib::hyperapp::Binding::Http {
Expand All @@ -44,7 +44,7 @@ pub struct Status {
},
],
save_config = hyperware_process_lib::hyperapp::SaveOptions::EveryMessage,
wit_world = "skeleton-app-skeleton-dot-os-v0"
wit_world = "hyperapp-skeleton-template-dot-os-v0"
)]
impl AppState {
// INITIALIZATION FUNCTION
Expand All @@ -57,15 +57,15 @@ impl AppState {
async fn initialize(&mut self) {
// Add your app to the Hyperware homepage
// Parameters: name, icon, path, widget
add_to_homepage("Skeleton App", Some(ICON), Some("/"), None);
add_to_homepage("HyperappSkeleton App", Some(ICON), Some("/"), None);

// Initialize your app state
self.counter = 0;
self.messages.push("App initialized!".to_string());

// Get our node identity (useful for P2P apps)
let our_node = our().node.clone();
println!("Skeleton app initialized on node: {}", our_node);
println!("HyperappSkeleton app initialized on node: {}", our_node);
}

// HTTP ENDPOINT EXAMPLE
Expand Down
8 changes: 4 additions & 4 deletions src/new/templates/rust/ui/hyperapp-skeleton/metadata.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "SkeletonApp",
"name": "HyperappSkeleton",
"description": "A minimal skeleton app for the Hyperware platform using the Hyperapp framework - demonstrates basic state management and HTTP endpoints",
"image": "",
"properties": {
"package_name": "skeleton-app",
"package_name": "hyperapp-skeleton",
"current_version": "0.1.0",
"publisher": "skeleton.os",
"publisher": "template.os",
"mirrors": [],
"code_hashes": {
"0.1.0": ""
Expand All @@ -15,4 +15,4 @@
},
"external_url": "",
"animation_url": ""
}
}
4 changes: 2 additions & 2 deletions src/new/templates/rust/ui/hyperapp-skeleton/pkg/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
{
"process_name": "skeleton-app",
"process_wasm_path": "/skeleton-app.wasm",
"process_name": "hyperapp-skeleton",
"process_wasm_path": "/hyperapp-skeleton.wasm",
"on_exit": "Restart",
"request_networking": false,
"request_capabilities": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ kit b --hyperapp

## Project Structure
```
skeleton-app/
hyperapp-skeleton/
├── Cargo.toml # Workspace config
├── metadata.json # App metadata
├── skeleton-app/ # Rust backend
├── hyperapp-skeleton/ # Rust backend
│ ├── Cargo.toml # DO NOT add hyperware_process_lib here!
│ └── src/
│ └── lib.rs # Main app logic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ async fn sync_with_node(&mut self, request_body: String) -> Result<String, Strin
let target_node: String = serde_json::from_str(&request_body)?;

// Construct address
let process_id = format!("skeleton-app:skeleton-app:{}", "skeleton.os")
let process_id = format!("hyperapp-skeleton:hyperapp-skeleton:{}", "template.os")
.parse::<ProcessId>()
.map_err(|e| format!("Invalid process ID: {}", e))?;

Expand Down Expand Up @@ -302,7 +302,7 @@ async fn broadcast_update(&mut self, request_body: String) -> Result<String, Str
let mut errors = Vec::new();

for node in &self.connected_nodes {
let process_id = format!("skeleton-app:skeleton-app:{}", "skeleton.os")
let process_id = format!("hyperapp-skeleton:hyperapp-skeleton:{}", "template.os")
.parse::<ProcessId>()
.unwrap();

Expand Down Expand Up @@ -338,7 +338,7 @@ async fn reliable_remote_call(
data: String,
max_retries: u32,
) -> Result<String, String> {
let process_id = format!("skeleton-app:skeleton-app:{}", "skeleton.os")
let process_id = format!("hyperapp-skeleton:hyperapp-skeleton:{}", "template.os")
.parse::<ProcessId>()
.map_err(|e| format!("Invalid process ID: {}", e))?;

Expand Down Expand Up @@ -385,13 +385,13 @@ async fn reliable_remote_call(
#[http]
async fn upload_file(&mut self, file_name: String, mime_type: String, file_data: Vec<u8>) -> Result<String, String> {
let file_id = uuid::Uuid::new_v4().to_string();
let file_path = format!("/skeleton-app:skeleton.os/files/{}", file_id);
let file_path = format!("/hyperapp-skeleton:template.os/files/{}", file_id);

// Create directory if needed
let vfs_address = Address::new(our().node.clone(), "vfs:distro:sys".parse::<ProcessId>().unwrap());

let create_dir = json!({
"path": "/skeleton-app:skeleton.os/files",
"path": "/hyperapp-skeleton:template.os/files",
"action": "CreateDirAll"
});

Expand Down Expand Up @@ -431,7 +431,7 @@ async fn upload_file(&mut self, file_name: String, mime_type: String, file_data:
#[http]
async fn download_file(&self, request_body: String) -> Result<Vec<u8>, String> {
let file_id: String = serde_json::from_str(&request_body)?;
let file_path = format!("/skeleton-app:skeleton.os/files/{}", file_id);
let file_path = format!("/hyperapp-skeleton:template.os/files/{}", file_id);

let vfs_address = Address::new(our().node.clone(), "vfs:distro:sys".parse::<ProcessId>().unwrap());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ let pid = "myapp-myapp-publisher".parse::<ProcessId>(); // Wrong separator
let pid = "myapp:myapp:publisher.os".parse::<ProcessId>()?;

// For your app matching remote nodes
let publisher = "skeleton.os"; // Or whatever the remote uses
let pid = format!("skeleton-app:skeleton-app:{}", publisher)
let publisher = "template.os"; // Or whatever the remote uses
let pid = format!("hyperapp-skeleton:hyperapp-skeleton:{}", publisher)
.parse::<ProcessId>()?;
```

Expand Down Expand Up @@ -637,8 +637,8 @@ ls -la pkg/
```json
// metadata.json must exist and be valid
{
"package": "skeleton-app",
"publisher": "skeleton.os"
"package": "hyperapp-skeleton",
"publisher": "template.os"
}
```

Expand All @@ -648,7 +648,7 @@ ls -la pkg/

**Example:**
```
Error: Process skeleton-app:skeleton-app:user.os does not have capability vfs:distro:sys
Error: Process hyperapp-skeleton:hyperapp-skeleton:user.os does not have capability vfs:distro:sys
```

**Root Cause:** Using system feature without requesting capability
Expand Down Expand Up @@ -715,7 +715,7 @@ ls -la pkg/ui/
### Test Incrementally
```bash
# 1. Test backend compiles
cd skeleton-app && cargo check
cd hyperapp-skeleton && cargo check

# 2. Test UI builds
cd ui && npm run build
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ let process_id = "myapp:myapp:publisher.os"
// For your app to talk to itself on other nodes
// IMPORTANT: All nodes must use the same publisher!
let my_process_id = format!("{}:{}:{}",
"skeleton-app", // process name (from metadata.json)
"skeleton-app", // package name (from metadata.json)
"skeleton.os" // publisher (must be consistent across nodes)
"hyperapp-skeleton", // process name (from metadata.json)
"hyperapp-skeleton", // package name (from metadata.json)
"template.os" // publisher (must be consistent across nodes)
).parse::<ProcessId>()?;
```

Expand Down Expand Up @@ -120,7 +120,7 @@ async fn get_remote_data(&self, request_body: String) -> Result<String, String>
let target_node: String = serde_json::from_str(&request_body)?;

// Build address
let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>()?;
let process_id = "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>()?;
let target = Address::new(target_node, process_id);

// Create request
Expand Down Expand Up @@ -204,7 +204,7 @@ async fn broadcast_event(&mut self, request_body: String) -> Result<String, Stri

// Send to all known nodes
for node in &self.connected_nodes {
let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>()?;
let process_id = "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>()?;
let target = Address::new(node.clone(), process_id);

// Fire and forget - still set timeout for reliability
Expand Down Expand Up @@ -262,7 +262,7 @@ pub struct SyncResponse {
// Periodic sync with peers
impl AppState {
async fn sync_with_peer(&mut self, peer_node: String) -> Result<(), String> {
let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>()?;
let process_id = "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>()?;
let target = Address::new(peer_node.clone(), process_id);

// Send our state info
Expand Down Expand Up @@ -359,7 +359,7 @@ impl AppState {
"ApplyOperation": serde_json::to_string(&op).unwrap()
});

let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>()?;
let process_id = "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>()?;

for peer in &self.peers {
let target = Address::new(peer.clone(), process_id);
Expand Down Expand Up @@ -509,7 +509,7 @@ impl AppState {
"RegisterNode": serde_json::to_string(&my_info).unwrap()
});

let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>()?;
let process_id = "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>()?;

// Announce to bootstrap nodes
for bootstrap in &self.bootstrap_nodes {
Expand Down Expand Up @@ -584,7 +584,7 @@ async fn start_transaction(&mut self, request_body: String) -> Result<String, St
"PrepareTransaction": serde_json::to_string(&tx).unwrap()
});

let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>()?;
let process_id = "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>()?;
let mut votes = HashMap::new();

for participant in &tx.participants {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,14 +684,14 @@ async fn diagnose_p2p(&self, request_body: String) -> String {
let mut diagnostics = vec![];

// Check 1: ProcessId parsing
match "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>() {
match "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>() {
Ok(pid) => diagnostics.push(format!("✅ ProcessId valid: {:?}", pid)),
Err(e) => diagnostics.push(format!("❌ ProcessId error: {}", e)),
}

// Check 2: Address construction
if !target_node.is_empty() {
let pid = "skeleton-app:skeleton-app:skeleton.os".parse::<ProcessId>().ok();
let pid = "hyperapp-skeleton:hyperapp-skeleton:template.os".parse::<ProcessId>().ok();
if let Some(pid) = pid {
let addr = Address::new(target_node.clone(), pid);
diagnostics.push(format!("✅ Address created: {:?}", addr));
Expand Down
Loading