From b18b08b8221d3ccf9acb8ab194ff9bf4a02f3f00 Mon Sep 17 00:00:00 2001 From: Kristian Ollikainen <14197772+DatCaptainHorse@users.noreply.github.com> Date: Sat, 1 Mar 2025 21:57:54 +0200 Subject: [PATCH 1/2] feat(runner): Rust updates and improvements (#196) ## Description - Updates to latest Rust 2024 :tada: - Make DataChannel messages ordered on nestri-server side - Bugfixes and code improvements + formatting ## Type of Change - [x] Bug fix (non-breaking change) - [x] New feature (non-breaking change) ## Checklist - [x] I have updated relevant documentation - [x] My code follows the project's coding style - [x] My changes generate no new warnings/errors --------- Co-authored-by: DatCaptainHorse Co-authored-by: Wanjohi --- .github/workflows/runner.yml | 2 + packages/server/Cargo.lock | 1049 +++------------------ packages/server/Cargo.toml | 2 +- packages/server/src/args/encoding_args.rs | 8 +- packages/server/src/enc_helper.rs | 17 +- packages/server/src/main.rs | 43 +- packages/server/src/nestrisink/imp.rs | 23 +- packages/server/src/nestrisink/mod.rs | 6 +- packages/server/src/proto.rs | 2 +- packages/server/src/proto/proto.rs | 68 +- packages/server/src/websocket.rs | 12 +- 11 files changed, 252 insertions(+), 980 deletions(-) diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml index a0ea6ec6..47717f69 100644 --- a/.github/workflows/runner.yml +++ b/.github/workflows/runner.yml @@ -7,6 +7,7 @@ on: paths: - "containers/runner.Containerfile" - "packages/scripts/**" + - "packages/server/**" - ".github/workflows/runner.yml" schedule: - cron: 7 0 * * 1,3,6 # Regularly to keep that build cache warm @@ -16,6 +17,7 @@ on: - "containers/runner.Containerfile" - ".github/workflows/runner.yml" - "packages/scripts/**" + - "packages/server/**" tags: - v*.*.* release: diff --git a/packages/server/Cargo.lock b/packages/server/Cargo.lock index ef2d22d7..eca99bbb 100644 --- a/packages/server/Cargo.lock +++ b/packages/server/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" [[package]] name = "arc-swap" @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.85" +version = "0.1.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" +checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" dependencies = [ "proc-macro2", "quote", @@ -201,9 +201,9 @@ dependencies = [ [[package]] name = "async-tungstenite" -version = "0.28.2" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c348fb0b6d132c596eca3dcd941df48fb597aafcb07a738ec41c004b087dc99" +checksum = "ef0f7efedeac57d9b26170f72965ecfd31473ca52ca7a64e925b0b6f5f079886" dependencies = [ "atomic-waker", "futures-core", @@ -215,7 +215,7 @@ dependencies = [ "pin-project-lite", "tokio", "tokio-native-tls", - "tungstenite 0.24.0", + "tungstenite 0.26.2", ] [[package]] @@ -236,53 +236,11 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "aws-config" -version = "1.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc47e70fc35d054c8fcd296d47a61711f043ac80534a10b4f741904f81e73a90" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sdk-sso", - "aws-sdk-ssooidc", - "aws-sdk-sts", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "hex", - "http 0.2.12", - "ring", - "time", - "tokio", - "tracing", - "url", - "zeroize", -] - -[[package]] -name = "aws-credential-types" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "zeroize", -] - [[package]] name = "aws-lc-rs" -version = "1.12.2" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b7ddaa2c56a367ad27a094ad8ef4faacf8a617c2575acb2ba88949df999ca" +checksum = "4cd755adf9707cf671e31d944a189be3deaaeee11c8bc1d669bb8022ac90fbd0" dependencies = [ "aws-lc-sys", "paste", @@ -291,9 +249,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2ddd3ada61a305e1d8bb6c005d1eaa7d14d903681edfc400406d523a9b491" +checksum = "0f9dd2e03ee80ca2822dd6ea431163d2ef259f2066a4d6ccaca6d9dcb386aa43" dependencies = [ "bindgen", "cc", @@ -303,308 +261,6 @@ dependencies = [ "paste", ] -[[package]] -name = "aws-runtime" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee7643696e7fdd74c10f9eb42848a87fe469d35eae9c3323f80aa98f350baac" -dependencies = [ - "aws-credential-types", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "http-body 0.4.6", - "once_cell", - "percent-encoding", - "pin-project-lite", - "tracing", - "uuid", -] - -[[package]] -name = "aws-sdk-kinesisvideo" -version = "1.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d4afed12d6a05c1b7a7e21d7de3395968aa6e738a9596fc7dbc8cbbefa76f45" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "http 0.2.12", - "once_cell", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-kinesisvideosignaling" -version = "1.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266cabc4a43b393a72fd7ed1a346a539d509cb24b0fb59fb6eb8c64cf68a3f2a" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "http 0.2.12", - "once_cell", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-sso" -version = "1.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54bab121fe1881a74c338c5f723d1592bf3b53167f80268a1274f404e1acc38" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "http 0.2.12", - "once_cell", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-ssooidc" -version = "1.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c8234fd024f7ac61c4e44ea008029bde934250f371efe7d4a39708397b1080c" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "http 0.2.12", - "once_cell", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-sts" -version = "1.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba60e1d519d6f23a9df712c04fdeadd7872ac911c84b2f62a8bda92e129b7962" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-query", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "http 0.2.12", - "once_cell", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sigv4" -version = "1.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "690118821e46967b3c4501d67d7d52dd75106a9c54cf36cefa1985cedbe94e05" -dependencies = [ - "aws-credential-types", - "aws-smithy-http", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "form_urlencoded", - "hex", - "hmac", - "http 0.2.12", - "http 1.2.0", - "once_cell", - "percent-encoding", - "sha2", - "time", - "tracing", -] - -[[package]] -name = "aws-smithy-async" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa59d1327d8b5053c54bf2eaae63bf629ba9e904434d0835a28ed3c0ed0a614e" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "aws-smithy-http" -version = "0.60.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7809c27ad8da6a6a68c454e651d4962479e81472aa19ae99e59f9aba1f9713cc" -dependencies = [ - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http-body 0.4.6", - "once_cell", - "percent-encoding", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-json" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "623a51127f24c30776c8b374295f2df78d92517386f77ba30773f15a30ce1422" -dependencies = [ - "aws-smithy-types", -] - -[[package]] -name = "aws-smithy-query" -version = "0.60.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" -dependencies = [ - "aws-smithy-types", - "urlencoding", -] - -[[package]] -name = "aws-smithy-runtime" -version = "1.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865f7050bbc7107a6c98a397a9fcd9413690c27fa718446967cf03b2d3ac517e" -dependencies = [ - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "fastrand", - "h2", - "http 0.2.12", - "http-body 0.4.6", - "http-body 1.0.1", - "httparse", - "hyper", - "hyper-rustls", - "once_cell", - "pin-project-lite", - "pin-utils", - "rustls 0.21.12", - "tokio", - "tracing", -] - -[[package]] -name = "aws-smithy-runtime-api" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" -dependencies = [ - "aws-smithy-async", - "aws-smithy-types", - "bytes", - "http 0.2.12", - "http 1.2.0", - "pin-project-lite", - "tokio", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-types" -version = "1.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28f6feb647fb5e0d5b50f0472c19a7db9462b74e2fec01bb0b44eedcc834e97" -dependencies = [ - "base64-simd", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.2.0", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "itoa", - "num-integer", - "pin-project-lite", - "pin-utils", - "ryu", - "serde", - "time", - "tokio", - "tokio-util", -] - -[[package]] -name = "aws-smithy-xml" -version = "0.60.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "aws-types" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0df5a18c4f951c645300d365fec53a61418bcf4650f604f85fe2a665bfaa0c2" -dependencies = [ - "aws-credential-types", - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "rustc_version", - "tracing", -] - [[package]] name = "backtrace" version = "0.3.74" @@ -638,16 +294,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" -dependencies = [ - "outref", - "vsimd", -] - [[package]] name = "base64ct" version = "1.6.0" @@ -730,19 +376,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" - -[[package]] -name = "bytes-utils" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" -dependencies = [ - "bytes", - "either", -] +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "cbc" @@ -755,9 +391,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.10" +version = "1.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" dependencies = [ "jobserver", "libc", @@ -844,9 +480,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.27" +version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" +checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" dependencies = [ "clap_builder", "clap_derive", @@ -854,9 +490,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.27" +version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" +checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" dependencies = [ "anstream", "anstyle", @@ -866,11 +502,11 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.24" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn", @@ -884,9 +520,9 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "cmake" -version = "0.1.53" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24a03c8b52922d68a1589ad61032f2c1aa5a8158d2aa0d93c6e9534944bbad6" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] @@ -1013,9 +649,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e60eed09d8c01d3cee5b7d30acb059b76614c918fa0f992e0dd6eeb10daad6f" +checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" [[package]] name = "der" @@ -1132,9 +768,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" @@ -1168,12 +804,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[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" @@ -1317,10 +947,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -1354,7 +982,7 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gio" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#7728982000b5ceec876560c9ae1011a1e75e52fa" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#c87867050de49f540b08bd26ae559983fc701a5b" dependencies = [ "futures-channel", "futures-core", @@ -1370,7 +998,7 @@ dependencies = [ [[package]] name = "gio-sys" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#7728982000b5ceec876560c9ae1011a1e75e52fa" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#c87867050de49f540b08bd26ae559983fc701a5b" dependencies = [ "glib-sys", "gobject-sys", @@ -1382,7 +1010,7 @@ dependencies = [ [[package]] name = "glib" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#7728982000b5ceec876560c9ae1011a1e75e52fa" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#c87867050de49f540b08bd26ae559983fc701a5b" dependencies = [ "bitflags 2.8.0", "futures-channel", @@ -1402,9 +1030,9 @@ dependencies = [ [[package]] name = "glib-macros" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#7728982000b5ceec876560c9ae1011a1e75e52fa" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#c87867050de49f540b08bd26ae559983fc701a5b" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro-crate", "proc-macro2", "quote", @@ -1414,7 +1042,7 @@ dependencies = [ [[package]] name = "glib-sys" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#7728982000b5ceec876560c9ae1011a1e75e52fa" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#c87867050de49f540b08bd26ae559983fc701a5b" dependencies = [ "libc", "system-deps", @@ -1429,7 +1057,7 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "gobject-sys" version = "0.21.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#7728982000b5ceec876560c9ae1011a1e75e52fa" +source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=main#c87867050de49f540b08bd26ae559983fc701a5b" dependencies = [ "glib-sys", "libc", @@ -1450,7 +1078,7 @@ dependencies = [ [[package]] name = "gst-plugin-version-helper" version = "0.8.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#5c7ab9b491f3d8be4a74f17a440288c81203e3ce" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#3d384bff62ab22f71272b8ae7cea565b160e443c" dependencies = [ "chrono", "toml_edit", @@ -1459,22 +1087,13 @@ dependencies = [ [[package]] name = "gst-plugin-webrtc" version = "0.14.0-alpha.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#5c7ab9b491f3d8be4a74f17a440288c81203e3ce" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#3d384bff62ab22f71272b8ae7cea565b160e443c" dependencies = [ "anyhow", "async-recursion", "async-tungstenite", - "aws-config", - "aws-credential-types", - "aws-sdk-kinesisvideo", - "aws-sdk-kinesisvideosignaling", - "aws-sigv4", - "aws-smithy-http", - "aws-smithy-types", - "aws-types", "chrono", "ctrlc", - "data-encoding", "fastrand", "futures", "gst-plugin-version-helper", @@ -1493,10 +1112,8 @@ dependencies = [ "http 1.2.0", "human_bytes", "itertools 0.14.0", - "livekit-api", - "livekit-protocol", "parse_link_header", - "rand 0.8.5", + "rand 0.9.0", "reqwest", "serde", "serde_json", @@ -1508,7 +1125,6 @@ dependencies = [ "tracing-log", "tracing-subscriber", "url", - "url-escape", "uuid", "warp", ] @@ -1516,7 +1132,7 @@ dependencies = [ [[package]] name = "gst-plugin-webrtc-signalling" version = "0.14.0-alpha.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#5c7ab9b491f3d8be4a74f17a440288c81203e3ce" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#3d384bff62ab22f71272b8ae7cea565b160e443c" dependencies = [ "anyhow", "async-tungstenite", @@ -1539,7 +1155,7 @@ dependencies = [ [[package]] name = "gst-plugin-webrtc-signalling-protocol" version = "0.14.0-alpha.1" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#5c7ab9b491f3d8be4a74f17a440288c81203e3ce" +source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs?branch=main#3d384bff62ab22f71272b8ae7cea565b160e443c" dependencies = [ "serde", "serde_json", @@ -1548,7 +1164,7 @@ dependencies = [ [[package]] name = "gstreamer" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "cfg-if", "futures-channel", @@ -1574,7 +1190,7 @@ dependencies = [ [[package]] name = "gstreamer-app" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "futures-core", "futures-sink", @@ -1588,7 +1204,7 @@ dependencies = [ [[package]] name = "gstreamer-app-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib-sys", "gstreamer-base-sys", @@ -1600,7 +1216,7 @@ dependencies = [ [[package]] name = "gstreamer-audio" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "cfg-if", "glib", @@ -1615,7 +1231,7 @@ dependencies = [ [[package]] name = "gstreamer-audio-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib-sys", "gobject-sys", @@ -1628,7 +1244,7 @@ dependencies = [ [[package]] name = "gstreamer-base" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "atomic_refcell", "cfg-if", @@ -1641,7 +1257,7 @@ dependencies = [ [[package]] name = "gstreamer-base-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib-sys", "gobject-sys", @@ -1653,7 +1269,7 @@ dependencies = [ [[package]] name = "gstreamer-net" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "gio", "glib", @@ -1664,7 +1280,7 @@ dependencies = [ [[package]] name = "gstreamer-net-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "gio-sys", "glib-sys", @@ -1676,7 +1292,7 @@ dependencies = [ [[package]] name = "gstreamer-rtp" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib", "gstreamer", @@ -1687,7 +1303,7 @@ dependencies = [ [[package]] name = "gstreamer-rtp-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib-sys", "gstreamer-base-sys", @@ -1699,7 +1315,7 @@ dependencies = [ [[package]] name = "gstreamer-sdp" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib", "gstreamer", @@ -1709,7 +1325,7 @@ dependencies = [ [[package]] name = "gstreamer-sdp-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib-sys", "gstreamer-sys", @@ -1720,7 +1336,7 @@ dependencies = [ [[package]] name = "gstreamer-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "cfg-if", "glib-sys", @@ -1732,7 +1348,7 @@ dependencies = [ [[package]] name = "gstreamer-utils" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "gstreamer", "gstreamer-app", @@ -1743,7 +1359,7 @@ dependencies = [ [[package]] name = "gstreamer-video" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "cfg-if", "futures-channel", @@ -1759,7 +1375,7 @@ dependencies = [ [[package]] name = "gstreamer-video-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib-sys", "gobject-sys", @@ -1772,7 +1388,7 @@ dependencies = [ [[package]] name = "gstreamer-webrtc" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib", "gstreamer", @@ -1784,7 +1400,7 @@ dependencies = [ [[package]] name = "gstreamer-webrtc-sys" version = "0.24.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#dee089ab4f2bb28d1e21accd7c5388beaf67e658" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs?branch=main#7851b9ced9542506968d62b33a54b027cf93ce8b" dependencies = [ "glib-sys", "gstreamer-sdp-sys", @@ -1842,12 +1458,6 @@ dependencies = [ "http 0.2.12", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -1920,29 +1530,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.2.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "pin-project-lite", -] - [[package]] name = "httparse" version = "1.10.0" @@ -1973,7 +1560,7 @@ dependencies = [ "futures-util", "h2", "http 0.2.12", - "http-body 0.4.6", + "http-body", "httparse", "httpdate", "itoa", @@ -1985,22 +1572,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper", - "log", - "rustls 0.21.12", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.24.1", -] - [[package]] name = "hyper-tls" version = "0.5.0" @@ -2188,9 +1759,9 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "block-padding", "generic-array", @@ -2228,15 +1799,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.12.1" @@ -2246,15 +1808,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -2289,19 +1842,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonwebtoken" -version = "9.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" -dependencies = [ - "base64 0.21.7", - "js-sys", - "ring", - "serde", - "serde_json", -] - [[package]] name = "kstring" version = "2.0.2" @@ -2351,45 +1891,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" -[[package]] -name = "livekit-api" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20c3fc3de5944ce6b5c8da4084cf828bbae7216671e32e83b767ce61feeb7e0" -dependencies = [ - "futures-util", - "jsonwebtoken", - "livekit-protocol", - "log", - "parking_lot", - "prost 0.12.6", - "reqwest", - "scopeguard", - "serde", - "sha2", - "thiserror 1.0.69", - "tokio", - "tokio-tungstenite 0.20.1", - "url", -] - -[[package]] -name = "livekit-protocol" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a1bd23257110be29d024d8d816adff70df18ea1d22ceb1aab6f3ad4aab0d523" -dependencies = [ - "futures-util", - "parking_lot", - "pbjson", - "pbjson-types", - "prost 0.12.6", - "prost-types 0.12.6", - "serde", - "thiserror 1.0.69", - "tokio", -] - [[package]] name = "lock_api" version = "0.4.12" @@ -2402,9 +1903,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.25" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "matchers" @@ -2464,9 +1965,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] @@ -2506,17 +2007,11 @@ dependencies = [ "version_check", ] -[[package]] -name = "multimap" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" - [[package]] name = "native-tls" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ "libc", "log", @@ -2542,15 +2037,15 @@ dependencies = [ "log", "num-derive", "num-traits", - "prost 0.13.4", - "prost-types 0.13.4", + "prost", + "prost-types", "rand 0.9.0", "regex", - "rustls 0.23.22", + "rustls 0.23.23", "serde", "serde_json", "tokio", - "tokio-tungstenite 0.26.1", + "tokio-tungstenite 0.26.2", "webrtc", ] @@ -2675,9 +2170,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "opaque-debug" @@ -2738,12 +2233,6 @@ dependencies = [ "paste", ] -[[package]] -name = "outref" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" - [[package]] name = "overload" version = "0.1.1" @@ -2764,9 +2253,9 @@ dependencies = [ [[package]] name = "p384" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" dependencies = [ "ecdsa", "elliptic-curve", @@ -2815,48 +2304,11 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pbjson" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1030c719b0ec2a2d25a5df729d6cff1acf3cc230bf766f4f97833591f7577b90" -dependencies = [ - "base64 0.21.7", - "serde", -] - -[[package]] -name = "pbjson-build" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735" -dependencies = [ - "heck 0.4.1", - "itertools 0.11.0", - "prost 0.12.6", - "prost-types 0.12.6", -] - -[[package]] -name = "pbjson-types" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f596653ba4ac51bdecbb4ef6773bc7f56042dc13927910de1684ad3d32aa12" -dependencies = [ - "bytes", - "chrono", - "pbjson", - "pbjson-build", - "prost 0.12.6", - "prost-build", - "serde", -] - [[package]] name = "pem" -version = "3.0.4" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" dependencies = [ "base64 0.22.1", "serde", @@ -2877,30 +2329,20 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[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.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" +checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" +checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" dependencies = [ "proc-macro2", "quote", @@ -3007,66 +2449,22 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", - "prost-derive 0.12.6", -] - -[[package]] -name = "prost" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" -dependencies = [ - "bytes", - "prost-derive 0.13.4", -] - -[[package]] -name = "prost-build" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" -dependencies = [ - "bytes", - "heck 0.5.0", - "itertools 0.12.1", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost 0.12.6", - "prost-types 0.12.6", - "regex", - "syn", - "tempfile", + "prost-derive", ] [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost-derive" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" -dependencies = [ - "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn", @@ -3074,20 +2472,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ - "prost 0.12.6", -] - -[[package]] -name = "prost-types" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" -dependencies = [ - "prost 0.13.4", + "prost", ] [[package]] @@ -3117,8 +2506,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.0", - "zerocopy 0.8.14", + "rand_core 0.9.2", + "zerocopy 0.8.20", ] [[package]] @@ -3138,7 +2527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.0", + "rand_core 0.9.2", ] [[package]] @@ -3152,12 +2541,12 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +checksum = "7a509b1a2ffbe92afab0e55c8fd99dea1c280e8171bd2d88682bb20bc41cbc2c" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.14", + "zerocopy 0.8.20", ] [[package]] @@ -3176,9 +2565,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" dependencies = [ "bitflags 2.8.0", ] @@ -3215,12 +2604,6 @@ dependencies = [ "regex-syntax 0.8.5", ] -[[package]] -name = "regex-lite" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" - [[package]] name = "regex-syntax" version = "0.6.29" @@ -3246,7 +2629,7 @@ dependencies = [ "futures-util", "h2", "http 0.2.12", - "http-body 0.4.6", + "http-body", "hyper", "hyper-tls", "ipnet", @@ -3285,15 +2668,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "da5349ae27d3887ca812fb375b45a4fbb36d8d12d2df394968cd86e35683fe73" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -3367,18 +2749,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.22.4" @@ -3388,39 +2758,27 @@ dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.22" +version = "0.23.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -3445,16 +2803,6 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.102.8" @@ -3500,16 +2848,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sdp" version = "0.7.0" @@ -3567,9 +2905,9 @@ checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] @@ -3585,9 +2923,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", @@ -3596,9 +2934,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" dependencies = [ "itoa", "memchr", @@ -3694,9 +3032,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "smol_str" @@ -3787,9 +3125,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.96" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -3841,7 +3179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005" dependencies = [ "cfg-expr", - "heck 0.5.0", + "heck", "pkg-config", "toml", "version-compare", @@ -3855,9 +3193,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.16.0" +version = "3.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" dependencies = [ "cfg-if", "fastrand", @@ -4018,16 +3356,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.25.0" @@ -4050,20 +3378,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" -dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite 0.20.1", -] - [[package]] name = "tokio-tungstenite" version = "0.21.0" @@ -4078,16 +3392,16 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4bf6fecd69fcdede0ec680aaf474cdab988f9de6bc73d3758f0160e3b7025a" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", "native-tls", "tokio", "tokio-native-tls", - "tungstenite 0.26.1", + "tungstenite 0.26.2", ] [[package]] @@ -4105,9 +3419,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", @@ -4126,9 +3440,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.23" +version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", @@ -4211,26 +3525,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 0.2.12", - "httparse", - "log", - "native-tls", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.21.0" @@ -4252,40 +3546,20 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.24.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ - "byteorder", "bytes", "data-encoding", "http 1.2.0", "httparse", "log", "native-tls", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "url", - "utf-8", -] - -[[package]] -name = "tungstenite" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413083a99c579593656008130e29255e54dcaae495be556cc26888f211648c24" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.2.0", - "httparse", - "log", - "native-tls", - "rand 0.8.5", + "rand 0.9.0", "sha1", "thiserror 2.0.11", + "url", "utf-8", ] @@ -4312,9 +3586,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicase" @@ -4324,9 +3598,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "universal-hash" @@ -4355,21 +3629,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "url-escape" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44e0ce4d1246d075ca5abec4b41d33e87a6054d08e2366b63205665e950db218" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "utf-8" version = "0.7.6" @@ -4396,11 +3655,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.12.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" +checksum = "93d59ca99a559661b96bf898d8fce28ed87935fd2bea9f05983c1464dd6c71b1" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.3.1", ] [[package]] @@ -4427,12 +3686,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" - [[package]] name = "waitgroup" version = "0.1.2" @@ -4475,7 +3728,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tokio-tungstenite 0.21.0", "tokio-util", "tower-service", @@ -4599,7 +3852,7 @@ dependencies = [ "ring", "rtcp", "rtp", - "rustls 0.23.22", + "rustls 0.23.23", "sdp", "serde", "serde_json", @@ -4661,7 +3914,7 @@ dependencies = [ "rand_core 0.6.4", "rcgen", "ring", - "rustls 0.23.22", + "rustls 0.23.23", "sec1", "serde", "sha1", @@ -4980,9 +4233,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e49d2d35d3fad69b39b94139037ecfb4f359f08958b9c11e7315ce770462419" +checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] @@ -5048,12 +4301,6 @@ dependencies = [ "time", ] -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - [[package]] name = "yasna" version = "0.5.2" @@ -5099,11 +4346,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.14" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" +checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c" dependencies = [ - "zerocopy-derive 0.8.14", + "zerocopy-derive 0.8.20", ] [[package]] @@ -5119,9 +4366,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.14" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700" dependencies = [ "proc-macro2", "quote", diff --git a/packages/server/Cargo.toml b/packages/server/Cargo.toml index 33ab5b49..1931a183 100644 --- a/packages/server/Cargo.toml +++ b/packages/server/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nestri-server" version = "0.1.0-alpha.2" -edition = "2021" +edition = "2024" [[bin]] name = "nestri-server" diff --git a/packages/server/src/args/encoding_args.rs b/packages/server/src/args/encoding_args.rs index 02b61a9a..1800e0ef 100644 --- a/packages/server/src/args/encoding_args.rs +++ b/packages/server/src/args/encoding_args.rs @@ -1,24 +1,24 @@ use std::ops::Deref; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct RateControlCQP { /// Constant Quantization Parameter (CQP) quality level pub quality: u32, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct RateControlVBR { /// Target bitrate in kbps pub target_bitrate: i32, /// Maximum bitrate in kbps pub max_bitrate: i32, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct RateControlCBR { /// Target bitrate in kbps pub target_bitrate: i32, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum RateControl { /// Constant Quantization Parameter CQP(RateControlCQP), diff --git a/packages/server/src/enc_helper.rs b/packages/server/src/enc_helper.rs index 27642619..98bb307d 100644 --- a/packages/server/src/enc_helper.rs +++ b/packages/server/src/enc_helper.rs @@ -1,4 +1,5 @@ -use crate::gpu::{self, get_gpu_by_card_path, get_gpus_by_vendor, GPUInfo}; +use crate::args::encoding_args::RateControl; +use crate::gpu::{self, GPUInfo, get_gpu_by_card_path, get_gpus_by_vendor}; use gst::prelude::*; #[derive(Debug, Eq, PartialEq, Clone)] @@ -245,7 +246,10 @@ pub fn encoder_gop_params(encoder: &VideoEncoderInfo, gop_size: u32) -> VideoEnc }) } -pub fn encoder_low_latency_params(encoder: &VideoEncoderInfo) -> VideoEncoderInfo { +pub fn encoder_low_latency_params( + encoder: &VideoEncoderInfo, + rate_control: &RateControl, +) -> VideoEncoderInfo { let mut encoder_optz = encoder_gop_params(encoder, 30); match encoder_optz.encoder_api { @@ -283,13 +287,8 @@ pub fn encoder_low_latency_params(encoder: &VideoEncoderInfo) -> VideoEncoderInf encoder_optz.set_parameter("tune", "zerolatency"); } "svtav1enc" => { - encoder_optz.set_parameter("preset", "12"); - let suffix = if encoder_optz.get_parameters_string().contains("cbr") { - ":pred-struct=1" - } else { - "" - }; - encoder_optz.set_parameter("parameters-string", &format!("lookahead=0{}", suffix)); + encoder_optz.set_parameter("preset", "11"); + encoder_optz.set_parameter("parameters-string", "lookahead=0"); } "av1enc" => { encoder_optz.set_parameter("usage-profile", "realtime"); diff --git a/packages/server/src/main.rs b/packages/server/src/main.rs index cdcd5822..4519ccaa 100644 --- a/packages/server/src/main.rs +++ b/packages/server/src/main.rs @@ -4,13 +4,13 @@ mod gpu; mod latency; mod messages; mod nestrisink; -mod websocket; mod proto; +mod websocket; use crate::args::encoding_args; +use crate::gpu::GPUVendor; use crate::nestrisink::NestriSignaller; use crate::websocket::NestriWebSocket; -use crate::gpu::GPUVendor; use futures_util::StreamExt; use gst::prelude::*; use gstrswebrtc::signaller::Signallable; @@ -55,12 +55,19 @@ fn handle_gpus(args: &args::Args) -> Option { gpu = filtered_gpus.get(args.device.gpu_index as usize).cloned(); } else { // get first GPU - gpu = filtered_gpus.into_iter().find(|g| *g.vendor() != GPUVendor::UNKNOWN); + gpu = filtered_gpus + .into_iter() + .find(|g| *g.vendor() != GPUVendor::UNKNOWN); } } if gpu.is_none() { - println!("No GPU found with the specified parameters: vendor='{}', name='{}', index='{}', card_path='{}'", - args.device.gpu_vendor, args.device.gpu_name, args.device.gpu_index, args.device.gpu_card_path); + println!( + "No GPU found with the specified parameters: vendor='{}', name='{}', index='{}', card_path='{}'", + args.device.gpu_vendor, + args.device.gpu_name, + args.device.gpu_index, + args.device.gpu_card_path + ); return None; } let gpu = gpu.unwrap(); @@ -83,7 +90,11 @@ fn handle_encoder_video(args: &args::Args) -> Option Option enc_helper::VideoEncoderInfo { - let mut optimized_encoder = enc_helper::encoder_low_latency_params(&video_encoder); + let mut optimized_encoder = + enc_helper::encoder_low_latency_params(&video_encoder, &args.encoding.video.rate_control); // Handle rate-control method match &args.encoding.video.rate_control { encoding_args::RateControl::CQP(cqp) => { @@ -240,14 +256,14 @@ async fn main() -> Result<(), Box> { &match &args.encoding.audio.rate_control { encoding_args::RateControl::CBR(cbr) => cbr.target_bitrate * 1000i32, encoding_args::RateControl::VBR(vbr) => vbr.target_bitrate * 1000i32, - _ => 128i32, + _ => 128000i32, }, ); /* Video */ // Video Source Element let video_source = gst::ElementFactory::make("waylanddisplaysrc").build()?; - video_source.set_property("render-node", &gpu.render_path()); + video_source.set_property_from_str("render-node", gpu.render_path()); // Caps Filter Element (resolution, fps) let caps_filter = gst::ElementFactory::make("capsfilter").build()?; @@ -289,6 +305,7 @@ async fn main() -> Result<(), Box> { let webrtcsink = BaseWebRTCSink::with_signaller(Signallable::from(signaller.clone())); webrtcsink.set_property_from_str("stun-server", "stun://stun.l.google.com:19302"); webrtcsink.set_property_from_str("congestion-control", "disabled"); + webrtcsink.set_property("do-retransmission", false); // Add elements to the pipeline pipeline.add_many(&[ @@ -343,7 +360,9 @@ async fn main() -> Result<(), Box> { } // Optimize latency of pipeline - video_source.sync_state_with_parent().expect("failed to sync with parent"); + video_source + .sync_state_with_parent() + .expect("failed to sync with parent"); video_source.set_property("do-timestamp", &true); audio_source.set_property("do-timestamp", &true); pipeline.set_property("latency", &0u64); diff --git a/packages/server/src/nestrisink/imp.rs b/packages/server/src/nestrisink/imp.rs index 71a195e9..1510d64b 100644 --- a/packages/server/src/nestrisink/imp.rs +++ b/packages/server/src/nestrisink/imp.rs @@ -1,6 +1,6 @@ use crate::messages::{ - decode_message_as, encode_message, AnswerType, JoinerType, MessageAnswer, MessageBase, - MessageICE, MessageJoin, MessageSDP, + AnswerType, JoinerType, MessageAnswer, MessageBase, MessageICE, MessageJoin, MessageSDP, + decode_message_as, encode_message, }; use crate::proto::proto::proto_input::InputType::{ KeyDown, KeyUp, MouseKeyDown, MouseKeyUp, MouseMove, MouseMoveAbs, MouseWheel, @@ -10,7 +10,7 @@ use crate::websocket::NestriWebSocket; use glib::subclass::prelude::*; use gst::glib; use gst::prelude::*; -use gst_webrtc::{gst_sdp, WebRTCSDPType, WebRTCSessionDescription}; +use gst_webrtc::{WebRTCSDPType, WebRTCSessionDescription, gst_sdp}; use gstrswebrtc::signaller::{Signallable, SignallableImpl}; use prost::Message; use std::collections::HashSet; @@ -144,8 +144,9 @@ impl Signaller { &[ &"nestri-data-channel", &gst::Structure::builder("config") - .field("ordered", &false) + .field("ordered", &true) .field("max-retransmits", &0u32) + .field("priority", "high") .build(), ], ), @@ -337,12 +338,14 @@ impl ObjectSubclass for Signaller { impl ObjectImpl for Signaller { fn properties() -> &'static [glib::ParamSpec] { static PROPS: LazyLock> = LazyLock::new(|| { - vec![glib::ParamSpecBoolean::builder("manual-sdp-munging") - .nick("Manual SDP munging") - .blurb("Whether the signaller manages SDP munging itself") - .default_value(false) - .read_only() - .build()] + vec![ + glib::ParamSpecBoolean::builder("manual-sdp-munging") + .nick("Manual SDP munging") + .blurb("Whether the signaller manages SDP munging itself") + .default_value(false) + .read_only() + .build(), + ] }); PROPS.as_ref() diff --git a/packages/server/src/nestrisink/mod.rs b/packages/server/src/nestrisink/mod.rs index f182a15f..62958bff 100644 --- a/packages/server/src/nestrisink/mod.rs +++ b/packages/server/src/nestrisink/mod.rs @@ -1,8 +1,8 @@ -use std::sync::Arc; +use crate::websocket::NestriWebSocket; use gst::glib; use gst::subclass::prelude::*; use gstrswebrtc::signaller::Signallable; -use crate::websocket::NestriWebSocket; +use std::sync::Arc; mod imp; @@ -22,4 +22,4 @@ impl Default for NestriSignaller { fn default() -> Self { panic!("Cannot create NestriSignaller without NestriWebSocket"); } -} \ No newline at end of file +} diff --git a/packages/server/src/proto.rs b/packages/server/src/proto.rs index 3e1772e2..febacec6 100644 --- a/packages/server/src/proto.rs +++ b/packages/server/src/proto.rs @@ -1 +1 @@ -pub mod proto; \ No newline at end of file +pub mod proto; diff --git a/packages/server/src/proto/proto.rs b/packages/server/src/proto/proto.rs index 3c1e3d56..5c070b86 100644 --- a/packages/server/src/proto/proto.rs +++ b/packages/server/src/proto/proto.rs @@ -3,17 +3,17 @@ #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoTimestampEntry { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub stage: ::prost::alloc::string::String, - #[prost(message, optional, tag="2")] + #[prost(message, optional, tag = "2")] pub time: ::core::option::Option<::prost_types::Timestamp>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoLatencyTracker { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub sequence_id: ::prost::alloc::string::String, - #[prost(message, repeated, tag="2")] + #[prost(message, repeated, tag = "2")] pub timestamps: ::prost::alloc::vec::Vec, } /// MouseMove message @@ -21,11 +21,11 @@ pub struct ProtoLatencyTracker { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoMouseMove { /// Fixed value "MouseMove" - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub r#type: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub x: i32, - #[prost(int32, tag="3")] + #[prost(int32, tag = "3")] pub y: i32, } /// MouseMoveAbs message @@ -33,11 +33,11 @@ pub struct ProtoMouseMove { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoMouseMoveAbs { /// Fixed value "MouseMoveAbs" - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub r#type: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub x: i32, - #[prost(int32, tag="3")] + #[prost(int32, tag = "3")] pub y: i32, } /// MouseWheel message @@ -45,11 +45,11 @@ pub struct ProtoMouseMoveAbs { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoMouseWheel { /// Fixed value "MouseWheel" - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub r#type: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub x: i32, - #[prost(int32, tag="3")] + #[prost(int32, tag = "3")] pub y: i32, } /// MouseKeyDown message @@ -57,9 +57,9 @@ pub struct ProtoMouseWheel { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoMouseKeyDown { /// Fixed value "MouseKeyDown" - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub r#type: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub key: i32, } /// MouseKeyUp message @@ -67,9 +67,9 @@ pub struct ProtoMouseKeyDown { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoMouseKeyUp { /// Fixed value "MouseKeyUp" - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub r#type: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub key: i32, } /// KeyDown message @@ -77,9 +77,9 @@ pub struct ProtoMouseKeyUp { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoKeyDown { /// Fixed value "KeyDown" - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub r#type: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub key: i32, } /// KeyUp message @@ -87,53 +87,53 @@ pub struct ProtoKeyDown { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoKeyUp { /// Fixed value "KeyUp" - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub r#type: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub key: i32, } /// Union of all Input types #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoInput { - #[prost(oneof="proto_input::InputType", tags="1, 2, 3, 4, 5, 6, 7")] + #[prost(oneof = "proto_input::InputType", tags = "1, 2, 3, 4, 5, 6, 7")] pub input_type: ::core::option::Option, } /// Nested message and enum types in `ProtoInput`. pub mod proto_input { #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] + #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum InputType { - #[prost(message, tag="1")] + #[prost(message, tag = "1")] MouseMove(super::ProtoMouseMove), - #[prost(message, tag="2")] + #[prost(message, tag = "2")] MouseMoveAbs(super::ProtoMouseMoveAbs), - #[prost(message, tag="3")] + #[prost(message, tag = "3")] MouseWheel(super::ProtoMouseWheel), - #[prost(message, tag="4")] + #[prost(message, tag = "4")] MouseKeyDown(super::ProtoMouseKeyDown), - #[prost(message, tag="5")] + #[prost(message, tag = "5")] MouseKeyUp(super::ProtoMouseKeyUp), - #[prost(message, tag="6")] + #[prost(message, tag = "6")] KeyDown(super::ProtoKeyDown), - #[prost(message, tag="7")] + #[prost(message, tag = "7")] KeyUp(super::ProtoKeyUp), } } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoMessageBase { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub payload_type: ::prost::alloc::string::String, - #[prost(message, optional, tag="2")] + #[prost(message, optional, tag = "2")] pub latency: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ProtoMessageInput { - #[prost(message, optional, tag="1")] + #[prost(message, optional, tag = "1")] pub message_base: ::core::option::Option, - #[prost(message, optional, tag="2")] + #[prost(message, optional, tag = "2")] pub data: ::core::option::Option, } // @@protoc_insertion_point(module) diff --git a/packages/server/src/websocket.rs b/packages/server/src/websocket.rs index e98d47a4..391eed0c 100644 --- a/packages/server/src/websocket.rs +++ b/packages/server/src/websocket.rs @@ -1,17 +1,17 @@ -use crate::messages::{decode_message, encode_message, MessageBase, MessageLog}; +use crate::messages::{MessageBase, MessageLog, decode_message, encode_message}; +use futures_util::StreamExt; use futures_util::sink::SinkExt; use futures_util::stream::{SplitSink, SplitStream}; -use futures_util::StreamExt; use log::{Level, Log, Metadata, Record}; use std::collections::HashMap; use std::error::Error; use std::sync::{Arc, RwLock}; use std::time::Duration; use tokio::net::TcpStream; -use tokio::sync::{mpsc, Mutex, Notify}; +use tokio::sync::{Mutex, Notify, mpsc}; use tokio::time::sleep; use tokio_tungstenite::tungstenite::{Message, Utf8Bytes}; -use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream}; +use tokio_tungstenite::{MaybeTlsStream, WebSocketStream, connect_async}; type Callback = Box; type WSRead = SplitStream>>; @@ -95,7 +95,9 @@ impl NestriWebSocket { while let Some(message_result) = ws_read.next().await { match message_result { Ok(message) => { - let data = message.into_text().expect("failed to turn message into text"); + let data = message + .into_text() + .expect("failed to turn message into text"); let base_message = match decode_message(data.to_string()) { Ok(base_message) => base_message, Err(e) => { From 178c612f0f5d9bcf21879e37db0a067b876c3d8f Mon Sep 17 00:00:00 2001 From: Wanjohi <71614375+wanjohiryan@users.noreply.github.com> Date: Sun, 2 Mar 2025 00:01:25 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9C=20fix:=20Make=20sure=20the=20d?= =?UTF-8?q?b=20uses=20the=20same=20name=20(#199)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This fixes the issue where Cloudflare fails ## Related Issues ## Type of Change - [x] Bug fix (non-breaking change) - [ ] New feature (non-breaking change) - [ ] Breaking change (fix or feature that changes existing functionality) - [ ] Documentation update - [ ] Other (please describe): ## Checklist - [x] I have updated relevant documentation - [x] My code follows the project's coding style - [x] My changes generate no new warnings/errors --- apps/www/package.json | 6 +- infra/database.ts | 2 +- infra:old/api.ts | 54 --- infra:old/auth.ts | 12 - infra:old/cluster.ts | 155 -------- infra:old/dns.ts | 9 - infra:old/party.ts | 33 -- infra:old/relay.ts | 179 --------- infra:old/secrets.ts | 13 - infra:old/ssh.ts | 19 - infra:old/stage.ts | 2 - infra:old/storage.ts | 4 - infra:old/vpc.ts | 103 ----- packages/core/src:old/actor.ts | 86 ---- packages/core/src:old/aws/client.ts | 90 ----- packages/core/src:old/common.ts | 7 - packages/core/src:old/database.ts | 12 - packages/core/src:old/email/index.ts | 45 --- packages/core/src:old/error.ts | 9 - packages/core/src:old/examples.ts | 75 ---- packages/core/src:old/game/index.ts | 151 ------- packages/core/src:old/instance/index.ts | 83 ---- packages/core/src:old/machine/index.ts | 232 ----------- packages/core/src:old/profile/index.ts | 412 -------------------- packages/core/src:old/session/index.ts | 251 ------------ packages/core/src:old/subscription/index.ts | 205 ---------- packages/core/src:old/task/index.ts | 331 ---------------- packages/core/src:old/team/index.ts | 164 -------- packages/core/src:old/types.ts | 17 - packages/core/src:old/user/index.ts | 37 -- packages/core/src:old/utils/fn.ts | 27 -- packages/core/src:old/utils/id.ts | 9 - packages/core/src:old/utils/index.ts | 2 - packages/ui/src/fonts.tsx | 4 - 34 files changed, 5 insertions(+), 2835 deletions(-) delete mode 100644 infra:old/api.ts delete mode 100644 infra:old/auth.ts delete mode 100644 infra:old/cluster.ts delete mode 100644 infra:old/dns.ts delete mode 100644 infra:old/party.ts delete mode 100644 infra:old/relay.ts delete mode 100644 infra:old/secrets.ts delete mode 100644 infra:old/ssh.ts delete mode 100644 infra:old/stage.ts delete mode 100644 infra:old/storage.ts delete mode 100644 infra:old/vpc.ts delete mode 100644 packages/core/src:old/actor.ts delete mode 100644 packages/core/src:old/aws/client.ts delete mode 100644 packages/core/src:old/common.ts delete mode 100644 packages/core/src:old/database.ts delete mode 100644 packages/core/src:old/email/index.ts delete mode 100644 packages/core/src:old/error.ts delete mode 100644 packages/core/src:old/examples.ts delete mode 100644 packages/core/src:old/game/index.ts delete mode 100644 packages/core/src:old/instance/index.ts delete mode 100644 packages/core/src:old/machine/index.ts delete mode 100644 packages/core/src:old/profile/index.ts delete mode 100644 packages/core/src:old/session/index.ts delete mode 100644 packages/core/src:old/subscription/index.ts delete mode 100644 packages/core/src:old/task/index.ts delete mode 100644 packages/core/src:old/team/index.ts delete mode 100644 packages/core/src:old/types.ts delete mode 100644 packages/core/src:old/user/index.ts delete mode 100644 packages/core/src:old/utils/fn.ts delete mode 100644 packages/core/src:old/utils/id.ts delete mode 100644 packages/core/src:old/utils/index.ts diff --git a/apps/www/package.json b/apps/www/package.json index 0e4a221f..3ec9d758 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -35,8 +35,10 @@ "@builder.io/qwik": "^1.8.0", "@builder.io/qwik-city": "^1.8.0", "@builder.io/qwik-react": "0.5.0", - "@fontsource-variable/bricolage-grotesque": "^5.1.1", - "@fontsource-variable/mona-sans": "^5.0.1", + "@fontsource/bricolage-grotesque": "^5.0.7", + "@fontsource/geist-mono": "^5.1.0", + "@fontsource/geist-sans": "^5.1.0", + "@fontsource/mona-sans": "^5.0.1", "@modular-forms/qwik": "^0.29.0", "@nestri/input": "*", "@nestri/libmoq": "*", diff --git a/infra/database.ts b/infra/database.ts index 44f0e0f6..83e99870 100644 --- a/infra/database.ts +++ b/infra/database.ts @@ -1,7 +1,7 @@ const dbProject = new neon.Project("Nestri", { historyRetentionSeconds: 86400, - // name:"Nestri" + name:"Nestri" }) const dbBranchId = $app.stage !== "production" ? diff --git a/infra:old/api.ts b/infra:old/api.ts deleted file mode 100644 index 2877b0c4..00000000 --- a/infra:old/api.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { authFingerprintKey } from "./auth"; -import { domain } from "./dns"; -import { secret } from "./secrets" -// import { party } from "./party" -import { gpuTaskDefinition, ecsCluster } from "./cluster"; - -export const urls = new sst.Linkable("Urls", { - properties: { - api: "https://api." + domain, - auth: "https://auth." + domain, - }, -}); - -export const kv = new sst.cloudflare.Kv("CloudflareAuthKV") - -export const auth = new sst.cloudflare.Worker("Auth", { - link: [ - kv, - urls, - authFingerprintKey, - secret.InstantAdminToken, - secret.InstantAppId, - secret.LoopsApiKey, - secret.GithubClientID, - secret.GithubClientSecret, - secret.DiscordClientID, - secret.DiscordClientSecret, - ], - handler: "./packages/functions/src/auth.ts", - url: true, - domain: "auth." + domain -}); - -export const api = new sst.cloudflare.Worker("Api", { - link: [ - urls, - ecsCluster, - gpuTaskDefinition, - authFingerprintKey, - secret.LoopsApiKey, - secret.InstantAppId, - secret.AwsAccessKey, - secret.AwsSecretKey, - secret.InstantAdminToken, - ], - url: true, - handler: "./packages/functions/src/api/index.ts", - domain: "api." + domain -}) - -export const outputs = { - auth: auth.url, - api: api.url -} \ No newline at end of file diff --git a/infra:old/auth.ts b/infra:old/auth.ts deleted file mode 100644 index b9c9fad5..00000000 --- a/infra:old/auth.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const authFingerprintKey = new random.RandomString( - "AuthFingerprintKey", - { - length: 32, - }, -); - -sst.Linkable.wrap(random.RandomString, (resource) => ({ - properties: { - value: resource.result, - }, -})); \ No newline at end of file diff --git a/infra:old/cluster.ts b/infra:old/cluster.ts deleted file mode 100644 index 8916b7f6..00000000 --- a/infra:old/cluster.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { sshKey } from "./ssh"; -import { authFingerprintKey } from "./auth"; - -export const ecsCluster = new aws.ecs.Cluster("NestriGPUCluster", { - name: "NestriGPUCluster", -}); - -const ecsInstanceRole = new aws.iam.Role("NestriGPUInstanceRole", { - name: "GPUAssumeRoleProd", - assumeRolePolicy: JSON.stringify({ - Version: "2012-10-17", - Statement: [{ - Action: "sts:AssumeRole", - Principal: { - Service: "ec2.amazonaws.com", - }, - Effect: "Allow", - Sid: "", - }], - }), -}); - -new aws.iam.RolePolicyAttachment("NestriGPUInstancePolicyAttachment", { - role: ecsInstanceRole.name, - policyArn: "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role", -}); - -const ecsInstanceProfile = new aws.iam.InstanceProfile("NestriGPUInstanceProfile", { - role: ecsInstanceRole.name, -}); - -// const server = new aws.ec2.Instance("NestriGPU", { -// instanceType: aws.ec2.InstanceType.G4dn_XLarge, -// ami: "ami-046a6af96ef510bb6",//Fedora cloud -// keyName: sshKey.keyName, -// instanceMarketOptions: { -// marketType: "spot", -// spotOptions: { -// maxPrice: "0.2", -// spotInstanceType: "persistent", -// instanceInterruptionBehavior: "stop" -// }, -// }, -// iamInstanceProfile: ecsInstanceProfile, -// }); - -const logGroup = new aws.cloudwatch.LogGroup("NestriGPULogGroup", { - name: "/ecs/nestri-gpu-prod", - retentionInDays: 7, -}); - -// Create a Task Definition for the ECS service to test it -export const gpuTaskDefinition = new aws.ecs.TaskDefinition("NestriGPUTask", { - family: "NestriGPUTaskProd", - requiresCompatibilities: ["EC2"], - volumes: [ - { - name: "host", - hostPath: "/mnt/" - // efsVolumeConfiguration: { - // fileSystemId: storage.id, - // authorizationConfig: { accessPointId: storage.accessPoint }, - // transitEncryption: "ENABLED", - // } - } - ], - containerDefinitions: authFingerprintKey.result.apply(v => JSON.stringify([{ - "essential": true, - "name": "nestri", - "memory": 1024, - "cpu": 200, - "gpu": 1, - "image": "ghcr.io/nestrilabs/nestri/runner:nightly", - "environment": [ - { - "name": "RESOLUTION", - "value": "1920x1080" - }, - { - "name": "AUTH_FINGERPRINT", - "value": v - }, - { - "name": "FRAMERATE", - "value": "60" - }, - { - "name": "NESTRI_ROOM", - "value": "aws-testing" - }, - { - "name": "RELAY_URL", - "value": "https://relay.dathorse.com" - }, - { - "name": "NESTRI_PARAMS", - "value": "--verbose=true --video-codec=h264 --video-bitrate=4000 --video-bitrate-max=6000 --gpu-card-path=/dev/dri/card0" - }, - ], - "mountPoints": [{ "containerPath": "/home/nestri", "sourceVolume": "host" }], - "disableNetworking": false, - "linuxParameter": { - "sharedMemorySize": 5120 - }, - "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-group": "/ecs/nestri-gpu-prod", - "awslogs-region": "us-east-1", - "awslogs-stream-prefix": "nestri-gpu-task" - } - } - }])) -}); - -sst.Linkable.wrap(aws.ecs.TaskDefinition, (resource) => ({ - properties: { - value: resource.arn, - }, -})); - -sst.Linkable.wrap(aws.ecs.Cluster, (resource) => ({ - properties: { - value: resource.arn, - }, -})); - -// userData: $interpolate`#!/bin/bash -// sudo rm /etc/sysconfig/docker -// echo DAEMON_MAXFILES=1048576 | sudo tee -a /etc/sysconfig/docker -// echo DAEMON_PIDFILE_TIMEOUT=10 | sud o tee -a /etc/sysconfig/docker -// echo OPTIONS="--default-ulimit nofile=32768:65536" | sudo tee -a /etc/sysconfig/docker -// sudo tee "/etc/docker/daemon.json" > /dev/null < party <-websocket-> container -// The container is it's own this, and can listen to Websocket connections to start or stop a Steam Game - -// import { authFingerprintKey } from "./auth"; -// import { ecsCluster, gpuTaskDefinition } from "./cluster"; - -// export const party = new sst.aws.Realtime("Party", { -// authorizer: "packages/functions/src/party/authorizer.handler" -// }); - -// export const partyFn = new sst.aws.Function("NestriPartyFn", { -// handler: "packages/functions/src/party/create.handler", -// // link: [queue], -// link: [authFingerprintKey], -// environment: { -// TASK_DEFINITION: gpuTaskDefinition.arn, -// // AUTH_FINGERPRINT: authFingerprintKey.result, -// ECS_CLUSTER: ecsCluster.arn, -// }, -// permissions: [ -// { -// effect: "allow", -// actions: ["ecs:RunTask"], -// resources: [gpuTaskDefinition.arn] -// } -// ], -// url: true, -// }); - -// export const outputs = { -// partyFunction: partyFn.url -// } \ No newline at end of file diff --git a/infra:old/relay.ts b/infra:old/relay.ts deleted file mode 100644 index e6f6e435..00000000 --- a/infra:old/relay.ts +++ /dev/null @@ -1,179 +0,0 @@ -// const vpc = new sst.aws.Vpc("NestriRelayVpc", { az: 2 }) -// import { subnet1, subnet2, securityGroup } from "./vpc" - -// const taskExecutionRole = new aws.iam.Role('NestriRelayExecutionRole', { -// assumeRolePolicy: JSON.stringify({ -// Version: '2012-10-17', -// Statement: [ -// { -// Effect: 'Allow', -// Principal: { -// Service: 'ecs-tasks.amazonaws.com', -// }, -// Action: 'sts:AssumeRole', -// }, -// ], -// }), -// }); - -// const taskRole = new aws.iam.Role('NestriRelayTaskRole', { -// assumeRolePolicy: JSON.stringify({ -// Version: '2012-10-17', -// Statement: [ -// { -// Effect: 'Allow', -// Principal: { -// Service: 'ecs-tasks.amazonaws.com', -// }, -// Action: 'sts:AssumeRole', -// }, -// ], -// }), -// }); - -// new aws.cloudwatch.LogGroup('NestriRelayLogGroup', { -// name: '/ecs/nestri-relay', -// retentionInDays: 7, -// }); - -// new aws.iam.RolePolicyAttachment('NestriRelayExecutionRoleAttachment', { -// policyArn: 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy', -// role: taskRole, -// }); - -// const logPolicy = new aws.iam.Policy('NestriRelayLogPolicy', { -// policy: JSON.stringify({ -// Version: '2012-10-17', -// Statement: [ -// { -// Effect: 'Allow', -// Action: ['logs:CreateLogStream', 'logs:PutLogEvents'], -// Resource: 'arn:aws:logs:*:*:*', -// }, -// ], -// }), -// }); - -// new aws.iam.RolePolicyAttachment('NestriRelayTaskRoleAttachment', { -// policyArn: logPolicy.arn, -// role: taskExecutionRole, -// }); - -// const taskDefinition = new aws.ecs.TaskDefinition("NestriRelayTask", { -// family: "NestriRelay", -// cpu: "1024", -// memory: "2048", -// networkMode: "awsvpc", -// taskRoleArn: taskRole.arn, -// requiresCompatibilities: ["FARGATE"], -// executionRoleArn: taskExecutionRole.arn, -// containerDefinitions: JSON.stringify([{ -// name: "nestri-relay", -// essential: true, -// memory: 2048, -// image: "ghcr.io/nestrilabs/nestri/relay:nightly", -// portMappings: [ -// // HTTP port -// { -// protocol: "tcp", -// hostPort: 80, -// containerPort: 80, -// }, -// // UDP port range (1,000 ports) -// { -// containerPortRange: "10000-11000", -// protocol: "udp", -// }, -// ], -// "environment": [ -// { -// name: "ENDPOINT_PORT", -// value: "80" -// }, -// ], -// logConfiguration: { -// logDriver: 'awslogs', -// options: { -// 'awslogs-group': '/ecs/nestri-relay', -// 'awslogs-region': 'us-east-1', -// 'awslogs-stream-prefix': 'ecs', -// }, -// }, -// }]), -// }); - -// const relayCluster = new aws.ecs.Cluster('NestriRelay'); - -// new aws.ecs.Service('NestriRelayService', { -// name: 'NestriRelayService', -// cluster: relayCluster.arn, -// desiredCount: 1, -// launchType: 'FARGATE', -// taskDefinition: taskDefinition.arn, -// deploymentCircuitBreaker: { -// enable: true, -// rollback: true, -// }, -// enableExecuteCommand: true, -// networkConfiguration: { -// assignPublicIp: true, -// subnets: [subnet1.id, subnet2.id], -// securityGroups: [securityGroup.id], -// }, -// }); - -//FIXME: I cannot create Global Accelerators (Something to do with Quotas - Yet my account is fine) -// const usWest2 = new aws.Provider("GlobalAccelerator", { region: aws.Region.USWest2 }) - -// const accelerator = new aws.globalaccelerator.Accelerator('Accelerator', { -// name: 'NestriRelayAccelerator', -// enabled: true, -// ipAddressType: 'IPV4', -// }, { provider: usWest2 }); - -// const httpListener = new aws.globalaccelerator.Listener('TcpListener', { -// acceleratorArn: accelerator.id, -// clientAffinity: 'SOURCE_IP', -// protocol: 'TCP', -// portRanges: [{ -// fromPort: 80, -// toPort: 80, -// }], -// }, { provider: usWest2 }); - -// const udpListener = new aws.globalaccelerator.Listener('UdpListener', { -// acceleratorArn: accelerator.id, -// clientAffinity: 'SOURCE_IP', -// protocol: 'UDP', -// portRanges: [{ -// fromPort: 10000, -// toPort: 11000, -// }], -// }, { provider: usWest2 }); - -// new aws.globalaccelerator.EndpointGroup('TcpRelay', { -// listenerArn: httpListener.id, -// // healthCheckPath: '/', -// endpointGroupRegion: aws.Region.USEast1, -// endpointConfigurations: [{ -// clientIpPreservationEnabled: true, -// endpointId: subnet1.id, //vpc.publicSubnets[0].apply(i => i), -// weight: 100, -// }], -// }, { provider: usWest2 }); - -// new aws.globalaccelerator.EndpointGroup('UdpRelay', { -// listenerArn: udpListener.id, -// // healthCheckPort: 80, -// // healthCheckPath: "/", -// endpointGroupRegion: aws.Region.USEast1, -// endpointConfigurations: [{ -// clientIpPreservationEnabled: true, -// endpointId: subnet1.id,//vpc.publicSubnets[0].apply(i => i), -// weight: 100, -// }], -// }, { provider: usWest2 }); - -// export const outputs = { -// relay: accelerator.dnsName -// } \ No newline at end of file diff --git a/infra:old/secrets.ts b/infra:old/secrets.ts deleted file mode 100644 index 5b564072..00000000 --- a/infra:old/secrets.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const secret = { - LoopsApiKey: new sst.Secret("LoopsApiKey"), - InstantAppId: new sst.Secret("InstantAppId"), - AwsSecretKey: new sst.Secret("AwsSecretKey"), - AwsAccessKey: new sst.Secret("AwsAccessKey"), - GithubClientID: new sst.Secret("GithubClientID"), - DiscordClientID: new sst.Secret("DiscordClientID"), - GithubClientSecret: new sst.Secret("GithubClientSecret"), - InstantAdminToken: new sst.Secret("InstantAdminToken"), - DiscordClientSecret: new sst.Secret("DiscordClientSecret"), - }; - - export const allSecrets = Object.values(secret); \ No newline at end of file diff --git a/infra:old/ssh.ts b/infra:old/ssh.ts deleted file mode 100644 index 9a809291..00000000 --- a/infra:old/ssh.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { resolve } from "path"; -import { writeFileSync } from "fs"; - -export const privateKey = new tls.PrivateKey("NestriGPUPrivateKey", { - algorithm: "RSA", - rsaBits: 4096, -}); - -// Just in case you want to SSH -export const sshKey = new aws.ec2.KeyPair("NestriGPUKey", { - keyName: "NestriGPUKeyProd", - publicKey: privateKey.publicKeyOpenssh -}) - -export const keyPath = privateKey.privateKeyOpenssh.apply((key) => { - const path = "key_ssh"; - writeFileSync(path, key, { mode: 0o600 }); - return resolve(path); -}); diff --git a/infra:old/stage.ts b/infra:old/stage.ts deleted file mode 100644 index 3f4f5335..00000000 --- a/infra:old/stage.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const isPermanentStage = - $app.stage === "production" || $app.stage === "dev"; \ No newline at end of file diff --git a/infra:old/storage.ts b/infra:old/storage.ts deleted file mode 100644 index 0b5e92f6..00000000 --- a/infra:old/storage.ts +++ /dev/null @@ -1,4 +0,0 @@ -// export const vpc = new sst.aws.Vpc("Vpc") - -// export const storage = new sst.aws.Efs("GameStorage",{ vpc }) -// // \ No newline at end of file diff --git a/infra:old/vpc.ts b/infra:old/vpc.ts deleted file mode 100644 index bff06b74..00000000 --- a/infra:old/vpc.ts +++ /dev/null @@ -1,103 +0,0 @@ -// export const vpc = new aws.ec2.Vpc('NestriVpc', { -// cidrBlock: '172.16.0.0/16', -// }); - -// export const subnet1 = new aws.ec2.Subnet('NestriSubnet1', { -// vpcId: vpc.id, -// cidrBlock: '172.16.1.0/24', -// // cidrBlock: '110.0.12.0/22', -// availabilityZone: 'us-east-1a', -// }); - -// export const subnet2 = new aws.ec2.Subnet('NestriSubnet2', { -// vpcId: vpc.id, -// cidrBlock: '172.16.2.0/24', -// // cidrBlock: '10.0.20.0/22', -// availabilityZone: 'us-east-1b', -// }); - -// const internetGateway = new aws.ec2.InternetGateway('NestriInternetGateway', { -// vpcId: vpc.id, -// }); - -// const routeTable = new aws.ec2.RouteTable('NestriRouteTable', { -// vpcId: vpc.id, -// routes: [ -// { -// cidrBlock: '0.0.0.0/0', -// gatewayId: internetGateway.id, -// }, -// ], -// }); - -// new aws.ec2.RouteTableAssociation('NestriSubnet1RouteTable', { -// subnetId: subnet1.id, -// routeTableId: routeTable.id, -// }); - -// new aws.ec2.RouteTableAssociation('NestriSubnet2RouteTable', { -// subnetId: subnet2.id, -// routeTableId: routeTable.id, -// }); - -// // const vpc = new sst.aws.Vpc("NestriRelayVpc") - -// export const securityGroup = new aws.ec2.SecurityGroup("NestriSecurityGroup", { -// vpcId: vpc.id, -// description: "Managed thru SST", -// ingress: [ -// { -// protocol: "tcp", -// fromPort: 80, -// toPort: 80, -// cidrBlocks: ["0.0.0.0/0"], -// }, -// { -// protocol: "udp", -// fromPort: 10000, -// toPort: 20000, -// cidrBlocks: ["0.0.0.0/0"], -// }, -// ], -// egress: [ -// { -// protocol: "-1", -// cidrBlocks: ["0.0.0.0/0"], -// fromPort: 0, -// toPort: 0 -// } -// ] -// }); - -// const loadBalancer = new aws.lb.LoadBalancer('NestriVpcLoadBalancer', { -// name: 'NestriVpcLoadBalancer', -// internal: false, -// securityGroups: [securityGroup.id], -// subnets: vpc.publicSubnets -// }); - -// const targetGroup = new aws.lb.TargetGroup('NestriVpcTargetGroup', { -// name: 'NestriVpcTargetGroup', -// port: 80, -// protocol: 'HTTP', -// targetType: 'ip', -// vpcId: vpc.id, -// healthCheck: { -// path: '/', -// protocol: 'HTTP', -// }, -// }); - -// new aws.lb.Listener('NestriVpcLoadBalancerListener', { -// loadBalancerArn: loadBalancer.arn, -// port: 80, -// protocol: 'HTTP', -// defaultActions: [ -// { -// type: 'forward', -// targetGroupArn: targetGroup.arn, -// }, -// ], -// }); - -// // export const subnets = [subnet1, subnet2] diff --git a/packages/core/src:old/actor.ts b/packages/core/src:old/actor.ts deleted file mode 100644 index 6fd4296a..00000000 --- a/packages/core/src:old/actor.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { createContext } from "../src/context"; -import { VisibleError } from "./error"; - -export interface UserActor { - type: "user"; - properties: { - accessToken: string; - userID: string; - auth?: - | { - type: "personal"; - token: string; - } - | { - type: "oauth"; - clientID: string; - }; - }; -} - -export interface DeviceActor { - type: "device"; - properties: { - teamSlug: string; - hostname: string; - auth?: - | { - type: "personal"; - token: string; - } - | { - type: "oauth"; - clientID: string; - }; - }; -} - -export interface PublicActor { - type: "public"; - properties: {}; -} - -type Actor = UserActor | PublicActor | DeviceActor; -export const ActorContext = createContext(); - -export function useCurrentUser() { - const actor = ActorContext.use(); - if (actor.type === "user") return { - id:actor.properties.userID, - token: actor.properties.accessToken, - }; - - throw new VisibleError( - "auth", - "unauthorized", - `You don't have permission to access this resource`, - ); -} - -export function useCurrentDevice() { - const actor = ActorContext.use(); - if (actor.type === "device") return { - hostname:actor.properties.hostname, - teamSlug: actor.properties.teamSlug - }; - throw new VisibleError( - "auth", - "unauthorized", - `You don't have permission to access this resource`, - ); -} - -export function useActor() { - try { - return ActorContext.use(); - } catch { - return { type: "public", properties: {} } as PublicActor; - } - } - - export function assertActor(type: T) { - const actor = useActor(); - if (actor.type !== type) - throw new VisibleError("auth", "actor.invalid", `Actor is not "${type}"`); - return actor as Extract; - } \ No newline at end of file diff --git a/packages/core/src:old/aws/client.ts b/packages/core/src:old/aws/client.ts deleted file mode 100644 index 21e528ec..00000000 --- a/packages/core/src:old/aws/client.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { z } from "zod" -import { Resource } from "sst"; -import { doubleFn, fn } from "../utils"; -import { AwsClient } from "aws4fetch"; -import { DescribeTasksCommandOutput, StopTaskCommandOutput, type RunTaskCommandOutput } from "@aws-sdk/client-ecs"; - - -export module Aws { - export const client = async () => { - return new AwsClient({ - accessKeyId: Resource.AwsAccessKey.value, - secretAccessKey: Resource.AwsSecretKey.value, - region: "us-east-1", - }); - } - - export const EcsRunTask = fn(z.object({ - cluster: z.string(), - count: z.number(), - taskDefinition: z.string(), - launchType: z.enum(["EC2", "FARGATE"]), - overrides: z.object({ - containerOverrides: z.object({ - name: z.string(), - environment: z.object({ - name: z.string(), - value: z.string().or(z.number()) - }).array() - }).array() - }) - }), async (body) => { - - const c = await client(); - - const url = new URL(`https://ecs.${c.region}.amazonaws.com/`) - - const res = await c.fetch(url, { - method: "POST", - headers: { - "X-Amz-Target": "AmazonEC2ContainerServiceV20141113.RunTask", - "Content-Type": "application/x-amz-json-1.1", - }, - body: JSON.stringify(body) - }) - - return await res.json() as RunTaskCommandOutput - }) - - export const EcsDescribeTasks = fn(z.object({ tasks: z.string().array(), cluster: z.string() }), async (body) => { - const c = await client(); - - const url = new URL(`https://ecs.${c.region}.amazonaws.com/`) - - const res = await c.fetch(url, { - method: "POST", - headers: { - "X-Amz-Target": "AmazonEC2ContainerServiceV20141113.DescribeTasks", - "Content-Type": "application/x-amz-json-1.1", - }, - body: JSON.stringify(body) - }) - - return await res.json() as DescribeTasksCommandOutput - }) - - - export const EcsStopTask = fn(z.object({ - cluster: z.string().optional(), - reason: z.string().optional(), - task: z.string() - }), async (body) => { - const c = await client(); - - const url = new URL(`https://ecs.${c.region}.amazonaws.com/`) - - const res = await c.fetch(url, { - method: "POST", - headers: { - "X-Amz-Target": "AmazonEC2ContainerServiceV20141113.StopTask", - "Content-Type": "application/x-amz-json-1.1", - }, - body: JSON.stringify(body) - }) - - return await res.json() as StopTaskCommandOutput - }) - -} - - diff --git a/packages/core/src:old/common.ts b/packages/core/src:old/common.ts deleted file mode 100644 index a7ec75d8..00000000 --- a/packages/core/src:old/common.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { z } from "zod"; -import "zod-openapi/extend"; - -export module Common { - export const IdDescription = `Unique object identifier. -The format and length of IDs may change over time.`; -} \ No newline at end of file diff --git a/packages/core/src:old/database.ts b/packages/core/src:old/database.ts deleted file mode 100644 index c782219c..00000000 --- a/packages/core/src:old/database.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Resource } from "sst"; -import { init } from "@instantdb/admin"; -import schema from "../instant.schema"; - -const databaseClient = () => init({ - appId: Resource.InstantAppId.value, - adminToken: Resource.InstantAdminToken.value, - schema - }) - - -export default databaseClient \ No newline at end of file diff --git a/packages/core/src:old/email/index.ts b/packages/core/src:old/email/index.ts deleted file mode 100644 index 769f1b31..00000000 --- a/packages/core/src:old/email/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { LoopsClient } from "loops"; -import { Resource } from "sst/resource" -export namespace Email { - export const Client = () => new LoopsClient(Resource.LoopsApiKey.value); - - export async function send( - to: string, - body: string, - ) { - - try { - await Client().sendTransactionalEmail( - { - transactionalId: "cm58pdf8d03upb5ecirnmvrfb", - email: to, - dataVariables: { - logincode: body - } - } - ); - } catch (error) { - console.log("error sending email", error) - } - } - - export async function sendWelcome( - to: string, - name: string, - ) { - - try { - await Client().sendTransactionalEmail( - { - transactionalId: "cm61jrbbx02twlstfwfcywt5u", - email: to, - dataVariables: { - name - } - } - ); - } catch (error) { - console.log("error sending email", error) - } - } -} \ No newline at end of file diff --git a/packages/core/src:old/error.ts b/packages/core/src:old/error.ts deleted file mode 100644 index 9aab0425..00000000 --- a/packages/core/src:old/error.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class VisibleError extends Error { - constructor( - public kind: "input" | "auth", - public code: string, - public message: string, - ) { - super(message); - } - } \ No newline at end of file diff --git a/packages/core/src:old/examples.ts b/packages/core/src:old/examples.ts deleted file mode 100644 index 6792355b..00000000 --- a/packages/core/src:old/examples.ts +++ /dev/null @@ -1,75 +0,0 @@ -export module Examples { - - export const User = { - id: "0bfcc712-df13-4454-81a8-fbee66eddca4", - email: "john@example.com", - }; - - export const Task = { - id: "0bfcc712-df13-4454-81a8-fbee66eddca4", - taskID: "b8302fca2d224d91ab342a2e4ab926d3", - type: "AWS" as const, //or "on-premises", - lastStatus: "RUNNING" as const, - healthStatus: "UNKNOWN" as const, - startedAt: '2025-01-09T01:56:23.902Z', - lastUpdated: '2025-01-09T01:56:23.902Z', - stoppedAt: '2025-01-09T04:46:23.902Z' - } - - export const Profile = { - id: "0bfcb712-df13-4454-81a8-fbee66eddca4", - username: "janedoe47", - status: "active" as const, - avatarUrl: "https://cdn.discordapp.com/avatars/xxxxxxx/xxxxxxx.png", - discriminator: 12, //it needs to be two digits - createdAt: '2025-01-04T11:56:23.902Z', - updatedAt: '2025-01-09T01:56:23.902Z' - } - - export const Subscription = { - id: "0bfcb712-df13-4454-81a8-fbee66eddca4", - checkoutID: "0bfcb712-df43-4454-81a8-fbee66eddca4", - // productID: "0bfcb712-df43-4454-81a8-fbee66eddca4", - // quantity: 1, - // frequency: "monthly" as const, - // next: '2025-01-09T01:56:23.902Z', - canceledAt: '2025-02-09T01:56:23.902Z' - } - - export const Team = { - id: "0bfcb712-df13-4454-81a8-fbee66eddca4", - // owner: true, - name: "Jane Doe's Games", - slug: "jane-does-games", - createdAt: '2025-01-04T11:56:23.902Z', - updatedAt: '2025-01-09T01:56:23.902Z' - } - - export const Machine = { - id: "0bfcb712-df13-4454-81a8-fbee66eddca4", - hostname: "DESKTOP-EUO8VSF", - fingerprint: "fc27f428f9ca47d4b41b70889ae0c62090", - createdAt: '2025-01-04T11:56:23.902Z', - deletedAt: '2025-01-09T01:56:23.902Z' - } - - export const Instance = { - id: "0bfcb712-df13-4454-81a8-fbee66eddca4", - hostname: "a955e059f05d", - createdAt: '2025-01-04T11:56:23.902Z', - lastActive: '2025-01-09T01:56:23.902Z' - } - - export const Game = { - id: '0bfcb712-df13-4454-81a8-fbee66eddca4', - name: "Control Ultimate Edition", - steamID: 870780, - } - - export const Session = { - id: "0bfcb712-df13-4454-81a8-fbee66eddca4", - public: true, - startedAt: '2025-01-04T11:56:23.902Z', - endedAt: '2025-01-04T12:36:23.902Z' - } -} \ No newline at end of file diff --git a/packages/core/src:old/game/index.ts b/packages/core/src:old/game/index.ts deleted file mode 100644 index 93e11282..00000000 --- a/packages/core/src:old/game/index.ts +++ /dev/null @@ -1,151 +0,0 @@ -// import { z } from "zod" -// import { fn } from "../utils"; -// import { Common } from "../common"; -// import { Examples } from "../examples"; -// import databaseClient from "../database" -// import { id as createID } from "@instantdb/admin"; -// import { groupBy, map, pipe, values } from "remeda" -// import { useCurrentDevice, useCurrentUser } from "../actor"; - -// export module Games { -// export const Info = z -// .object({ -// id: z.string().openapi({ -// description: Common.IdDescription, -// example: Examples.Game.id, -// }), -// name: z.string().openapi({ -// description: "A human-readable name for the game, used for easy identification.", -// example: Examples.Game.name, -// }), -// steamID: z.number().openapi({ -// description: "The Steam ID of the game, used to identify it during installation and runtime.", -// example: Examples.Game.steamID, -// }) -// }) -// .openapi({ -// ref: "Game", -// description: "Represents a Steam game that can be installed and played on a machine.", -// example: Examples.Game, -// }); - -// export type Info = z.infer; - -// export const create = fn(Info.pick({ name: true, steamID: true }), async (input) => { -// const id = createID() -// const db = databaseClient() -// const device = useCurrentDevice() - -// await db.transact( -// db.tx.games[id]!.update({ -// name: input.name, -// steamID: input.steamID, -// }).link({ machines: device.id }) -// ) -// // -// return id -// }) - -// export const list = async () => { -// const db = databaseClient() -// const user = useCurrentUser() - -// const query = { -// $users: { -// $: { where: { id: user.id } }, -// games: {} -// }, -// } - -// const res = await db.query(query) - -// const games = res.$users[0]?.games -// if (games && games.length > 0) { -// const result = pipe( -// games, -// groupBy(x => x.id), -// values(), -// map((group): Info => ({ -// id: group[0].id, -// name: group[0].name, -// steamID: group[0].steamID, -// })) -// ) -// return result -// } -// return null -// } - -// export const fromSteamID = fn(z.number(), async (steamID) => { -// const db = databaseClient() - -// const query = { -// games: { -// $: { -// where: { -// steamID, -// } -// } -// } -// } - -// const res = await db.query(query) - -// const games = res.games - -// if (games.length > 0) { -// const result = pipe( -// games, -// groupBy(x => x.id), -// values(), -// map((group): Info => ({ -// id: group[0].id, -// name: group[0].name, -// steamID: group[0].steamID, -// })) -// ) -// return result[0] -// } - -// return null -// }) - -// export const linkToCurrentUser = fn(z.string(), async (steamID) => { -// const user = useCurrentUser() -// const db = databaseClient() - -// await db.transact(db.tx.games[steamID]!.link({ owners: user.id })) - -// return "ok" -// }) - -// export const unLinkFromCurrentUser = fn(z.number(), async (steamID) => { -// const user = useCurrentUser() -// const db = databaseClient() - -// const query = { -// $users: { -// $: { where: { id: user.id } }, -// games: { -// $: { -// where: { -// steamID, -// } -// } -// } -// }, -// } - -// const res = await db.query(query) -// const games = res.$users[0]?.games -// if (games && games.length > 0) { -// const game = games[0] as Info -// await db.transact(db.tx.games[game.id]!.unlink({ owners: user.id })) - -// return "ok" -// } - -// return null -// }) - -// } \ No newline at end of file diff --git a/packages/core/src:old/instance/index.ts b/packages/core/src:old/instance/index.ts deleted file mode 100644 index 04a419f4..00000000 --- a/packages/core/src:old/instance/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { z } from "zod" -import { fn } from "../utils"; -import { Common } from "../common"; -import { Examples } from "../examples"; -import databaseClient from "../database" -import { id as createID } from "@instantdb/admin"; -import { groupBy, map, pipe, values } from "remeda" - -export module Instances { - export const Info = z - .object({ - id: z.string().openapi({ - description: Common.IdDescription, - example: Examples.Instance.id, - }), - hostname: z.string().openapi({ - description: "The container's hostname", - example: Examples.Instance.hostname, - }), - createdAt: z.string().or(z.number()).openapi({ - description: "The time this instances was registered on the network", - example: Examples.Instance.createdAt, - }), - lastActive: z.string().or(z.number()).optional().openapi({ - description: "The time this instance was last seen on the network", - example: Examples.Instance.lastActive, - }) - }) - .openapi({ - ref: "Instance", - description: "Represents a running container that is connected to the Nestri network..", - example: Examples.Instance, - }); - - export type Info = z.infer; - export const create = fn(z.object({ hostname: z.string(), teamID: z.string() }), async (input) => { - const id = createID() - const now = new Date().toISOString() - const db = databaseClient() - await db.transact( - db.tx.instances[id]!.update({ - hostname: input.hostname, - createdAt: now, - }).link({ owners: input.teamID }) - ) - - return "ok" - }) - - export const fromTeamID = fn(z.string(), async (teamID) => { - const db = databaseClient() - - const query = { - instances: { - $: { - where: { - owners: teamID - } - } - } - } - - const res = await db.query(query) - const data = res.instances - - if (data && data.length > 0) { - const result = pipe( - data, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - lastActive: group[0].lastActive, - hostname: group[0].hostname, - createdAt: group[0].createdAt - })) - ) - return result - } - - return null - }) -} \ No newline at end of file diff --git a/packages/core/src:old/machine/index.ts b/packages/core/src:old/machine/index.ts deleted file mode 100644 index 06403421..00000000 --- a/packages/core/src:old/machine/index.ts +++ /dev/null @@ -1,232 +0,0 @@ -// import { z } from "zod" -// import { fn } from "../utils"; -// import { Games } from "../game" -// import { Common } from "../common"; -// import { Examples } from "../examples"; -// import { useCurrentUser } from "../actor"; -// import databaseClient from "../database" -// import { id as createID } from "@instantdb/admin"; -// import { groupBy, map, pipe, values } from "remeda" -// export module Machines { -// export const Info = z -// .object({ -// id: z.string().openapi({ -// description: Common.IdDescription, -// example: Examples.Machine.id, -// }), -// hostname: z.string().openapi({ -// description: "The Linux hostname that identifies this machine", -// example: Examples.Machine.hostname, -// }), -// fingerprint: z.string().openapi({ -// description: "A unique identifier derived from the machine's Linux machine ID.", -// example: Examples.Machine.fingerprint, -// }), -// createdAt: z.string().or(z.number()).openapi({ -// description: "Represents a machine running on the Nestri network, containing its identifying information and metadata.", -// example: Examples.Machine.createdAt, -// }) -// }) -// .openapi({ -// ref: "Machine", -// description: "Represents a physical or virtual machine connected to the Nestri network..", -// example: Examples.Machine, -// }); - -// export type Info = z.infer; - -// export const create = fn(Info.pick({ fingerprint: true, hostname: true }), async (input) => { -// const id = createID() -// const now = new Date().toISOString() -// const db = databaseClient() -// await db.transact( -// db.tx.machines[id]!.update({ -// fingerprint: input.fingerprint, -// hostname: input.hostname, -// createdAt: now, -// //Just in case it had been previously deleted -// deletedAt: undefined -// }) -// ) - -// return id -// }) - -// // export const fromID = fn(z.string(), async (id) => { -// const db = databaseClient() - -// const query = { -// machines: { -// $: { -// where: { -// id: id, -// deletedAt: { $isNull: true } -// } -// } -// } -// } - -// const res = await db.query(query) -// const machines = res.machines - -// if (machines && machines.length > 0) { -// const result = pipe( -// machines, -// groupBy(x => x.id), -// values(), -// map((group): Info => ({ -// id: group[0].id, -// fingerprint: group[0].fingerprint, -// hostname: group[0].hostname, -// createdAt: group[0].createdAt -// })) -// ) -// return result -// } - -// return null -// }) - -// export const installedGames = fn(z.string(), async (id) => { -// const db = databaseClient() - -// const query = { -// machines: { -// $: { -// where: { -// id: id, -// deletedAt: { $isNull: true } -// } -// }, -// games: {} -// } -// } - -// const res = await db.query(query) -// const machines = res.machines - -// if (machines && machines.length > 0) { -// const games = machines[0]?.games as any -// if (games.length > 0) { -// return games as Games.Info[] -// } -// return null -// } - -// return null -// }) - -// export const fromFingerprint = fn(z.string(), async (input) => { -// const db = databaseClient() - -// const query = { -// machines: { -// $: { -// where: { -// fingerprint: input, -// deletedAt: { $isNull: true } -// } -// } -// } -// } - -// const res = await db.query(query) - -// const machines = res.machines - -// if (machines.length > 0) { -// const result = pipe( -// machines, -// groupBy(x => x.id), -// values(), -// map((group): Info => ({ -// id: group[0].id, -// fingerprint: group[0].fingerprint, -// hostname: group[0].hostname, -// createdAt: group[0].createdAt -// })) -// ) -// return result[0] -// } - -// return null -// }) - -// export const list = async () => { -// const user = useCurrentUser() -// const db = databaseClient() - -// const query = { -// $users: { -// $: { where: { id: user.id } }, -// machines: { -// $: { -// where: { -// deletedAt: { $isNull: true } -// } -// } -// } -// }, -// } - -// const res = await db.query(query) - -// const machines = res.$users[0]?.machines -// if (machines && machines.length > 0) { -// const result = pipe( -// machines, -// groupBy(x => x.id), -// values(), -// map((group): Info => ({ -// id: group[0].id, -// fingerprint: group[0].fingerprint, -// hostname: group[0].hostname, -// createdAt: group[0].createdAt -// })) -// ) -// return result -// } -// return null -// } - -// export const linkToCurrentUser = fn(z.string(), async (id) => { -// const user = useCurrentUser() -// const db = databaseClient() - -// await db.transact(db.tx.machines[id]!.link({ owner: user.id })) - -// return "ok" -// }) - -// export const unLinkFromCurrentUser = fn(z.string(), async (id) => { -// const user = useCurrentUser() -// const db = databaseClient() -// const now = new Date().toISOString() - -// const query = { -// $users: { -// $: { where: { id: user.id } }, -// machines: { -// $: { -// where: { -// id, -// deletedAt: { $isNull: true } -// } -// } -// } -// }, -// } - -// const res = await db.query(query) -// const machines = res.$users[0]?.machines -// if (machines && machines.length > 0) { -// const machine = machines[0] as Info -// await db.transact(db.tx.machines[machine.id]!.update({ deletedAt: now })) - -// return "ok" -// } - -// return null -// }) - -// } \ No newline at end of file diff --git a/packages/core/src:old/profile/index.ts b/packages/core/src:old/profile/index.ts deleted file mode 100644 index b17a5c0c..00000000 --- a/packages/core/src:old/profile/index.ts +++ /dev/null @@ -1,412 +0,0 @@ -import { z } from "zod" -import { fn } from "../utils"; -import { Common } from "../common"; -import { Examples } from "../examples"; -import databaseClient from "../database"; -import { groupBy, map, pipe, values } from "remeda" -import { id as createID, } from "@instantdb/admin"; -import { useCurrentUser } from "../actor"; - -export const userStatus = z.enum([ - "active", //online and playing a game - "idle", //online and not playing - "offline", -]); - -export module Profiles { - const MAX_ATTEMPTS = 50; - - export const Info = z - .object({ - id: z.string().openapi({ - description: Common.IdDescription, - example: Examples.Machine.id, - }), - username: z.string().openapi({ - description: "The user's unique username", - example: Examples.Profile.username, - }), - avatarUrl: z.string().or(z.undefined()).openapi({ - description: "The url to the profile picture.", - example: Examples.Profile.username, - }), - status: userStatus.openapi({ - description: "Whether the user is active, idle or offline", - example: Examples.Profile.status - }), - discriminator: z.string().or(z.number()).openapi({ - description: "The number discriminator for each username", - example: Examples.Profile.discriminator, - }), - createdAt: z.string().or(z.number()).openapi({ - description: "The time when this profile was first created", - example: Examples.Profile.createdAt, - }), - updatedAt: z.string().or(z.number()).openapi({ - description: "The time when this profile was last edited", - example: Examples.Profile.updatedAt, - }) - }) - .openapi({ - ref: "Profile", - description: "Represents a profile of a user on Nestri", - example: Examples.Profile, - }); - - export type Info = z.infer; - export type userStatus = z.infer; - - export const sanitizeUsername = (username: string): string => { - // Remove spaces and numbers - return username.replace(/[\s0-9]/g, ''); - }; - - export const generateDiscriminator = (): string => { - return Math.floor(Math.random() * 100).toString().padStart(2, '0'); - }; - - export const isValidDiscriminator = (discriminator: string): boolean => { - return /^\d{2}$/.test(discriminator); - }; - - export const fromUsername = fn(z.string(), async (input) => { - const sanitizedUsername = sanitizeUsername(input); - - const db = databaseClient() - - const query = { - profiles: { - $: { - where: { - username: sanitizedUsername, - } - } - } - } - - const res = await db.query(query) - - const profiles = res.profiles - - if (!profiles || profiles.length == 0) { - - return null - } - - return pipe( - profiles, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - username: group[0].username, - createdAt: group[0].createdAt, - discriminator: group[0].discriminator, - updatedAt: group[0].updatedAt, - status: group[0].status as userStatus - })) - ) - }) - - export const findAvailableDiscriminator = fn(z.string(), async (input) => { - const db = databaseClient() - const username = sanitizeUsername(input); - - for (let i = 0; i < MAX_ATTEMPTS; i++) { - const discriminator = generateDiscriminator(); - const query = { - profiles: { - $: { - where: { - username, - discriminator - } - } - } - } - const res = await db.query(query) - const profiles = res.profiles - if (profiles.length === 0) { - return discriminator; - } - } - return null; // No available discriminators - - }) - - export const create = fn(z.object({ username: z.string(), customDiscriminator: z.string().optional(), avatarUrl: z.string().optional(), owner: z.string() }), async (input) => { - const username = sanitizeUsername(input.username); - - const db = databaseClient() - const id = createID() - const now = new Date().toISOString() - - let discriminator: string | null; - if (input.customDiscriminator) { - if (!isValidDiscriminator(input.customDiscriminator)) { - console.error('Invalid discriminator format') - return null - // throw new Error('Invalid discriminator format'); - } - - const query = { - profiles: { - $: { - where: { - username, - discriminator: input.customDiscriminator - } - } - } - } - - const res = await db.query(query) - const profiles = res.profiles - if (profiles.length != 0) { - console.error("Username and discriminator combination already taken ") - return null - // throw new Error('Username and discriminator combination already taken'); - } - - discriminator = input.customDiscriminator - } else { - // Generate a random available discriminator - discriminator = await findAvailableDiscriminator(username); - - if (!discriminator) { - console.error("No available discriminators for this username ") - return null - // throw new Error('No available discriminators for this username'); - } - } - - return await db.transact( - db.tx.profiles[id]!.update({ - username, - avatarUrl: input.avatarUrl, - createdAt: now, - updatedAt: now, - discriminator, - status: "idle" - }).link({ owner: input.owner }) - ) - }) - - export const getFullUsername = async (username: string) => { - const db = databaseClient() - - const query = { - profiles: { - $: { - where: { - username, - } - } - } - } - const res = await db.query(query) - const profiles = res.profiles - - if (!profiles || profiles.length === 0) { - console.error('User not found') - return null - // throw new Error('User not found'); - } - - return `${profiles[0]?.username}#${profiles[0]?.discriminator}`; - } - - export const fromOwnerID = async (ownerID: string) => { - try { - - const db = databaseClient() - - const query = { - profiles: { - $: { - where: { - owner: ownerID - } - }, - } - } - const res = await db.query(query) - - const profiles = res.profiles - - if (!profiles || profiles.length === 0) { - throw new Error("No profiles were found"); - } - - const profile = pipe( - profiles, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - username: group[0].username, - createdAt: group[0].createdAt, - updatedAt: group[0].updatedAt, - avatarUrl: group[0].avatarUrl, - discriminator: group[0].discriminator, - status: group[0].status as userStatus - })) - ) - - return profile[0] - } catch (error) { - console.log("user fromOwnerID", error) - return null - } - } - - export const fromID = async (id: string) => { - try { - - const db = databaseClient() - - const query = { - profiles: { - $: { - where: { - id - } - }, - } - } - const res = await db.query(query) - - const profiles = res.profiles - - if (!profiles || profiles.length === 0) { - throw new Error("No profiles were found"); - } - - const profile = pipe( - profiles, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - username: group[0].username, - createdAt: group[0].createdAt, - updatedAt: group[0].updatedAt, - avatarUrl: group[0].avatarUrl, - discriminator: group[0].discriminator, - status: group[0].status as userStatus - })) - ) - - return profile[0] - } catch (error) { - console.log("user fromID", error) - return null - } - } - - export const fromIDToOwner = async (id: string) => { - try { - - const db = databaseClient() - - const query = { - profiles: { - $: { - where: { - id - } - }, - } - } - const res = await db.query(query) - - const profiles = res.profiles as any - - if (!profiles || profiles.length === 0) { - throw new Error("No profiles were found"); - } - - return profiles[0]!.owner as string - } catch (error) { - console.log("user fromID", error) - return null - } - } - export const getCurrentProfile = async () => { - const user = useCurrentUser() - const currentProfile = await fromOwnerID(user.id); - - return currentProfile - } - - export const setStatus = fn(userStatus, async (status) => { - try { - const user = useCurrentUser() - const db = databaseClient() - - const now = new Date().toISOString() - - await db.transact( - db.tx.profiles[user.id]!.update({ - status, - updatedAt: now - }) - ) - } catch (error) { - console.log("user setStatus error", error) - return null - } - }) - - export const list = async () => { - try { - const db = databaseClient() - // const ago = new Date(Date.now() - (60 * 1000 * 30)).toISOString() - const ago = new Date(Date.now() - (24 * 60 * 60 * 1000)).toISOString() - - const query = { - profiles: { - $: { - limit: 10, - where: { - updatedAt: { $gt: ago }, - }, - order: { - updatedAt: "desc" as const, - }, - } - } - } - - const res = await db.query(query) - - const profiles = res.profiles - - if (!profiles || profiles.length === 0) { - throw new Error("No profiles were found"); - - } - - const result = pipe( - profiles, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - username: group[0].username, - createdAt: group[0].createdAt, - updatedAt: group[0].updatedAt, - avatarUrl: group[0].avatarUrl, - discriminator: group[0].discriminator, - status: group[0].status as userStatus - })) - ) - - return result - - } catch (error) { - console.log("user list error", error) - return null - } - } -} \ No newline at end of file diff --git a/packages/core/src:old/session/index.ts b/packages/core/src:old/session/index.ts deleted file mode 100644 index d15d0528..00000000 --- a/packages/core/src:old/session/index.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { z } from "zod" -import { fn } from "../utils"; -import { Common } from "../common"; -import { Examples } from "../examples"; -import databaseClient from "../database" -import { useCurrentUser } from "../actor"; -import { groupBy, map, pipe, values } from "remeda" -import { id as createID } from "@instantdb/admin"; - -export module Sessions { - export const Info = z - .object({ - id: z.string().openapi({ - description: Common.IdDescription, - example: Examples.Session.id, - }), - public: z.boolean().openapi({ - description: "If true, the session is publicly viewable by all users. If false, only authorized users can access it", - example: Examples.Session.public, - }), - endedAt: z.string().or(z.number()).or(z.undefined()).openapi({ - description: "The timestamp indicating when this session was completed or terminated. Null if session is still active.", - example: Examples.Session.endedAt, - }), - startedAt: z.string().or(z.number()).openapi({ - description: "The timestamp indicating when this session started.", - example: Examples.Session.startedAt, - }) - }) - .openapi({ - ref: "Session", - description: "Represents a single game play session, tracking its lifetime and accessibility settings.", - example: Examples.Session, - }); - - export type Info = z.infer; - - export const create = fn(z.object({ public: z.boolean() }), async (input) => { - try { - const id = createID() - const db = databaseClient() - const user = useCurrentUser() - const now = new Date().toISOString() - - await db.transact( - db.tx.sessions[id]!.update({ - public: input.public, - startedAt: now, - }).link({ owner: user.id }) - ) - - return id - } catch (err) { - return null - } - }) - - export const getActive = async () => { - try { - const db = databaseClient() - - const query = { - sessions: { - $: { - where: { - endedAt: { $isNull: true } - } - } - } - } - - const res = await db.query(query) - - const sessions = res.sessions - if (!sessions || sessions.length === 0) { - throw new Error("No active sessions found") - } - - const result = pipe( - sessions, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - endedAt: group[0].endedAt, - startedAt: group[0].startedAt, - public: group[0].public, - })) - ) - - return result - - } catch (error) { - return null - } - } - - export const fromID = fn(z.string(), async (id) => { - try { - const db = databaseClient() - - const query = { - sessions: { - $: { - where: { - id: id, - } - } - } - } - - const res = await db.query(query) - const sessions = res.sessions - - if (!sessions || sessions.length === 0) { - throw new Error("No sessions were found"); - } - - const result = pipe( - sessions, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - endedAt: group[0].endedAt, - startedAt: group[0].startedAt, - public: group[0].public, - })) - ) - return result - } catch (err) { - console.log("sessions error", err) - return null - } - }) - - export const fromTaskID = fn(z.string(), async (taskID) => { - try { - const db = databaseClient() - - const query = { - sessions: { - $: { - where: { - task: taskID, - endedAt: { $isNull: true } - } - } - } - } - - const res = await db.query(query) - const sessions = res.sessions - - if (!sessions || sessions.length === 0) { - throw new Error("No sessions were found"); - } - console.log("sessions", sessions) - - const result = pipe( - sessions, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - endedAt: group[0].endedAt, - startedAt: group[0].startedAt, - public: group[0].public, - })) - ) - return result[0] - } catch (err) { - console.log("sessions error", err) - return null - } - }) - - export const end = fn(z.string(), async (id) => { - const user = useCurrentUser() - try { - const db = databaseClient() - const now = new Date().toISOString() - - const query = { - sessions: { - $: { - where: { - owner: user.id, - id, - } - } - }, - } - - const res = await db.query(query) - const sessions = res.sessions - if (!sessions || sessions.length === 0) { - throw new Error("No sessions were found"); - } - - await db.transact(db.tx.sessions[sessions[0]!.id]!.update({ endedAt: now })) - - return "ok" - - } catch (error) { - - return null - } - - }) - - export const fromOwnerID = fn(z.string(), async (id) => { - try { - const db = databaseClient() - - const query = { - sessions: { - $: { - where: { - owner: id, - endedAt: { $isNull: true } - } - } - } - } - - const res = await db.query(query) - const sessions = res.sessions - - if (!sessions || sessions.length === 0) { - throw new Error("No sessions were found"); - } - - const result = pipe( - sessions, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - endedAt: group[0].endedAt, - startedAt: group[0].startedAt, - public: group[0].public, - })) - ) - return result[0] - } catch (err) { - console.log("session owner error", err) - return null - } - }) -} \ No newline at end of file diff --git a/packages/core/src:old/subscription/index.ts b/packages/core/src:old/subscription/index.ts deleted file mode 100644 index 75ef5acd..00000000 --- a/packages/core/src:old/subscription/index.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { z } from "zod"; -import databaseClient from "../database" -import { fn } from "../utils"; -import { groupBy, map, pipe, values } from "remeda" -import { Common } from "../common"; -import { Examples } from "../examples"; -import { useCurrentUser } from "../actor"; -import { id as createID } from "@instantdb/admin"; -import { Email } from "../email"; -import { Profiles } from "../profile"; - -export const SubscriptionFrequency = z.enum([ - "fixed", - "daily", - "weekly", - "monthly", - "yearly", -]); - -export type SubscriptionFrequency = z.infer; - -export namespace Subscriptions { - export const Info = z - .object({ - id: z.string().openapi({ - description: Common.IdDescription, - example: Examples.Subscription.id, - }), - checkoutID: z.string().openapi({ - description: "The polar.sh checkout id", - example: Examples.Subscription.checkoutID, - }), - // productID: z.string().openapi({ - // description: "ID of the product being subscribed to.", - // example: Examples.Subscription.productID, - // }), - // quantity: z.number().int().openapi({ - // description: "Quantity of the subscription.", - // example: Examples.Subscription.quantity, - // }), - // frequency: SubscriptionFrequency.openapi({ - // description: "Frequency of the subscription.", - // example: Examples.Subscription.frequency, - // }), - // next: z.string().or(z.number()).openapi({ - // description: "Next billing date for the subscription.", - // example: Examples.Subscription.next, - // }), - canceledAt: z.string().or(z.number()).optional().openapi({ - description: "Cancelled date for the subscription.", - example: Examples.Subscription.canceledAt, - }), - }) - .openapi({ - ref: "Subscription", - description: "Subscription to a Nestri product.", - example: Examples.Subscription, - }); - - export type Info = z.infer; - - export const list = fn(z.string().optional(), async (userID) => { - const db = databaseClient() - const user = userID ? userID : useCurrentUser().id - - const query = { - subscriptions: { - $: { - where: { - owner: user, - canceledAt: { $isNull: true } - } - }, - } - } - - const res = await db.query(query) - - const response = res.subscriptions - if (!response || response.length === 0) { - return null - } - - const result = pipe( - response, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - // next: group[0].next, - // frequency: group[0].frequency as any, - // quantity: group[0].quantity, - // productID: group[0].productID, - checkoutID: group[0].checkoutID, - })) - ) - - return result - }) - - export const create = fn(Info.omit({ id: true, canceledAt: true }), async (input) => { - // const id = createID() - const id = createID() - const db = databaseClient() - const user = useCurrentUser() - - //Use the polar.sh ID - await db.transact(db.tx.subscriptions[id]!.update({ - // next: input.next, - // frequency: input.frequency, - // quantity: input.quantity, - checkoutID: input.checkoutID, - }).link({ owner: user.id })) - const res = await db.auth.getUser({ id: user.id }) - const profile = await Profiles.fromOwnerID(user.id) - if (profile) { - await Email.sendWelcome(res.email, profile.username) - } - - }) - - export const remove = fn(z.string(), async (id) => { - const db = databaseClient() - - await db.transact(db.tx.subscriptions[id]!.update({ - canceledAt: new Date().toISOString() - })) - }) - - export const fromID = fn(z.string(), async (id) => { - const db = databaseClient() - const user = useCurrentUser() - const query = { - subscriptions: { - $: { - where: { - id, - //Make sure they can only get subscriptions they own - owner: user.id, - canceledAt: { $isNull: true } - } - }, - } - } - - const res = await db.query(query) - - const response = res.subscriptions - if (!response || response.length === 0) { - return null - } - - const result = pipe( - response, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - checkoutID: group[0].checkoutID, - // next: group[0].next, - // frequency: group[0].frequency as any, - // quantity: group[0].quantity, - // productID: group[0].productID, - })) - ) - - return result[0] - }) - - export const fromCheckoutID = fn(z.string(), async (id) => { - const db = databaseClient() - const user = useCurrentUser() - const query = { - subscriptions: { - $: { - where: { - id, - //Make sure they can only get subscriptions they own - checkoutID: id, - canceledAt: { $isNull: true } - } - }, - } - } - - const res = await db.query(query) - - const response = res.subscriptions - if (!response || response.length === 0) { - return null - } - - const result = pipe( - response, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - checkoutID: group[0].checkoutID, - })) - ) - - return result[0] - }) -} \ No newline at end of file diff --git a/packages/core/src:old/task/index.ts b/packages/core/src:old/task/index.ts deleted file mode 100644 index c15b0372..00000000 --- a/packages/core/src:old/task/index.ts +++ /dev/null @@ -1,331 +0,0 @@ -import { z } from "zod"; -import { fn } from "../utils"; -import { Resource } from "sst"; -import { Aws } from "../aws/client"; -import { Common } from "../common"; -import { Examples } from "../examples"; -import databaseClient from "../database" -import { useCurrentUser } from "../actor"; -import { id as createID } from "@instantdb/admin"; -import { groupBy, map, pipe, values } from "remeda" -import { Sessions } from "../session"; - -export const lastStatus = z.enum([ - "RUNNING", - "PENDING", - "UNKNOWN", - "STOPPED", -]); - -export const taskType = z.enum([ - "AWS", - "ON_PREMISES", - "UNKNOWN" -]); - -export const healthStatus = z.enum([ - "HEALTHY", - "UNHEALTHY", - "UNKNOWN", -]); - -export type taskType = z.infer; -export type lastStatus = z.infer; -export type healthStatus = z.infer; - -export module Tasks { - export const Info = z - .object({ - id: z.string().openapi({ - description: Common.IdDescription, - example: Examples.Task.id, - }), - type: taskType.openapi({ - description: "Where this task is hosted on", - example: Examples.Task.type, - }), - taskID: z.string().openapi({ - description: "The id of this task as seen on AWS", - example: Examples.Task.taskID, - }), - startedAt: z.string().or(z.number()).openapi({ - description: "The time this task was started", - example: Examples.Task.startedAt, - }), - lastUpdated: z.string().or(z.number()).openapi({ - description: "The time the information about this task was last updated", - example: Examples.Task.lastUpdated, - }), - stoppedAt: z.string().or(z.number()).optional().openapi({ - description: "The time this task was stopped or quit", - example: Examples.Task.lastUpdated, - }), - lastStatus: lastStatus.openapi({ - description: "The last registered status of this task", - example: Examples.Task.lastStatus, - }), - healthStatus: healthStatus.openapi({ - description: "The health status of this task", - example: Examples.Task.healthStatus, - }) - }) - .openapi({ - ref: "Subscription", - description: "Subscription to a Nestri product.", - example: Examples.Task, - }); - - export type Info = z.infer; - - export const list = async () => { - const db = databaseClient() - const user = useCurrentUser() - - try { - const query = { - tasks: { - $: { - where: { - stoppedAt: { $isNull: true }, - owner: user.id - } - }, - } - } - - const data = await db.query(query) - - const response = data.tasks - if (!response || response.length === 0) { - throw new Error("No task for this user were found"); - } - - const result = pipe( - response, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - taskID: group[0].taskID, - type: group[0].type as taskType, - lastStatus: group[0].lastStatus as lastStatus, - healthStatus: group[0].healthStatus as healthStatus, - startedAt: group[0].startedAt, - stoppedAt: group[0].stoppedAt, - lastUpdated: group[0].lastUpdated, - })) - ) - - return result - } catch (e) { - return null - } - } - - export const create = async () => { - const user = useCurrentUser() - - try { - - //TODO: Use a simpler way to set the session ID - // const sessionID = createID() - - const sessionID = await Sessions.create({ public: true }) - if (!sessionID) throw new Error("No session id was given"); - - const run = await Aws.EcsRunTask({ - count: 1, - cluster: Resource.NestriGPUCluster.value, - taskDefinition: Resource.NestriGPUTask.value, - launchType: "EC2", - overrides: { - containerOverrides: [ - { - name: "nestri", - environment: [ - { - name: "NESTRI_ROOM", - value: sessionID - } - ] - } - ] - } - }) - - if (!run.tasks || run.tasks.length === 0) { - throw new Error(`No tasks were started`); - } - - // Extract task details - const task = run.tasks[0]; - const taskArn = task?.taskArn!; - const taskId = taskArn.split('/').pop()!; // Extract task ID from ARN - const taskStatus = task?.lastStatus; - const taskHealthStatus = task?.healthStatus; - const startedAt = task?.startedAt!; - - const id = createID() - const db = databaseClient() - const now = new Date().toISOString() - await db.transact(db.tx.tasks[id]!.update({ - taskID: taskId, - type: "AWS", - healthStatus: taskHealthStatus ? taskHealthStatus.toString() : "UNKNOWN", - startedAt: startedAt ? startedAt.toISOString() : now, - lastStatus: taskStatus, - lastUpdated: now, - }).link({ owner: user.id, sessions: sessionID })) - - return id - } catch (e) { - console.error("error", e) - return null - } - } - - export const fromID = fn(z.string(), async (taskID) => { - const db = databaseClient() - try { - const query = { - tasks: { - $: { - where: { - id: taskID, - stoppedAt: { $isNull: true } - } - }, - } - } - - const data = await db.query(query) - - const response = data.tasks - if (!response || response.length === 0) { - throw new Error("No task with the given id was found"); - } - - const result = pipe( - response, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - taskID: group[0].taskID, - type: group[0].type as taskType, - lastStatus: group[0].lastStatus as lastStatus, - healthStatus: group[0].healthStatus as healthStatus, - startedAt: group[0].startedAt, - stoppedAt: group[0].stoppedAt, - lastUpdated: group[0].lastUpdated, - })) - ) - - return result[0] - - } catch (error) { - return null - } - }) - - export const update = fn(z.string(), async (taskID) => { - try { - const db = databaseClient() - - const query = { - tasks: { - $: { - where: { - id: taskID, - stoppedAt: { $isNull: true } - } - }, - } - } - - const data = await db.query(query) - - const response = data.tasks - if (!response || response.length === 0) { - throw new Error("No task with the given taskID was found"); - } - - const now = new Date().toISOString() - const describeResponse = await Aws.EcsDescribeTasks({ - tasks: [response[0]!.taskID], - cluster: Resource.NestriGPUCluster.value - }) - - if (!describeResponse.tasks || describeResponse.tasks.length === 0) { - throw new Error("No tasks were found"); - } - - const task = describeResponse.tasks[0]! - - const updatedDb = { - healthStatus: task.healthStatus ? task.healthStatus : "UNKNOWN", - lastStatus: task.lastStatus ? task.lastStatus : "UNKNOWN", - lastUpdated: now, - } - - await db.transact(db.tx.tasks[response[0]!.id]!.update({ - ...updatedDb - })) - - const updatedRes = [{ ...response[0]!, ...updatedDb }] - - const result = pipe( - updatedRes, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - taskID: group[0].taskID, - type: group[0].type as taskType, - lastStatus: group[0].lastStatus as lastStatus, - healthStatus: group[0].healthStatus as healthStatus, - startedAt: group[0].startedAt, - stoppedAt: group[0].stoppedAt, - lastUpdated: group[0].lastUpdated, - })) - ) - - return result - - } catch (error) { - console.error("update error", error) - return null - } - }) - - export const stop = fn(z.object({ taskID: z.string(), id: z.string() }), async (input) => { - const db = databaseClient() - const now = new Date().toISOString() - try { - //TODO:Check whether they own this task first - - const stopResponse = await Aws.EcsStopTask({ - task: input.taskID, - cluster: Resource.NestriGPUCluster.value, - reason: "Client requested a shutdown" - }) - - if (!stopResponse.task) { - throw new Error(`No task was stopped`); - } - - await db.transact(db.tx.tasks[input.id]!.update({ - stoppedAt: now, - lastUpdated: now, - lastStatus: "STOPPED", - healthStatus: "UNKNOWN" - })) - - return "ok" - - } catch (error) { - console.error("stop error", error) - return null - } - }) -} \ No newline at end of file diff --git a/packages/core/src:old/team/index.ts b/packages/core/src:old/team/index.ts deleted file mode 100644 index f472be54..00000000 --- a/packages/core/src:old/team/index.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { z } from "zod"; -import databaseClient from "../database" -import { fn } from "../utils"; -import { groupBy, map, pipe, values } from "remeda" -import { Common } from "../common"; -import { Examples } from "../examples"; -import { useCurrentUser } from "../actor"; -import { id as createID } from "@instantdb/admin"; - -export namespace Teams { - export const Info = z - .object({ - id: z.string().openapi({ - description: Common.IdDescription, - example: Examples.Team.id, - }), - name: z.string().openapi({ - description: "Name of the team", - example: Examples.Team.name, - }), - createdAt: z.string().or(z.number()).openapi({ - description: "The time when this team was first created", - example: Examples.Team.createdAt, - }), - updatedAt: z.string().or(z.number()).openapi({ - description: "The time when this team was last edited", - example: Examples.Team.updatedAt, - }), - // owner: z.boolean().openapi({ - // description: "Whether this team is owned by this user", - // example: Examples.Team.owner, - // }), - slug: z.string().openapi({ - description: "This is the unique name identifier for the team", - example: Examples.Team.slug - }) - }) - .openapi({ - ref: "Team", - description: "A group of users sharing the same machines for gaming.", - example: Examples.Team, - }); - - export type Info = z.infer; - - export const list = async () => { - const db = databaseClient() - const user = useCurrentUser() - - const query = { - teams: { - $: { - where: { - members: user.id, - deletedAt: { $isNull: true } - } - }, - } - } - - const res = await db.query(query) - - const teams = res.teams - if (!teams || teams.length === 0) { - return null - } - - const result = pipe( - teams, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - name: group[0].name, - createdAt: group[0].createdAt, - updatedAt: group[0].updatedAt, - slug: group[0].slug, - //@ts-expect-error - owner: group[0].owner === user.id - })) - ) - - return result - } - - - export const fromSlug = fn(z.string(), async (slug) => { - const db = databaseClient() - - const query = { - teams: { - $: { - where: { - slug, - deletedAt: { $isNull: true } - } - }, - } - } - - const res = await db.query(query) - - const teams = res.teams - if (!teams || teams.length === 0) { - return null - } - - const result = pipe( - teams, - groupBy(x => x.id), - values(), - map((group): Info => ({ - id: group[0].id, - name: group[0].name, - slug: group[0].slug, - createdAt: group[0].createdAt, - updatedAt: group[0].updatedAt, - // owner: group[0].owner === user.id - })) - ) - - return result[0] - }) - - export const create = fn(Info.pick({ name: true, slug: true }), async (input) => { - const id = createID() - const db = databaseClient() - const user = useCurrentUser() - const now = new Date().toISOString() - - await db.transact(db.tx.teams[id]!.update({ - name: input.name, - slug: input.slug, - createdAt: now, - updatedAt: now, - }).link({ owner: user.id, members: user.id })) - - return id - }) - - export const remove = fn(z.string(), async (id) => { - const db = databaseClient() - const now = new Date().toISOString() - - await db.transact(db.tx.teams[id]!.update({ - deletedAt: now - })) - - return "ok" - }) - - export const invite = fn(z.object({email:z.string(), id: z.string()}), async (input) => { - //TODO: - // const db = databaseClient() - // const now = new Date().toISOString() - - // await db.transact(db.tx.teams[id]!.update({ - // deletedAt: now - // })) - - return "ok" - }) - -} \ No newline at end of file diff --git a/packages/core/src:old/types.ts b/packages/core/src:old/types.ts deleted file mode 100644 index 2e8fc014..00000000 --- a/packages/core/src:old/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -export interface CloudflareCF { - colo: string; - continent: string; - country: string, - city: string; - region: string; - longitude: number; - latitude: number; - metroCode: string; - postalCode: string; - timezone: string; - regionCode: number; -} - -export interface CFRequest extends Request { - cf: CloudflareCF -} \ No newline at end of file diff --git a/packages/core/src:old/user/index.ts b/packages/core/src:old/user/index.ts deleted file mode 100644 index 278fbbcc..00000000 --- a/packages/core/src:old/user/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { z } from "zod"; -import databaseClient from "../database" -import { fn } from "../utils"; -import { Common } from "../common"; -import { Examples } from "../examples"; - -export module Users { - export const Info = z - .object({ - id: z.string().openapi({ - description: Common.IdDescription, - example: Examples.User.id, - }), - email: z.string().nullable().openapi({ - description: "Email address of the user.", - example: Examples.User.email, - }), - }) - .openapi({ - ref: "User", - description: "A Nestri console user.", - example: Examples.User, - }); - - export const fromEmail = fn(z.string(), async (email) => { - const db = databaseClient() - const res = await db.auth.getUser({ email }) - return res - }) - - export const create = fn(z.string(), async (email) => { - const db = databaseClient() - const token = await db.auth.createToken(email) - - return token - }) -} \ No newline at end of file diff --git a/packages/core/src:old/utils/fn.ts b/packages/core/src:old/utils/fn.ts deleted file mode 100644 index 105656b3..00000000 --- a/packages/core/src:old/utils/fn.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ZodSchema, z } from "zod"; - -export function fn< - Arg1 extends ZodSchema, - Callback extends (arg1: z.output) => any, ->(arg1: Arg1, cb: Callback) { - const result = function (input: z.input): ReturnType { - const parsed = arg1.parse(input); - return cb.apply(cb, [parsed as any]); - }; - result.schema = arg1; - return result; -} - -export function doubleFn< - Arg1 extends ZodSchema, - Arg2 extends ZodSchema, - Callback extends (arg1: z.output, arg2: z.output) => any, ->(arg1: Arg1, arg2: Arg2, cb: Callback) { - const result = function (input: z.input, input2: z.input): ReturnType { - const parsed = arg1.parse(input); - const parsed2 = arg2.parse(input2); - return cb.apply(cb, [parsed as any, parsed2 as any]); - }; - result.schema = arg1; - return result; -} \ No newline at end of file diff --git a/packages/core/src:old/utils/id.ts b/packages/core/src:old/utils/id.ts deleted file mode 100644 index badcc0d9..00000000 --- a/packages/core/src:old/utils/id.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ulid } from "ulid"; - -export const prefixes = { - user: "usr", -} as const; - -export function createID(prefix: keyof typeof prefixes): string { - return [prefixes[prefix], ulid()].join("_"); -} \ No newline at end of file diff --git a/packages/core/src:old/utils/index.ts b/packages/core/src:old/utils/index.ts deleted file mode 100644 index 16ec78f3..00000000 --- a/packages/core/src:old/utils/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./fn" -export * from "./id" \ No newline at end of file diff --git a/packages/ui/src/fonts.tsx b/packages/ui/src/fonts.tsx index 46aaea3d..3ed240ca 100644 --- a/packages/ui/src/fonts.tsx +++ b/packages/ui/src/fonts.tsx @@ -10,10 +10,6 @@ import "@fontsource/geist-mono/400.css" import "@fontsource/geist-mono/700.css" //font-mona import "@fontsource-variable/mona-sans" -// import "@fontsource/mona-sans/500.css" -// import "@fontsource/mona-sans/600.css" -// import "@fontsource/mona-sans/700.css" -// import "@fontsource/mona-sans/800.css" //font-bricolage import '@fontsource-variable/bricolage-grotesque';