Compare commits

..

14 commits

Author SHA1 Message Date
b82d3edf77 Integrate USDPL basics 2024-10-23 22:33:31 -04:00
Zack Whipkey
05cb4433d8
small refactor to avoid vscode spitting out errors for tasks.json (#30) 2024-10-04 13:33:27 -04:00
eXhumer
49201b05d7
Changes to template for new API (#44) 2024-10-03 16:54:11 -04:00
PartyWumpus
fb031f240a small cleanup 2024-09-27 18:05:16 +01:00
PartyWumpus
a2de28e318 Merge branch 'main' into aa/websockets 2024-09-27 17:05:12 +01:00
AAGaming
df346147b0
fix order of the navigation example 2024-07-28 20:31:50 -04:00
Wayne Heaney
d69496d4ad
Add _uninstall function to the python Plugin template (#34) 2024-07-24 15:01:55 -07:00
TrainDoctor
a85c79735f
Update README.md
Closes #42
2024-07-24 15:00:07 -07:00
Renn
d18cbd5c99
Fix deployment for plugin names with more than one spaces (#41) 2024-07-09 21:59:14 -07:00
AAGaming
93ef11096f
use @decky/rollup rollup config template 2024-07-08 20:28:57 -04:00
AAGaming
64310bcf71
update deps 2024-06-13 18:31:09 -04:00
AAGaming
b939274d15
support new APIs fully 2024-06-13 18:31:08 -04:00
AnOpenSauceDev
cbd489150f
Make setup.sh download the correct binaries. (#37)
`setup.sh` downloads non-existent binaries for Decky CLI, creating a file with the contents "Not Found". This puts a check for both OS and arch so the right files are downloaded.
2024-02-26 10:03:18 -08:00
TrainDoctor
4ab713585d
Update LICENSE 2024-02-12 18:12:48 -08:00
35 changed files with 4050 additions and 507 deletions

5
.gitignore vendored
View file

@ -55,3 +55,8 @@ out/*
cli/
cli/*
cli/decky
bin/*
# Ignore Rust compiler folders
backend/target
src/rust/target

2
.vscode/build.sh vendored
View file

@ -7,4 +7,4 @@ printf "Please input sudo password to proceed.\n"
# printf "\n"
echo $sudopass | sudo $CLI_LOCATION/decky plugin build $(pwd)
echo $sudopass | sudo -E $CLI_LOCATION/decky plugin build $(pwd)

22
.vscode/setup.sh vendored
View file

@ -40,8 +40,28 @@ if ! test -f "$CLI_INSTALLED"; then
if [[ "$run_cli_script" =~ "n" ]]; then
echo "You have chosen to not install the Decky CLI tool to build your plugins. Please install this tool to build and test your plugin before submitting it to the Plugin Database."
else
SYSTEM_ARCH="$(uname -a)"
mkdir "$(pwd)"/cli
curl -L -o "$(pwd)"/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky"
if [[ "$SYSTEM_ARCH" =~ "x86_64" ]]; then
if [[ "$SYSTEM_ARCH" =~ "Linux" ]]; then
curl -L -o "$(pwd)"/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky-linux-x86_64"
fi
if [[ "$SYSTEM_ARCH" =~ "Darwin" ]]; then
curl -L -o "$(pwd)"/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky-macOS-x86_64"
fi
else
echo "System Arch not found! The only supported systems are Linux x86_64 and Apple x86_64/ARM64, not $SYSTEM_ARCH"
fi
if [[ "$SYSTEM_ARCH" =~ "arm64" ]]; then
curl -L -o "$(pwd)"/cli/decky "https://github.com/SteamDeckHomebrew/cli/releases/latest/download/decky-macOS-aarch64"
fi
chmod +x "$(pwd)"/cli/decky
echo "Decky CLI tool is now installed and you can build plugins into easy zip files using the "Build Zip" Task in vscodium."
fi

18
.vscode/tasks.json vendored
View file

@ -8,9 +8,7 @@
"type": "shell",
"group": "none",
"detail": "Install depedencies for basic setup",
"linux": {
"command": "${workspaceFolder}/.vscode/setup.sh",
},
"command": "${workspaceFolder}/.vscode/setup.sh",
// // placeholder for windows scripts, not currently planned
// "windows": {
// "command": "call -c ${workspaceFolder}\\.vscode\\setup.bat",
@ -44,9 +42,7 @@
"type": "shell",
"group": "none",
"detail": "Check that settings.json has been created",
"linux": {
"command": "${workspaceFolder}/.vscode/config.sh",
},
"command": "${workspaceFolder}/.vscode/config.sh",
// // placeholder for windows scripts, not currently planned
// "windows": {
// "command": "call ${workspaceFolder}\\.vscode\\config.bat",
@ -58,9 +54,7 @@
"label": "cli-build",
"group": "build",
"detail": "Build plugin with CLI",
"linux": {
"command": "${workspaceFolder}/.vscode/build.sh",
},
"command": "${workspaceFolder}/.vscode/build.sh",
// // placeholder for windows logic, not currently planned
// "windows": {
// "command": "call ${workspaceFolder}\\.vscode\\build.bat",
@ -99,7 +93,7 @@
"detail": "",
"type": "shell",
"group": "none",
"command": "echo '${config:deckdir}/homebrew/plugins/${config:pluginname}.zip' && ssh ${config:deckuser}@${config:deckip} -p ${config:deckport} ${config:deckkey} 'echo ${config:deckpass} | sudo -S cp \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" cp \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}-backup\" | sudo -S rm \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sudo -S mkdir 755 -m -p \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|\")\" && echo ${config:deckpass} | sudo -S chown ${config:deckuser}:${config:deckuser} \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|\")\" && echo ${config:deckpass} | sudo -S bsdtar -xzpf \"${config:deckdir}/homebrew/plugins/${config:pluginname}.zip\" -C \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|g\")\" --strip-components=1 --fflags '",
"command": "echo '${config:deckdir}/homebrew/plugins/${config:pluginname}.zip' && ssh ${config:deckuser}@${config:deckip} -p ${config:deckport} ${config:deckkey} 'echo ${config:deckpass} | sudo -S mkdir 755 -p \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|g\")\" && echo ${config:deckpass} | sudo -S chown ${config:deckuser}:${config:deckuser} \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|g\")\" && echo ${config:deckpass} | sudo -S bsdtar -xzpf \"${config:deckdir}/homebrew/plugins/${config:pluginname}.zip\" -C \"$(echo \"${config:deckdir}/homebrew/plugins/${config:pluginname}\" | sed \"s| |-|g\")\" --strip-components=1 --fflags '",
"problemMatcher": []
},
//"All-in-one" deploy task
@ -131,8 +125,8 @@
"label": "updatefrontendlib",
"type": "shell",
"group": "build",
"detail": "Update deck-frontend-lib aka DFL",
"command": "pnpm update decky-frontend-lib --latest",
"detail": "Update @decky/ui aka DFL",
"command": "pnpm update @decky/ui --latest",
"problemMatcher": []
},
//Used chmod plugins folder to allow copy-over of files

View file

@ -1,7 +1,7 @@
BSD 3-Clause License
Copyright (c) 2023, Hypothetical Plugin Developer
Original Copyright (c) 2022-2023, Steam Deck Homebrew
Copyright (c) 2024, Hypothetical Plugin Developer
Original Copyright (c) 2022-2024, Steam Deck Homebrew
All rights reserved.

View file

@ -1,6 +1,6 @@
# React-Frontend Plugin Template [![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://deckbrew.xyz/discord)
# Decky Plugin Template [![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://deckbrew.xyz/discord)
Reference example for using [decky-frontend-lib](https://github.com/SteamDeckHomebrew/decky-frontend-lib) in a [decky-loader](https://github.com/SteamDeckHomebrew/decky-loader) plugin.
Reference example for using [decky-frontend-lib](https://github.com/SteamDeckHomebrew/decky-frontend-lib) (@decky/ui) in a [decky-loader](https://github.com/SteamDeckHomebrew/decky-loader) plugin.
### **Please also refer to the [wiki](https://wiki.deckbrew.xyz/en/user-guide/home#plugin-development) for important information on plugin development and submissions/updates. currently documentation is split between this README and the wiki which is something we are hoping to rectify in the future.**
@ -8,24 +8,20 @@ Reference example for using [decky-frontend-lib](https://github.com/SteamDeckHom
### Dependencies
This template relies on the user having Node.js v16.14+ and `pnpm` (v8.5.1) installed on their system.
Please make sure to install pnpm v8.5.1 to prevent issues with CI during plugin submission.
This template relies on the user having Node.js v16.14+ and `pnpm` (v9) installed on their system.
Please make sure to install pnpm v9 to prevent issues with CI during plugin submission.
`pnpm` can be downloaded from `npm` itself which is recommended.
#### Linux
```bash
sudo npm i -g pnpm@8.5.1
sudo npm i -g pnpm@9
```
If you would like to build plugins that have their own custom backends, Docker is required as it is used by the Decky CLI tool.
### Making your own plugin
If you use VSCode or it's derivatives (we suggest [VSCodium](https://vscodium.com/)!) just run the `setup` and `build` tasks. It's really that simple.
1. You can fork this repo or utilize the "Use this template" button on Github.
2. In your local fork/own plugin-repository run these commands:
1. ``pnpm i``
@ -33,8 +29,8 @@ If you use VSCode or it's derivatives (we suggest [VSCodium](https://vscodium.co
- These setup pnpm and build the frontend code for testing.
3. Consult the [decky-frontend-lib](https://github.com/SteamDeckHomebrew/decky-frontend-lib) repository for ways to accomplish your tasks.
- Documentation and examples are still rough,
- While decky-loader primarily targets Steam Deck hardware so keep this in mind when developing your plugin.
4. Run the `setup` and `build` and `deploy` vscode tasks, or you can derive your own makefile or just manually utilize the scripts for these commands as you see fit.
- Decky loader primarily targets Steam Deck hardware so keep this in mind when developing your plugin.
4. If using VSCodium/VSCode, run the `setup` and `build` and `deploy` tasks. If not using VSCodium etc. you can derive your own makefile or just manually utilize the scripts for these commands as you see fit.
If you use VSCode or it's derivatives (we suggest [VSCodium](https://vscodium.com/)!) just run the `setup` and `build` tasks. It's really that simple.
@ -45,7 +41,7 @@ Everytime you change the frontend code (`index.tsx` etc) you will need to rebuil
Note: If you are receiving build errors due to an out of date library, you should run this command inside of your repository:
```bash
pnpm update decky-frontend-lib --latest
pnpm update @decky/ui --latest
```
### Backend support

1609
backend/Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

35
backend/Cargo.toml Normal file
View file

@ -0,0 +1,35 @@
[package]
name = "usdpl-decky"
version = "0.1.0"
edition = "2021"
authors = ["Author <email@example.org>"]
description = "Backend functionality for usdpl-decky template"
license = "BSD-3-Clause"
repository = "https://git.ngni.us/NG-SD-Plugins/usdpl-decky-plugin-template"
keywords = ["template", "decky"]
readme = "../README.md"
[dependencies]
usdpl-back = { version = "1.0", features = ["blocking", "decky"], path = "../../../usdpl-back"}
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
nrpc = { version = "1.0", path = "../../../../nRPC/nrpc", default-features = false }
prost = "0.11"
tokio = { version = "1", features = ["sync", "rt"] }
sysfuss = { version = "0.3", features = ["derive"] }
# logging
log = "0.4"
simplelog = "0.12"
[build-dependencies]
usdpl-build = { version = "1.0", path = "../../../usdpl-build" }
[profile.release]
debug = false
strip = true
lto = true
codegen-units = 4

View file

@ -1,9 +1,6 @@
# we support images for building with a vanilla SteamOS base,
# or versions with ootb support for rust or go
# developers can also customize these images via this Dockerfile
#FROM ghcr.io/steamdeckhomebrew/holo-toolchain-rust:latest
#FROM ghcr.io/steamdeckhomebrew/holo-toolchain-go:latest
FROM ghcr.io/steamdeckhomebrew/holo-base:latest
FROM ghcr.io/steamdeckhomebrew/holo-toolchain-rust:latest
# for building Rust wasm frontend
RUN curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# entrypoint.sh should always be located in the backend folder
ENTRYPOINT [ "/backend/entrypoint.sh" ]

View file

@ -1,14 +0,0 @@
# This is the default target, which will be built when
# you invoke make
.PHONY: all
all: hello
# This rule tells make how to build hello from hello.cpp
hello:
mkdir -p ./out
gcc -o ./out/hello ./src/main.c
# This rule tells make to delete hello and hello.o
.PHONY: clean
clean:
rm -f hello

22
backend/build-docker.sh Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
echo "--- Rust version info ---"
rustup --version
rustc --version
cargo --version
echo "--- Building plugin backend ---"
cargo build --release
#mkdir -p out
cp target/release/fantastic-rs out/backend
echo "--- Building plugin frontend (wasm) ---"
# this only builds the webassembly part, while the actual frontend task builds the rest of it
cd /plugin/src/rust
./build.sh decky
cargo clean
cd /backend
echo " --- Cleaning up ---"
# remove root-owned target folder
cargo clean

9
backend/build.rs Normal file
View file

@ -0,0 +1,9 @@
fn main() {
//println!("CWD: {}", std::env::current_dir().unwrap().display());
usdpl_build::back::build([
format!("{}/protos/usdpl_template.proto", std::env::current_dir().unwrap().display())
].into_iter(),
[
format!("{}/protos/", std::env::current_dir().unwrap().display())
].into_iter())
}

9
backend/build.sh Executable file
View file

@ -0,0 +1,9 @@
#!/bin/bash
#cargo build --target x86_64-unknown-linux-musl --release
cargo build
mkdir -p ../bin
#cp ./target/x86_64-unknown-linux-musl/release/usdpl-decky ../bin/backend
cp ./target/debug/usdpl-decky ../bin/backend

4
backend/create_docker_img.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
# build docker container locally (for testing)
docker build -t fantastic_backend .

View file

@ -5,4 +5,4 @@ echo "Container's IP address: `awk 'END{print $1}' /etc/hosts`"
cd /backend
make
bash build-docker.sh

View file

@ -0,0 +1,55 @@
syntax = "proto3";
//
// This is a protobuf file. This is used by gRPC (and nRPC) to define the interface
// between the front-end and the back-end. Because the front-end is compiled to
// WebAssembly and has Javascript bindings, there are a few gotchas:
//
// - A message cannot contain non-Copy fields unless it only has one field;
// messages are turned into Rust structs if they have more than one field
// and all types bound to Javascript must be Copy
// - A single-field message will not be turned into a single-field struct;
// the field will be passed around directly instead.
// - A zero-field message will be turned into an empty tuple ()
// - JS bindings are similar, except with JS Objects
// - Values can be streamed back- to front-end with a Rust generator stream and a JS callback function
// - Values can be streamed front- to back-end with a JS generator function and a Rust stream consumer
//
// The generated Rust module and Typescript bindings should provide a good clue as to how to pass parameters
//
package usdpl_template;
// The most amazing nRPC service
service Template {
// Send back the exact same message as received
rpc echo (EchoMessage) returns (EchoMessage);
// Hello world
rpc hello (NameMessage) returns (HelloResponse);
// Service version info
rpc version (Empty) returns (VersionMessage);
// Service name
rpc name (Empty) returns (NameMessage);
}
// The request and response message for Echo
message EchoMessage {
string msg = 1;
}
message NameMessage {
string name = 1;
}
message HelloResponse {
string phrase = 1;
}
message Empty {}
message VersionMessage {
string version = 1;
}

7
backend/run_docker_img.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
# run docker container locally (for testing)
# assumes you're running in the backend/ dir of the project
docker run -i --entrypoint /backend/entrypoint.sh -v $PWD:/backend fantastic_backend
mkdir -p ../bin
cp ./out/backend ../bin

View file

@ -1,5 +0,0 @@
#include <stdio.h>
int main() {
printf("Hello World\n");
return 0;
}

35
backend/src/main.rs Normal file
View file

@ -0,0 +1,35 @@
//mod api;
//mod control;
//mod datastructs;
//mod json;
//mod sys;
mod service_impl;
use simplelog::{WriteLogger, LevelFilter};
#[allow(missing_docs)]
#[allow(dead_code)]
pub mod services {
include!(concat!(env!("OUT_DIR"), "/mod.rs"));
}
use services::usdpl_template::TemplateServer;
fn main() -> Result<(), ()> {
WriteLogger::init(
#[cfg(debug_assertions)]{LevelFilter::Debug},
#[cfg(not(debug_assertions))]{LevelFilter::Info},
Default::default(),
std::fs::File::create("/tmp/usdpl-template.log").unwrap()
).unwrap();
log::info!("Starting back-end ({} v{}):{}", service_impl::NAME, service_impl::VERSION, service_impl::PORT);
println!("Starting back-end ({} v{}):{}", service_impl::NAME, service_impl::VERSION, service_impl::PORT);
usdpl_back::Server::new(service_impl::PORT)
.register(TemplateServer::new(
service_impl::TemplateService::new()
))
.run_blocking()
.unwrap();
Ok(())
}

View file

@ -0,0 +1,38 @@
use crate::services::usdpl_template::*;
pub const PORT: u16 = 12340; // TODO: choose a unique port number
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub const NAME: &'static str = env!("CARGO_PKG_NAME");
pub struct TemplateService;
impl TemplateService {
pub fn new() -> Self {
Self
}
}
#[usdpl_back::nrpc::_helpers::async_trait::async_trait]
impl<'a> ITemplate<'a> for TemplateService {
async fn echo(&mut self, input: EchoMessage) -> Result<EchoMessage, Box<dyn std::error::Error + Send>> {
Ok(input)
}
async fn hello(&mut self, input: NameMessage) -> Result<HelloResponse, Box<dyn std::error::Error + Send>> {
Ok(HelloResponse {
phrase: format!("Hello {}!", input.name),
})
}
async fn version(&mut self, _: Empty) -> Result<VersionMessage, Box<dyn std::error::Error + Send>> {
Ok(VersionMessage {
version: VERSION.to_string(),
})
}
async fn name(&mut self, _: Empty) -> Result<NameMessage, Box<dyn std::error::Error + Send>> {
Ok(NameMessage {
name: NAME.to_string(),
})
}
}

View file

@ -12,10 +12,12 @@ Some basic migration helpers are available: `migrate_any`, `migrate_settings`, `
A logging facility `logger` is available which writes to the recommended location.
"""
__version__ = '0.1.0'
__version__ = '1.0.0'
import logging
from typing import Any
"""
Constants
"""
@ -50,7 +52,6 @@ Environment variable: `DECKY_USER`.
e.g.: `deck`
"""
DECKY_USER_HOME: str
"""
The home of the user where decky resides in.
@ -172,3 +173,12 @@ Logging
logger: logging.Logger
"""The main plugin logger writing to `DECKY_PLUGIN_LOG`."""
"""
Event handling
"""
# TODO better docstring im lazy
async def emit(event: str, *args: Any) -> None:
"""
Send an event to the frontend.
"""

69
main.py
View file

@ -1,41 +1,48 @@
import os
# The decky plugin module is located at decky-loader/plugin
# For easy intellisense checkout the decky-loader code one directory up
# or add the `decky-loader/plugin` path to `python.analysis.extraPaths` in `.vscode/settings.json`
import decky_plugin
# For easy intellisense checkout the decky-loader code repo
# and add the `decky-loader/plugin/imports` path to `python.analysis.extraPaths` in `.vscode/settings.json`
import pathlib
import subprocess
import asyncio
import os
HOME_DIR = str(pathlib.Path(os.getcwd()).parent.parent.resolve())
PARENT_DIR = str(pathlib.Path(__file__).parent.resolve())
LOG_LOCATION = "/tmp/usdpl-template.py.log"
# set up logging for Python back-end spawning
import logging
logging.basicConfig(
filename = LOG_LOCATION,
format = '%(asctime)s %(levelname)s %(message)s',
filemode = 'w',
force = True)
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logging.info(f"usdpl-decky-template main.py https://git.ngni.us/NG-SD-Plugins/usdpl-decky-plugin-template")
class Plugin:
# A normal method. It can be called from JavaScript using call_plugin_function("method_1", argument1, argument2)
async def add(self, left, right):
return left + right
backend_proc = None
# Asyncio-compatible long-running code, executed in a task when the plugin is loaded
async def _main(self):
decky_plugin.logger.info("Hello World!")
# startup back-end
self.backend_proc = subprocess.Popen(
[PARENT_DIR + "/bin/backend"],
env = dict(os.environ))
while True: # keep running in case Decky checks; very likely unnecessary
await asyncio.sleep(1)
# Function called first during the unload process, utilize this to handle your plugin being removed
async def _unload(self):
decky_plugin.logger.info("Goodbye World!")
pass
# Migrations that should be performed before entering `_main()`.
async def _migration(self):
decky_plugin.logger.info("Migrating")
# Here's a migration example for logs:
# - `~/.config/decky-template/template.log` will be migrated to `decky_plugin.DECKY_PLUGIN_LOG_DIR/template.log`
decky_plugin.migrate_logs(os.path.join(decky_plugin.DECKY_USER_HOME,
".config", "decky-template", "template.log"))
# Here's a migration example for settings:
# - `~/homebrew/settings/template.json` is migrated to `decky_plugin.DECKY_PLUGIN_SETTINGS_DIR/template.json`
# - `~/.config/decky-template/` all files and directories under this root are migrated to `decky_plugin.DECKY_PLUGIN_SETTINGS_DIR/`
decky_plugin.migrate_settings(
os.path.join(decky_plugin.DECKY_HOME, "settings", "template.json"),
os.path.join(decky_plugin.DECKY_USER_HOME, ".config", "decky-template"))
# Here's a migration example for runtime data:
# - `~/homebrew/template/` all files and directories under this root are migrated to `decky_plugin.DECKY_PLUGIN_RUNTIME_DIR/`
# - `~/.local/share/decky-template/` all files and directories under this root are migrated to `decky_plugin.DECKY_PLUGIN_RUNTIME_DIR/`
decky_plugin.migrate_runtime(
os.path.join(decky_plugin.DECKY_HOME, "template"),
os.path.join(decky_plugin.DECKY_USER_HOME, ".local", "share", "decky-template"))
# gracefully stop the back-end, but kill if it doesn't exit quickly enough
if self.backend_proc is not None:
self.backend_proc.terminate()
try:
self.backend_proc.wait(timeout=5) # 5 seconds timeout
except subprocess.TimeoutExpired:
self.backend_proc.kill()
self.backend_proc = None

View file

@ -2,8 +2,9 @@
"name": "decky-plugin-template",
"version": "0.0.1",
"description": "A template to quickly create decky plugins from scratch, based on TypeScript and webpack",
"type": "module",
"scripts": {
"build": "shx rm -rf dist && rollup -c",
"build": "rollup -c",
"watch": "rollup -c -w",
"test": "echo \"Error: no test specified\" && exit 1"
},
@ -18,29 +19,26 @@
"steam-deck",
"deck"
],
"author": "Jonas Dellinger <jonas@dellinger.dev>",
"author": "You <you@you.tld>",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/SteamDeckHomebrew/decky-plugin-template/issues"
},
"homepage": "https://github.com/SteamDeckHomebrew/decky-plugin-template#readme",
"devDependencies": {
"@rollup/plugin-commonjs": "^21.1.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-typescript": "^8.3.3",
"@types/react": "16.14.0",
"@types/webpack": "^5.28.0",
"rollup": "^2.77.1",
"rollup-plugin-import-assets": "^1.1.1",
"shx": "^0.3.4",
"tslib": "^2.4.0",
"typescript": "^4.7.4"
"@decky/rollup": "^1.0.1",
"@decky/ui": "^4.8.1",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@types/webpack": "^5.28.5",
"rollup": "^4.24.0",
"typescript": "^5.6.3"
},
"dependencies": {
"decky-frontend-lib": "^3.24.5",
"react-icons": "^4.4.0"
"@decky/api": "^1.1.2",
"react-icons": "^5.3.0",
"tslib": "^2.8.0",
"usdpl-template-wasm": "file:src/rust/pkg"
},
"pnpm": {
"peerDependencyRules": {

View file

@ -2,6 +2,7 @@
"name": "Example Plugin",
"author": "John Doe",
"flags": ["debug", "_root"],
"api_version": 1,
"publish": {
"tags": ["template", "root"],
"description": "Decky example plugin.",

File diff suppressed because it is too large Load diff

View file

View file

@ -1,14 +1,7 @@
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import typescript from '@rollup/plugin-typescript';
import { defineConfig } from 'rollup';
import importAssets from 'rollup-plugin-import-assets';
import deckyPlugin from "@decky/rollup";
import { name } from "./plugin.json";
export default defineConfig({
export default deckyPlugin({
// Add your extra Rollup options here
input: './src/index.tsx',
plugins: [
commonjs(),
@ -24,15 +17,15 @@ export default defineConfig({
})
],
context: 'window',
external: ["react", "react-dom", "decky-frontend-lib"],
external: ['react', 'react-dom', 'decky-frontend-lib'],
output: {
file: "dist/index.js",
file: 'dist/index.js',
globals: {
react: "SP_REACT",
"react-dom": "SP_REACTDOM",
"decky-frontend-lib": "DFL"
react: 'SP_REACT',
'react-dom': 'SP_REACTDOM',
'decky-frontend-lib': 'DFL',
},
format: 'iife',
exports: 'default',
},
});
})

View file

@ -1,105 +1,124 @@
import {
ButtonItem,
definePlugin,
DialogButton,
Menu,
MenuItem,
Navigation,
PanelSection,
PanelSectionRow,
ServerAPI,
showContextMenu,
staticClasses,
} from "decky-frontend-lib";
import { VFC } from "react";
Navigation,
staticClasses
} from "@decky/ui";
import {
addEventListener,
removeEventListener,
callable,
definePlugin,
toaster,
// routerHook
} from "@decky/api"
import { useState } from "react";
import { FaShip } from "react-icons/fa";
import logo from "../assets/logo.png";
import { init_embedded, target_usdpl } from "usdpl-template-wasm";
import { Template } from "usdpl-template-wasm";
// interface AddMethodArgs {
// left: number;
// right: number;
// }
const USDPL_PORT: number = 12340; // TODO: choose a unique port number
const Content: VFC<{ serverAPI: ServerAPI }> = ({serverAPI}) => {
// const [result, setResult] = useState<number | undefined>();
// Front-end connection to the nRPC service
var TEMPLATE_CLIENT: Template | undefined = undefined;
// const onClick = async () => {
// const result = await serverAPI.callPluginMethod<AddMethodArgs, number>(
// "add",
// {
// left: 2,
// right: 2,
// }
// );
// if (result.success) {
// setResult(result.result);
// }
// };
var name: string = "Unknown";
var version: string = "?.?.?";
// init service
(async function(){
await init_embedded()
FAN_CLIENT = new Fan(USDPL_PORT);
console.log("USDPL-TEMPLATE: USDPL front-end service started, framework: " + target_usdpl());
// add here any back-end calls to execute on startup
name = await TEMPLATE_CLIENT.name();
version = await TEMPLATE_CLIENT.version();
})();
// import logo from "../assets/logo.png";
function Content() {
const [result, setResult] = useState<number | undefined>();
/*const onClick = async () => {
const result = await add(Math.random(), Math.random());
setResult(result);
};*/
return (
<PanelSection title="Panel Section">
{/* Template TODO: add this functionality
<PanelSectionRow>
<ButtonItem
layout="below"
onClick={(e) =>
showContextMenu(
<Menu label="Menu" cancelText="CAAAANCEL" onCancel={() => {}}>
<MenuItem onSelected={() => {}}>Item #1</MenuItem>
<MenuItem onSelected={() => {}}>Item #2</MenuItem>
<MenuItem onSelected={() => {}}>Item #3</MenuItem>
</Menu>,
e.currentTarget ?? window
)
}
onClick={onClick}
>
Server says yolo
{result ?? "Add two numbers via Python"}
</ButtonItem>
</PanelSectionRow>*/}
<PanelSectionRow>
<Field
label={name}>
v{version}
</Field>
</PanelSectionRow>
<PanelSectionRow>
{/* <PanelSectionRow>
<div style={{ display: "flex", justifyContent: "center" }}>
<img src={logo} />
</div>
</PanelSectionRow>
</PanelSectionRow> */}
<PanelSectionRow>
{/*<PanelSectionRow>
<ButtonItem
layout="below"
onClick={() => {
Navigation.CloseSideMenus();
Navigation.Navigate("/decky-plugin-test");
Navigation.CloseSideMenus();
}}
>
Router
</ButtonItem>
</PanelSectionRow>
</PanelSectionRow>*/}
</PanelSection>
);
};
const DeckyPluginRouterTest: VFC = () => {
return (
<div style={{ marginTop: "50px", color: "white" }}>
Hello World!
<DialogButton onClick={() => Navigation.NavigateToLibraryTab()}>
Go to Library
</DialogButton>
</div>
);
};
export default definePlugin(() => {
console.log("Template plugin initializing, this is called once on frontend startup")
export default definePlugin((serverApi: ServerAPI) => {
serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, {
exact: true,
// serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, {
// exact: true,
// });
// Add an event listener to the "timer_event" event from the backend
const listener = addEventListener<[
test1: string,
test2: boolean,
test3: number
]>("timer_event", (test1, test2, test3) => {
console.log("Template got timer_event with:", test1, test2, test3)
toaster.toast({
title: "template got timer_event",
body: `${test1}, ${test2}, ${test3}`
});
});
return {
title: <div className={staticClasses.Title}>Example Plugin</div>,
content: <Content serverAPI={serverApi} />,
// The name shown in various decky menus
name: "Test Plugin",
// The element displayed at the top of your plugin's menu
titleView: <div className={staticClasses.Title}>Decky Example Plugin</div>,
// The content of your plugin's menu
content: <Content />,
// The icon displayed in the plugin list
icon: <FaShip />,
// The function triggered when your plugin unloads
onDismount() {
serverApi.routerHook.removeRoute("/decky-plugin-test");
console.log("Unloading")
// serverApi.routerHook.removeRoute("/decky-plugin-test");
},
};
});

974
src/rust/Cargo.lock generated Normal file
View file

@ -0,0 +1,974 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "beef"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytes"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if",
"wasm-bindgen",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "fastrand"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
name = "fixedbitset"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "futures"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-macro"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]]
name = "futures-sink"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "futures-task"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gloo-net"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ac9e8288ae2c632fa9f8657ac70bfe38a1530f345282d7ba66a1f70b72b7dc4"
dependencies = [
"futures-channel",
"futures-core",
"futures-sink",
"gloo-utils",
"http",
"js-sys",
"pin-project",
"serde",
"serde_json",
"thiserror",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "gloo-utils"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa"
dependencies = [
"js-sys",
"serde",
"serde_json",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "hashbrown"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "http"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "indexmap"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "logos"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1"
dependencies = [
"logos-derive",
]
[[package]]
name = "logos-codegen"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68"
dependencies = [
"beef",
"fnv",
"proc-macro2",
"quote",
"regex-syntax 0.6.29",
"syn 2.0.82",
]
[[package]]
name = "logos-derive"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e"
dependencies = [
"logos-codegen",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miette"
version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
dependencies = [
"miette-derive",
"once_cell",
"thiserror",
"unicode-width",
]
[[package]]
name = "miette-derive"
version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]]
name = "multimap"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
[[package]]
name = "nrpc"
version = "1.0.0"
dependencies = [
"bytes",
"futures",
"prost",
]
[[package]]
name = "nrpc-build"
version = "1.0.0"
dependencies = [
"nrpc",
"prettyplease 0.2.24",
"proc-macro2",
"prost-build",
"prost-types",
"protox",
"quote",
"syn 2.0.82",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "petgraph"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]]
name = "pin-project"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "prettyplease"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
dependencies = [
"proc-macro2",
"syn 1.0.109",
]
[[package]]
name = "prettyplease"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "910d41a655dac3b764f1ade94821093d3610248694320cd072303a8eedcf221d"
dependencies = [
"proc-macro2",
"syn 2.0.82",
]
[[package]]
name = "proc-macro2"
version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "prost"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-build"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
dependencies = [
"bytes",
"heck",
"itertools",
"lazy_static",
"log",
"multimap",
"petgraph",
"prettyplease 0.1.25",
"prost",
"prost-types",
"regex",
"syn 1.0.109",
"tempfile",
"which",
]
[[package]]
name = "prost-derive"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "prost-reflect"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b823de344848e011658ac981009100818b322421676740546f8b52ed5249428"
dependencies = [
"logos",
"miette",
"once_cell",
"prost",
"prost-types",
]
[[package]]
name = "prost-types"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13"
dependencies = [
"prost",
]
[[package]]
name = "protox"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24022a7eb88547eaba87a1db7954c9c4cb4a143565c4e8f2b7f3e76eed63db2d"
dependencies = [
"bytes",
"miette",
"prost",
"prost-reflect",
"prost-types",
"protox-parse",
"thiserror",
]
[[package]]
name = "protox-parse"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a2a651fa4466e67df6c967df5d7fc6cbffac89afc7b834f97ec49846c9c11"
dependencies = [
"logos",
"miette",
"prost-types",
"thiserror",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-automata"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustix"
version = "0.38.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]]
name = "serde_json"
version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
dependencies = [
"cfg-if",
"fastrand",
"once_cell",
"rustix",
"windows-sys 0.59.0",
]
[[package]]
name = "thiserror"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "usdpl-build"
version = "1.0.0"
dependencies = [
"nrpc-build",
"prettyplease 0.2.24",
"proc-macro2",
"prost-build",
"prost-types",
"quote",
"syn 2.0.82",
]
[[package]]
name = "usdpl-core"
version = "1.0.0"
dependencies = [
"base64",
]
[[package]]
name = "usdpl-front"
version = "1.0.0"
dependencies = [
"console_error_panic_hook",
"futures",
"futures-channel",
"gloo-net",
"js-sys",
"log",
"nrpc",
"prost",
"usdpl-core",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "usdpl-template-wasm"
version = "0.1.0"
dependencies = [
"nrpc",
"prost",
"usdpl-build",
"usdpl-front",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.82",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "web-sys"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

33
src/rust/Cargo.toml Normal file
View file

@ -0,0 +1,33 @@
[package]
name = "usdpl-template-wasm"
version = "0.1.0"
edition = "2021"
authors = ["Author <email@example.org>"]
description = "Backend functionality for usdpl-decky template"
license = "BSD-3-Clause"
repository = "https://git.ngni.us/NG-SD-Plugins/usdpl-decky-plugin-template"
keywords = ["template", "decky"]
readme = "../../README.md"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
usdpl-front = { features = ["decky"], version = "1.0", path = "../../../../usdpl-front" }
nrpc = { version = "1.0", path = "../../../../../nRPC/nrpc", default-features = false }
prost = "0.11"
[build-dependencies]
usdpl-build = { version = "1.0", path = "../../../../usdpl-build" }
[features]
debug = ["usdpl-front/debug"]
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"
debug = false
strip = true
lto = true
codegen-units = 4

15
src/rust/build.rs Normal file
View file

@ -0,0 +1,15 @@
fn main() {
println!("CWD: {}", std::env::current_dir().unwrap().display());
usdpl_build::front::build(
[format!(
"{}/../../backend/protos/usdpl_template.proto",
std::env::current_dir().unwrap().display()
)]
.into_iter(),
[format!(
"{}/../../backend/protos/",
std::env::current_dir().unwrap().display()
)]
.into_iter(),
)
}

19
src/rust/build.sh Executable file
View file

@ -0,0 +1,19 @@
#!/bin/bash
if [ -n "$1" ]; then
if [ "$1" == "--help" ]; then
echo "Usage:
$0 [decky|crankshaft|<nothing>]"
exit 0
elif [ "$1" == "decky" ]; then
echo "Building WASM module for decky framework"
RUSTFLAGS="--cfg aes_compact" wasm-pack build --target web --features decky,$2
else
echo "Unsupported plugin framework \`$1\`"
exit 1
fi
else
echo "WARNING: Building for any plugin framework, which may not work for every framework"
RUSTFLAGS="--cfg aes_compact" wasm-pack build --target web --features debug,$2
fi
python3 ./scripts/generate_embedded_wasm.py

View file

@ -0,0 +1,45 @@
import base64
if __name__ == "__main__":
print("Embedding WASM into js")
# assumption: current working directory (relative to this script) is ../
# assumption: release wasm binary at ./pkg/usdpl_bg.wasm
with open("./pkg/fantastic_wasm_bg.wasm", mode="rb") as infile:
with open("./pkg/fantastic_wasm.js", mode="ab") as outfile:
outfile.write("\n\n// USDPL customization\nconst encoded = \"".encode())
encoded = base64.b64encode(infile.read())
outfile.write(encoded)
outfile.write("\";\n\n".encode())
outfile.write(
"""function asciiToBinary(str) {
if (typeof atob === 'function') {
return atob(str)
} else {
return new Buffer(str, 'base64').toString('binary');
}
}
function decode() {
var binaryString = asciiToBinary(encoded);
var bytes = new Uint8Array(binaryString.length);
for (var i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return (async function() {
return new Response(bytes.buffer, {
status: 200,
statusText: 'OK',
headers: {
'Content-Type': 'application/wasm'
}
});
})();
}
export function init_embedded() {
return __wbg_init(decode())
}
""".encode())
with open("./pkg/fantastic_wasm.d.ts", "a") as outfile:
outfile.write("\n\n// USDPL customization\nexport function init_embedded();\n")
print("Done: Embedded WASM into js")

7
src/rust/src/lib.rs Normal file
View file

@ -0,0 +1,7 @@
#[allow(missing_docs)]
#[allow(dead_code)]
pub mod services {
include!(concat!(env!("OUT_DIR"), "/mod.rs"));
}
pub use usdpl_front;

View file

@ -15,9 +15,7 @@
"noImplicitThis": true,
"noImplicitAny": true,
"strict": true,
"suppressImplicitAnyIndexErrors": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true
"allowSyntheticDefaultImports": true
},
"include": ["src"],
"exclude": ["node_modules"]