Compare commits

..

11 Commits

Author SHA1 Message Date
Aiden McClelland
81a80baed8 ts bindings refactor 2025-11-13 15:19:59 -07:00
Aiden McClelland
60ee836d44 prevent gateways from getting stuck empty 2025-11-13 15:19:30 -07:00
Aiden McClelland
aeaad3c833 Merge branch 'next/major' of github.com:Start9Labs/start-os into feature/dev-qol 2025-11-10 14:29:20 -07:00
Matt Hill
ce97827c42 CA instead of leaf for StartTunnel (#3046)
* updated docs for CA instead of cert

* generate ca instead of self-signed in start-tunnel

* Fix formatting in START-TUNNEL.md installation instructions

* Fix formatting in START-TUNNEL.md

* fix infinite loop

* add success message to install

* hide loopback and bridge gateways

---------

Co-authored-by: Aiden McClelland <me@drbonez.dev>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
2025-11-10 14:15:58 -07:00
Aiden McClelland
14fcb60670 wip: types 2025-11-10 09:45:30 -07:00
Aiden McClelland
f83df5682c bump sdk 2025-11-07 18:07:25 -07:00
Aiden McClelland
bfdab897ab misc fixes 2025-11-07 14:31:14 -07:00
Aiden McClelland
3efec07338 Include StartTunnel installation command
Added installation instructions for StartTunnel.
2025-11-07 20:00:31 +00:00
Aiden McClelland
29c97fcbb0 sdk fixes 2025-11-07 11:20:13 -07:00
Aiden McClelland
e7847d0e88 squashfs-wip 2025-11-07 03:13:54 -07:00
Aiden McClelland
68f401bfa3 Feature/start tunnel (#3037)
* fix live-build resolv.conf

* improved debuggability

* wip: start-tunnel

* fixes for trixie and tor

* non-free-firmware on trixie

* wip

* web server WIP

* wip: tls refactor

* FE patchdb, mocks, and most endpoints

* fix editing records and patch mocks

* refactor complete

* finish api

* build and formatter update

* minor change toi viewing addresses and fix build

* fixes

* more providers

* endpoint for getting config

* fix tests

* api fixes

* wip: separate port forward controller into parts

* simplify iptables rules

* bump sdk

* misc fixes

* predict next subnet and ip, use wan ips, and form validation

* refactor: break big components apart and address todos (#3043)

* refactor: break big components apart and address todos

* starttunnel readme, fix pf mocks, fix adding tor domain in startos

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>

* better tui

* tui tweaks

* fix: address comments

* better regex for subnet

* fixes

* better validation

* handle rpc errors

* build fixes

* fix: address comments (#3044)

* fix: address comments

* fix unread notification mocks

* fix row click for notification

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>

* fix raspi build

* fix build

* fix build

* fix build

* fix build

* try to fix build

* fix tests

* fix tests

* fix rsync tests

* delete useless effectful test

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>
Co-authored-by: Alex Inkin <alexander@inkin.ru>
2025-11-07 10:12:05 +00:00
390 changed files with 3854 additions and 1996 deletions

View File

@@ -283,10 +283,7 @@ sdk/base/lib/osBindings/index.ts: $(shell if [ "$(REBUILD_TYPES)" -ne 0 ]; then
touch sdk/base/lib/osBindings/index.ts touch sdk/base/lib/osBindings/index.ts
core/startos/bindings/index.ts: $(call ls-files, core) $(ENVIRONMENT_FILE) core/startos/bindings/index.ts: $(call ls-files, core) $(ENVIRONMENT_FILE)
rm -rf core/startos/bindings
./core/build-ts.sh ./core/build-ts.sh
ls core/startos/bindings/*.ts | sed 's/core\/startos\/bindings\/\([^.]*\)\.ts/export { \1 } from ".\/\1";/g' | grep -v '"./index"' | tee core/startos/bindings/index.ts
npm --prefix sdk exec -- prettier --config ./sdk/base/package.json -w ./core/startos/bindings/*.ts
touch core/startos/bindings/index.ts touch core/startos/bindings/index.ts
sdk/dist/package.json sdk/baseDist/package.json: $(call ls-files, sdk) sdk/base/lib/osBindings/index.ts sdk/dist/package.json sdk/baseDist/package.json: $(call ls-files, sdk) sdk/base/lib/osBindings/index.ts

View File

@@ -6,6 +6,14 @@ You can think of StartTunnel as "virtual router in the cloud"
Use it for private, remote access, to self-hosted services running on a personal server, or to expose self-hosted services to the public Internet without revealing the host server's IP address. Use it for private, remote access, to self-hosted services running on a personal server, or to expose self-hosted services to the public Internet without revealing the host server's IP address.
## Features
- **Create Subnets**: Each subnet creates a private, virtual local area network (VLAN), similar to the LAN created by a home router.
- **Add Devices**: When you add a device (server, phone, laptop) to a subnet, it receives a LAN IP address on that subnet as well as a unique Wireguard config that must be copied, downloaded, or scanned into the device.
- **Forward Ports**: Forwarding a port creates a "reverse tunnel", exposing a specific port on a specific device to the public Internet.
## Installation ## Installation
1. Rent a low cost VPS. For most use cases, the cheapest option should be enough. 1. Rent a low cost VPS. For most use cases, the cheapest option should be enough.
@@ -20,15 +28,11 @@ Use it for private, remote access, to self-hosted services running on a personal
1. Install StartTunnel: 1. Install StartTunnel:
@TODO ```sh
TMP_DIR=$(mktemp -d) && (cd $TMP_DIR && wget https://github.com/Start9Labs/start-os/releases/download/v0.4.0-alpha.12/start-tunnel-0.4.0-alpha.12-68f401b_$(uname -m).deb && apt-get install -y ./start-tunnel-0.4.0-alpha.12-68f401b_$(uname -m).deb) && rm -rf $TMP_DIR && systemctl start start-tunneld && echo "Installation Succeeded"
```
## Features 5. [Initialize the web interface](#web-interface) (recommended)
- **Create Subnets**: Each subnet creates a private, virtual local area network (VLAN), similar to the LAN created by a home router.
- **Add Devices**: When you add a device (server, phone, laptop) to a subnet, it receives a LAN IP address on that subnet as well as a unique Wireguard config that must be copied, downloaded, or scanned into the device.
- **Forward Ports**: Forwarding a port creates a "reverse tunnel", exposing a specific port on a specific device to the public Internet.
## CLI ## CLI
@@ -52,8 +56,8 @@ If you choose to enable the web interface (recommended in most cases), StartTunn
1. Select whether to autogenerate a self-signed certificate or provide your own certificate and key. If you choose to autogenerate, you will be asked to list all IP addresses and domains for which to sign the certificate. For example, if you intend to access your StartTunnel web UI at a domain, include the domain in the list. 1. Select whether to autogenerate a self-signed certificate or provide your own certificate and key. If you choose to autogenerate, you will be asked to list all IP addresses and domains for which to sign the certificate. For example, if you intend to access your StartTunnel web UI at a domain, include the domain in the list.
1. You will receive a success message that the webserver is running at the chosen IP:port, as well as your SSL certificate and an autogenerated UI password. 1. You will receive a success message with 3 pieces of information:
1. If not already, trust the certificate in your system keychain and/or browser. - <https://IP:port>: the URL where you can reach your personal web interface.
- Password: an autogenerated password for your interface. If you lose/forget it, you can reset using the CLI.
1. If you lose/forget your password, you can reset it using the CLI. - Root Certificate Authority: the Root CA of your StartTunnel instance. If not already, trust it in your browser or system keychain.

View File

@@ -38,7 +38,7 @@
}, },
"../sdk/dist": { "../sdk/dist": {
"name": "@start9labs/start-sdk", "name": "@start9labs/start-sdk",
"version": "0.4.0-beta.42", "version": "0.4.0-beta.43",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@iarna/toml": "^3.0.0", "@iarna/toml": "^3.0.0",

265
core/Cargo.lock generated
View File

@@ -270,7 +270,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [ dependencies = [
"async-trait", "async-trait",
"cfg-if", "cfg-if",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"educe", "educe",
@@ -367,7 +367,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"synstructure", "synstructure",
] ]
@@ -379,7 +379,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"synstructure", "synstructure",
] ]
@@ -391,7 +391,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -459,9 +459,9 @@ dependencies = [
[[package]] [[package]]
name = "async-compression" name = "async-compression"
version = "0.4.32" version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0" checksum = "93c1f86859c1af3d514fa19e8323147ff10ea98684e6c7b307912509f50e67b2"
dependencies = [ dependencies = [
"compression-codecs", "compression-codecs",
"compression-core", "compression-core",
@@ -567,7 +567,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -634,7 +634,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -651,7 +651,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -989,7 +989,7 @@ dependencies = [
"regex", "regex",
"rustc-hash", "rustc-hash",
"shlex", "shlex",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -1107,7 +1107,7 @@ checksum = "e0b121a9fe0df916e362fb3271088d071159cdf11db0e4182d02152850756eff"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -1247,9 +1247,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.44" version = "1.2.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver", "jobserver",
@@ -1404,7 +1404,7 @@ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -1497,9 +1497,9 @@ dependencies = [
[[package]] [[package]]
name = "compression-codecs" name = "compression-codecs"
version = "0.4.31" version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" checksum = "680dc087785c5230f8e8843e2e57ac7c1c90488b6a91b88caa265410568f441b"
dependencies = [ dependencies = [
"brotli", "brotli",
"compression-core", "compression-core",
@@ -1512,9 +1512,9 @@ dependencies = [
[[package]] [[package]]
name = "compression-core" name = "compression-core"
version = "0.4.29" version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb" checksum = "3a9b614a5787ef0c8802a55766480563cb3a93b435898c422ed2a359cf811582"
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
@@ -2011,7 +2011,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2059,7 +2059,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim 0.11.1", "strsim 0.11.1",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2081,7 +2081,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [ dependencies = [
"darling_core 0.21.3", "darling_core 0.21.3",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2138,7 +2138,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2151,44 +2151,16 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[package]]
name = "derive-deftly"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8ea84d0109517cc2253d4a679bdda1e8989e9bd86987e9e4f75ffdda0095fd1"
dependencies = [
"derive-deftly-macros 0.14.6",
"heck 0.5.0",
]
[[package]] [[package]]
name = "derive-deftly" name = "derive-deftly"
version = "1.2.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957bb73a3a9c0bbcac67e129b81954661b3cfcb9e28873d8441f91b54852e77a" checksum = "957bb73a3a9c0bbcac67e129b81954661b3cfcb9e28873d8441f91b54852e77a"
dependencies = [ dependencies = [
"derive-deftly-macros 1.2.0", "derive-deftly-macros",
"heck 0.5.0", "heck 0.5.0",
] ]
[[package]]
name = "derive-deftly-macros"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357422a457ccb850dc8f1c1680e0670079560feaad6c2e247e3f345c4fab8a3f"
dependencies = [
"heck 0.5.0",
"indexmap 2.12.0",
"itertools 0.14.0",
"proc-macro-crate",
"proc-macro2",
"quote",
"sha3 0.10.8",
"strum",
"syn 2.0.108",
"void",
]
[[package]] [[package]]
name = "derive-deftly-macros" name = "derive-deftly-macros"
version = "1.2.0" version = "1.2.0"
@@ -2203,7 +2175,7 @@ dependencies = [
"quote", "quote",
"sha3 0.10.8", "sha3 0.10.8",
"strum", "strum",
"syn 2.0.108", "syn 2.0.110",
"void", "void",
] ]
@@ -2215,7 +2187,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2259,7 +2231,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustc_version", "rustc_version",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2280,7 +2252,7 @@ dependencies = [
"convert_case 0.7.1", "convert_case 0.7.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"unicode-xid", "unicode-xid",
] ]
@@ -2370,7 +2342,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2451,7 +2423,7 @@ dependencies = [
"proc-macro-error2", "proc-macro-error2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2645,7 +2617,7 @@ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2658,7 +2630,7 @@ dependencies = [
"num-traits", "num-traits",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -2679,7 +2651,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -3113,7 +3085,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -3879,9 +3851,9 @@ dependencies = [
[[package]] [[package]]
name = "iddqd" name = "iddqd"
version = "0.3.14" version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bac5efd33e0c5eb0ac45cbd210541a214dac576896ca97ba08e16e3b1079cdd8" checksum = "dda610d939ea51890ca6c827c8365acf0a44b4b53d2ed6f371e8e7e47bc75d25"
dependencies = [ dependencies = [
"allocator-api2", "allocator-api2",
"equivalent", "equivalent",
@@ -4767,7 +4739,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -5150,7 +5122,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -5313,9 +5285,9 @@ dependencies = [
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.74" version = "0.10.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.10.0",
"cfg-if", "cfg-if",
@@ -5334,7 +5306,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -5354,9 +5326,9 @@ dependencies = [
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.110" version = "0.9.111"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@@ -5518,7 +5490,7 @@ dependencies = [
"nix 0.30.1", "nix 0.30.1",
"patch-db-macro", "patch-db-macro",
"serde", "serde",
"serde_cbor", "serde_cbor 0.11.1",
"thiserror 2.0.17", "thiserror 2.0.17",
"tokio", "tokio",
"tracing", "tracing",
@@ -5609,7 +5581,7 @@ dependencies = [
"pest_meta", "pest_meta",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -5683,7 +5655,7 @@ dependencies = [
"phf_shared 0.11.3", "phf_shared 0.11.3",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -5696,7 +5668,7 @@ dependencies = [
"phf_shared 0.13.1", "phf_shared 0.13.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -5740,7 +5712,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -5947,7 +5919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -6012,7 +5984,7 @@ dependencies = [
"proc-macro-error-attr2", "proc-macro-error-attr2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -6076,7 +6048,7 @@ checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -6099,7 +6071,7 @@ dependencies = [
"itertools 0.14.0", "itertools 0.14.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -6148,14 +6120,14 @@ dependencies = [
[[package]] [[package]]
name = "pwd-grp" name = "pwd-grp"
version = "1.0.0" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94fdf3867b7f2889a736f0022ea9386766280d2cca4bdbe41629ada9e4f3b8f" checksum = "0e2023f41b5fcb7c30eb5300a5733edfaa9e0e0d502d51b586f65633fd39e40c"
dependencies = [ dependencies = [
"derive-deftly 0.14.6", "derive-deftly",
"libc", "libc",
"paste", "paste",
"thiserror 1.0.69", "thiserror 2.0.17",
] ]
[[package]] [[package]]
@@ -6248,9 +6220,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.41" version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -6577,7 +6549,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -6719,7 +6691,7 @@ dependencies = [
[[package]] [[package]]
name = "rpc-toolkit" name = "rpc-toolkit"
version = "0.3.2" version = "0.3.2"
source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master#068db905ee38a7da97cc4a43b806409204e73723" source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master#2dd2832e043eb5380c91cf80f3e78a700d204be3"
dependencies = [ dependencies = [
"async-stream", "async-stream",
"async-trait", "async-trait",
@@ -6736,10 +6708,12 @@ dependencies = [
"pin-project", "pin-project",
"reqwest", "reqwest",
"serde", "serde",
"serde_cbor 0.11.2",
"serde_json", "serde_json",
"thiserror 2.0.17", "thiserror 2.0.17",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"ts-rs",
"url", "url",
"yajrc", "yajrc",
] ]
@@ -7045,9 +7019,9 @@ dependencies = [
[[package]] [[package]]
name = "schemars" name = "schemars"
version = "1.0.5" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1317c3bf3e7df961da95b0a56a172a02abead31276215a0497241a7624b487ce" checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289"
dependencies = [ dependencies = [
"dyn-clone", "dyn-clone",
"ref-cast", "ref-cast",
@@ -7174,6 +7148,16 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half 1.8.3",
"serde",
]
[[package]] [[package]]
name = "serde_core" name = "serde_core"
version = "1.0.228" version = "1.0.228"
@@ -7191,7 +7175,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -7248,7 +7232,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -7293,7 +7277,7 @@ dependencies = [
"indexmap 1.9.3", "indexmap 1.9.3",
"indexmap 2.12.0", "indexmap 2.12.0",
"schemars 0.9.0", "schemars 0.9.0",
"schemars 1.0.5", "schemars 1.1.0",
"serde_core", "serde_core",
"serde_json", "serde_json",
"serde_with_macros", "serde_with_macros",
@@ -7309,7 +7293,7 @@ dependencies = [
"darling 0.21.3", "darling 0.21.3",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -7727,7 +7711,7 @@ dependencies = [
"quote", "quote",
"sqlx-core", "sqlx-core",
"sqlx-macros-core", "sqlx-macros-core",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -7748,7 +7732,7 @@ dependencies = [
"sha2 0.10.9", "sha2 0.10.9",
"sqlx-core", "sqlx-core",
"sqlx-postgres", "sqlx-postgres",
"syn 2.0.108", "syn 2.0.110",
"tokio", "tokio",
"url", "url",
] ]
@@ -7813,7 +7797,7 @@ dependencies = [
"quote", "quote",
"regex-syntax 0.6.29", "regex-syntax 0.6.29",
"strsim 0.11.1", "strsim 0.11.1",
"syn 2.0.108", "syn 2.0.110",
"unicode-width 0.1.14", "unicode-width 0.1.14",
] ]
@@ -8114,7 +8098,7 @@ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -8157,9 +8141,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.108" version = "2.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -8183,7 +8167,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -8351,7 +8335,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -8362,7 +8346,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -8487,7 +8471,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -8723,7 +8707,7 @@ name = "tor-async-utils"
version = "0.33.0" version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700" source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [ dependencies = [
"derive-deftly 1.2.0", "derive-deftly",
"educe", "educe",
"futures", "futures",
"oneshot-fused-workaround", "oneshot-fused-workaround",
@@ -8757,7 +8741,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700" source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [ dependencies = [
"bytes", "bytes",
"derive-deftly 1.2.0", "derive-deftly",
"digest 0.10.7", "digest 0.10.7",
"educe", "educe",
"getrandom 0.3.4", "getrandom 0.3.4",
@@ -8777,7 +8761,7 @@ dependencies = [
"bitflags 2.10.0", "bitflags 2.10.0",
"bytes", "bytes",
"caret", "caret",
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"educe", "educe",
"itertools 0.14.0", "itertools 0.14.0",
@@ -8868,7 +8852,7 @@ dependencies = [
"async-trait", "async-trait",
"bounded-vec-deque", "bounded-vec-deque",
"cfg-if", "cfg-if",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"downcast-rs 2.0.2", "downcast-rs 2.0.2",
@@ -8915,7 +8899,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [ dependencies = [
"amplify", "amplify",
"cfg-if", "cfg-if",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"educe", "educe",
"either", "either",
@@ -9078,7 +9062,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [ dependencies = [
"amplify", "amplify",
"base64ct", "base64ct",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"dyn-clone", "dyn-clone",
@@ -9118,7 +9102,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700" source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"educe", "educe",
"either", "either",
@@ -9162,7 +9146,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [ dependencies = [
"cipher 0.4.4", "cipher 0.4.4",
"data-encoding", "data-encoding",
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"digest 0.10.7", "digest 0.10.7",
"equix", "equix",
@@ -9196,7 +9180,7 @@ dependencies = [
"async-trait", "async-trait",
"base64ct", "base64ct",
"cfg-if", "cfg-if",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"digest 0.10.7", "digest 0.10.7",
@@ -9249,7 +9233,7 @@ name = "tor-key-forge"
version = "0.33.0" version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700" source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [ dependencies = [
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"downcast-rs 2.0.2", "downcast-rs 2.0.2",
"paste", "paste",
@@ -9272,7 +9256,7 @@ dependencies = [
"amplify", "amplify",
"arrayvec 0.7.6", "arrayvec 0.7.6",
"cfg-if", "cfg-if",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"downcast-rs 2.0.2", "downcast-rs 2.0.2",
@@ -9311,7 +9295,7 @@ dependencies = [
"base64ct", "base64ct",
"by_address", "by_address",
"caret", "caret",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"hex", "hex",
@@ -9339,7 +9323,7 @@ dependencies = [
"ctr 0.9.2", "ctr 0.9.2",
"curve25519-dalek 4.1.3", "curve25519-dalek 4.1.3",
"der-parser 10.0.0", "der-parser 10.0.0",
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"digest 0.10.7", "digest 0.10.7",
"ed25519-dalek 2.2.0", "ed25519-dalek 2.2.0",
@@ -9387,7 +9371,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700" source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"dyn-clone", "dyn-clone",
"educe", "educe",
@@ -9451,7 +9435,7 @@ dependencies = [
"base64ct", "base64ct",
"bitflags 2.10.0", "bitflags 2.10.0",
"cipher 0.4.4", "cipher 0.4.4",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"digest 0.10.7", "digest 0.10.7",
@@ -9494,7 +9478,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700" source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [ dependencies = [
"amplify", "amplify",
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"filetime", "filetime",
"fs-mistrust", "fs-mistrust",
@@ -9530,7 +9514,7 @@ dependencies = [
"cipher 0.4.4", "cipher 0.4.4",
"coarsetime", "coarsetime",
"criterion-cycles-per-byte", "criterion-cycles-per-byte",
"derive-deftly 1.2.0", "derive-deftly",
"derive_builder_fork_arti", "derive_builder_fork_arti",
"derive_more 2.0.1", "derive_more 2.0.1",
"digest 0.10.7", "digest 0.10.7",
@@ -9645,7 +9629,7 @@ dependencies = [
"amplify", "amplify",
"assert_matches", "assert_matches",
"async-trait", "async-trait",
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"educe", "educe",
"futures", "futures",
@@ -9672,7 +9656,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [ dependencies = [
"amplify", "amplify",
"caret", "caret",
"derive-deftly 1.2.0", "derive-deftly",
"educe", "educe",
"safelog", "safelog",
"subtle", "subtle",
@@ -9686,7 +9670,7 @@ name = "tor-units"
version = "0.33.0" version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700" source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [ dependencies = [
"derive-deftly 1.2.0", "derive-deftly",
"derive_more 2.0.1", "derive_more 2.0.1",
"serde", "serde",
"thiserror 2.0.17", "thiserror 2.0.17",
@@ -9811,7 +9795,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -9902,7 +9886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -9917,6 +9901,7 @@ version = "9.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c" checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c"
dependencies = [ dependencies = [
"chrono",
"thiserror 1.0.69", "thiserror 1.0.69",
"ts-rs-macros", "ts-rs-macros",
] ]
@@ -9929,7 +9914,7 @@ checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"termcolor", "termcolor",
] ]
@@ -9986,7 +9971,7 @@ checksum = "1ecb9ecf7799210407c14a8cfdfe0173365780968dc57973ed082211958e0b18"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -10214,7 +10199,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -10237,7 +10222,7 @@ checksum = "de41688745bbd6ed24e2f4923026911b523f0c057e10f86f44652a20e65555ce"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -10364,7 +10349,7 @@ dependencies = [
"bumpalo", "bumpalo",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@@ -10645,7 +10630,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -10656,7 +10641,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -11245,7 +11230,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"synstructure", "synstructure",
] ]
@@ -11292,7 +11277,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"zbus_names", "zbus_names",
"zvariant", "zvariant",
"zvariant_utils", "zvariant_utils",
@@ -11327,7 +11312,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -11347,7 +11332,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"synstructure", "synstructure",
] ]
@@ -11368,7 +11353,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -11402,7 +11387,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
] ]
[[package]] [[package]]
@@ -11456,7 +11441,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.108", "syn 2.0.110",
"zvariant_utils", "zvariant_utils",
] ]
@@ -11469,6 +11454,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn 2.0.108", "syn 2.0.110",
"winnow", "winnow",
] ]

View File

@@ -1,2 +1,5 @@
[build] [build]
pre-build = ["apt-get update && apt-get install -y rsync"] pre-build = ["apt-get update && apt-get install -y rsync"]
[build.env]
passthrough = ["RUST_BACKTRACE"]

View File

@@ -24,6 +24,9 @@ if [ "$ARCH" = "riscv64" ]; then
fi fi
cd .. cd ..
rm -rf core/startos/bindings/
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')" FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
RUSTFLAGS="" RUSTFLAGS=""
if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
@@ -32,3 +35,15 @@ fi
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features test,$FEATURES --locked 'export_bindings_' cross test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features test,$FEATURES --locked 'export_bindings_'
cd core/startos/bindings
for folder in $(find . -type d); do
(
cd $folder
find . -name '*.ts' -maxdepth 1 | sed 's/\.\/\([^.]*\)\.ts/export * from ".\/\1";/g' | grep -v '"./index"' | tee ./index.ts
find . -mindepth 1 -maxdepth 1 -type d | sed 's/\.\/\([^.]*\)/export * as \1 from ".\/\1";/g' | grep -v '"./index"' | tee -a ./index.ts
)
done
find . -name '*.ts' | xargs -P $(nproc) -I % npm --prefix ../../../sdk exec -- prettier --config ../../../sdk/base/package.json -w %

View File

@@ -8,7 +8,7 @@ use ts_rs::TS;
use crate::{FromStrParser, Id}; use crate::{FromStrParser, Id};
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, TS)] #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, TS)]
#[ts(export, type = "string")] #[ts(type = "string")]
pub struct ServiceInterfaceId(Id); pub struct ServiceInterfaceId(Id);
impl From<Id> for ServiceInterfaceId { impl From<Id> for ServiceInterfaceId {
fn from(id: Id) -> Self { fn from(id: Id) -> Self {

View File

@@ -280,7 +280,7 @@ tracing-error = "0.2.0"
tracing-futures = "0.2.5" tracing-futures = "0.2.5"
tracing-journald = "0.3.0" tracing-journald = "0.3.0"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
ts-rs = "9.0.1" ts-rs = { version = "9.0.1", features = ["chrono-impl"] }
typed-builder = "0.21.0" typed-builder = "0.21.0"
unix-named-pipe = "0.2.0" unix-named-pipe = "0.2.0"
url = { version = "2.4.1", features = ["serde"] } url = { version = "2.4.1", features = ["serde"] }

View File

@@ -4,7 +4,7 @@ use clap::{CommandFactory, FromArgMatches, Parser};
pub use models::ActionId; pub use models::ActionId;
use models::{PackageId, ReplayId}; use models::{PackageId, ReplayId};
use qrcode::QrCode; use qrcode::QrCode;
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tracing::instrument; use tracing::instrument;
use ts_rs::TS; use ts_rs::TS;
@@ -14,9 +14,22 @@ use crate::db::model::package::TaskSeverity;
use crate::prelude::*; use crate::prelude::*;
use crate::rpc_continuations::Guid; use crate::rpc_continuations::Guid;
use crate::util::serde::{ use crate::util::serde::{
HandlerExtSerde, StdinDeserializable, WithIoFormat, display_serializable, display_serializable, HandlerExtSerde, StdinDeserializable, WithIoFormat,
}; };
#[test]
fn export_bindings_action() {
use crate::db::model::package::{ActionMetadata, Task};
const OUT_DIR: &str = "./bindings/action";
ActionId::export_all_to(OUT_DIR).unwrap();
ActionInput::export_all_to(OUT_DIR).unwrap();
ActionResult::export_all_to(OUT_DIR).unwrap();
ActionMetadata::export_all_to(OUT_DIR).unwrap();
Task::export_all_to(OUT_DIR).unwrap();
}
pub fn action_api<C: Context>() -> ParentHandler<C> { pub fn action_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new() ParentHandler::new()
.subcommand( .subcommand(
@@ -49,7 +62,6 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
} }
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ActionInput { pub struct ActionInput {
#[serde(default)] #[serde(default)]
@@ -86,7 +98,6 @@ pub async fn get_action_input(
#[derive(Debug, Serialize, Deserialize, TS)] #[derive(Debug, Serialize, Deserialize, TS)]
#[serde(tag = "version")] #[serde(tag = "version")]
#[ts(export)]
pub enum ActionResult { pub enum ActionResult {
#[serde(rename = "0")] #[serde(rename = "0")]
V0(ActionResultV0), V0(ActionResultV0),

View File

@@ -70,7 +70,6 @@ pub async fn write_shadow(password: &str) -> Result<(), Error> {
#[derive(Clone, Serialize, Deserialize, TS)] #[derive(Clone, Serialize, Deserialize, TS)]
#[serde(untagged)] #[serde(untagged)]
#[ts(export)]
pub enum PasswordType { pub enum PasswordType {
EncryptedWire(EncryptedWire), EncryptedWire(EncryptedWire),
String(String), String(String),
@@ -149,14 +148,6 @@ where
.no_display() .no_display()
.with_about("Reset password"), .with_about("Reset password"),
) )
.subcommand(
"get-pubkey",
from_fn_async(get_pubkey)
.with_metadata("authenticated", Value::Bool(false))
.no_display()
.with_about("Get public key derived from server private key")
.with_call_remote::<CliContext>(),
)
} }
#[test] #[test]
@@ -216,7 +207,6 @@ pub fn check_password(hash: &str, password: &str) -> Result<(), Error> {
#[derive(Deserialize, Serialize, TS)] #[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct LoginParams { pub struct LoginParams {
password: String, password: String,
#[ts(skip)] #[ts(skip)]
@@ -294,7 +284,6 @@ pub async fn logout<C: AuthContext>(
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Session { pub struct Session {
#[ts(type = "string")] #[ts(type = "string")]
pub logged_in: DateTime<Utc>, pub logged_in: DateTime<Utc>,
@@ -305,7 +294,6 @@ pub struct Session {
#[derive(Deserialize, Serialize, TS)] #[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SessionList { pub struct SessionList {
#[ts(type = "string | null")] #[ts(type = "string | null")]
current: Option<InternedString>, current: Option<InternedString>,
@@ -395,7 +383,7 @@ pub async fn list<C: AuthContext>(
}) })
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
struct KillSessionId(InternedString); struct KillSessionId(InternedString);
impl KillSessionId { impl KillSessionId {

View File

@@ -36,7 +36,7 @@ impl Map for CifsTargets {
} }
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct CifsBackupTarget { pub struct CifsBackupTarget {
hostname: String, hostname: String,

View File

@@ -34,11 +34,11 @@ use crate::util::serde::{
pub mod cifs; pub mod cifs;
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(tag = "type")] #[serde(tag = "type")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")]
pub enum BackupTarget { pub enum BackupTarget {
#[serde(rename_all = "camelCase")]
Disk { Disk {
vendor: Option<String>, vendor: Option<String>,
model: Option<String>, model: Option<String>,
@@ -210,19 +210,21 @@ pub async fn list(ctx: RpcContext) -> Result<BTreeMap<BackupTargetId, BackupTarg
.collect()) .collect())
} }
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct BackupInfo { pub struct BackupInfo {
#[ts(type = "string")]
pub version: Version, pub version: Version,
pub timestamp: Option<DateTime<Utc>>, pub timestamp: Option<DateTime<Utc>>,
pub package_backups: BTreeMap<PackageId, PackageBackupInfo>, pub package_backups: BTreeMap<PackageId, PackageBackupInfo>,
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PackageBackupInfo { pub struct PackageBackupInfo {
pub title: InternedString, pub title: InternedString,
pub version: VersionString, pub version: VersionString,
#[ts(type = "string")]
pub os_version: Version, pub os_version: Version,
pub timestamp: DateTime<Utc>, pub timestamp: DateTime<Utc>,
} }

View File

@@ -40,7 +40,6 @@ lazy_static::lazy_static! {
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetupResult { pub struct SetupResult {
pub tor_addresses: Vec<String>, pub tor_addresses: Vec<String>,
#[ts(type = "string")] #[ts(type = "string")]

View File

@@ -1,7 +1,6 @@
pub mod model; pub mod model;
pub mod prelude; pub mod prelude;
use std::panic::UnwindSafe;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@@ -56,9 +55,18 @@ pub fn db<C: Context>() -> ParentHandler<C> {
"dump", "dump",
from_fn_async(cli_dump) from_fn_async(cli_dump)
.with_display_serializable() .with_display_serializable()
.no_ts()
.with_about("Filter/query db to display tables and records"), .with_about("Filter/query db to display tables and records"),
) )
.subcommand("dump", from_fn_async(dump).no_cli()) .subcommand(
"dump",
from_fn_async(dump)
.custom_ts(
DumpParams::inline_flattened(),
format!("{{ id: number; value: unknown }}"),
)
.no_cli(),
)
.subcommand( .subcommand(
"subscribe", "subscribe",
from_fn_async(subscribe) from_fn_async(subscribe)
@@ -73,6 +81,7 @@ pub fn db<C: Context>() -> ParentHandler<C> {
"apply", "apply",
from_fn_async(cli_apply) from_fn_async(cli_apply)
.no_display() .no_display()
.no_ts()
.with_about("Update a db record"), .with_about("Update a db record"),
) )
.subcommand("apply", from_fn_async(apply).no_cli()) .subcommand("apply", from_fn_async(apply).no_cli())

View File

@@ -20,7 +20,6 @@ use crate::status::MainStatus;
use crate::util::serde::{Pem, is_partial_of}; use crate::util::serde::{Pem, is_partial_of};
#[derive(Debug, Default, Deserialize, Serialize, TS)] #[derive(Debug, Default, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct AllPackageData(pub BTreeMap<PackageId, PackageDataEntry>); pub struct AllPackageData(pub BTreeMap<PackageId, PackageDataEntry>);
impl Map for AllPackageData { impl Map for AllPackageData {
type Key = PackageId; type Key = PackageId;
@@ -43,7 +42,6 @@ pub enum ManifestPreference {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(tag = "state")] #[serde(tag = "state")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub enum PackageState { pub enum PackageState {
Installing(InstallingState), Installing(InstallingState),
Restoring(InstallingState), Restoring(InstallingState),
@@ -277,7 +275,6 @@ impl Model<PackageState> {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct InstallingState { pub struct InstallingState {
pub installing_info: InstallingInfo, pub installing_info: InstallingInfo,
} }
@@ -285,7 +282,6 @@ pub struct InstallingState {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct UpdatingState { pub struct UpdatingState {
pub manifest: Manifest, pub manifest: Manifest,
pub s9pk: PathBuf, pub s9pk: PathBuf,
@@ -295,7 +291,6 @@ pub struct UpdatingState {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct InstalledState { pub struct InstalledState {
pub manifest: Manifest, pub manifest: Manifest,
} }
@@ -303,13 +298,11 @@ pub struct InstalledState {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct InstallingInfo { pub struct InstallingInfo {
pub new_manifest: Manifest, pub new_manifest: Manifest,
pub progress: FullProgress, pub progress: FullProgress,
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum AllowedStatuses { pub enum AllowedStatuses {
OnlyRunning, OnlyRunning,
@@ -344,7 +337,6 @@ pub struct ActionMetadata {
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
#[serde(rename_all_fields = "camelCase")] #[serde(rename_all_fields = "camelCase")]
pub enum ActionVisibility { pub enum ActionVisibility {
@@ -361,7 +353,6 @@ impl Default for ActionVisibility {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct PackageDataEntry { pub struct PackageDataEntry {
pub state_info: PackageState, pub state_info: PackageState,
pub s9pk: PathBuf, pub s9pk: PathBuf,
@@ -388,7 +379,6 @@ impl AsRef<PackageDataEntry> for PackageDataEntry {
} }
#[derive(Debug, Clone, Default, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Default, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct CurrentDependencies(pub BTreeMap<PackageId, CurrentDependencyInfo>); pub struct CurrentDependencies(pub BTreeMap<PackageId, CurrentDependencyInfo>);
impl CurrentDependencies { impl CurrentDependencies {
pub fn map( pub fn map(
@@ -440,7 +430,6 @@ pub enum CurrentDependencyKind {
#[derive(Clone, Debug, Deserialize, Serialize, TS, HasModel)] #[derive(Clone, Debug, Deserialize, Serialize, TS, HasModel)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
#[model = "Model<Self>"] #[model = "Model<Self>"]
pub struct TaskEntry { pub struct TaskEntry {
pub task: Task, pub task: Task,
@@ -449,7 +438,6 @@ pub struct TaskEntry {
#[derive(Clone, Debug, Deserialize, Serialize, TS, HasModel)] #[derive(Clone, Debug, Deserialize, Serialize, TS, HasModel)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
#[model = "Model<Self>"] #[model = "Model<Self>"]
pub struct Task { pub struct Task {
pub package_id: PackageId, pub package_id: PackageId,
@@ -466,7 +454,6 @@ pub struct Task {
#[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
#[ts(export)]
pub enum TaskSeverity { pub enum TaskSeverity {
Optional, Optional,
Important, Important,
@@ -480,7 +467,6 @@ impl Default for TaskSeverity {
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct TaskTrigger { pub struct TaskTrigger {
#[serde(default)] #[serde(default)]
pub once: bool, pub once: bool,
@@ -489,7 +475,6 @@ pub struct TaskTrigger {
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
#[ts(export)]
pub enum TaskCondition { pub enum TaskCondition {
InputNotMatches, InputNotMatches,
} }

View File

@@ -16,12 +16,12 @@ use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
use crate::account::AccountInfo; use crate::account::AccountInfo;
use crate::db::DbAccessByKey;
use crate::db::model::Database;
use crate::db::model::package::AllPackageData; use crate::db::model::package::AllPackageData;
use crate::db::model::Database;
use crate::db::DbAccessByKey;
use crate::net::acme::AcmeProvider; use crate::net::acme::AcmeProvider;
use crate::net::host::Host;
use crate::net::host::binding::{AddSslOptions, BindInfo, BindOptions, NetInfo}; use crate::net::host::binding::{AddSslOptions, BindInfo, BindOptions, NetInfo};
use crate::net::host::Host;
use crate::net::utils::ipv6_is_local; use crate::net::utils::ipv6_is_local;
use crate::net::vhost::AlpnInfo; use crate::net::vhost::AlpnInfo;
use crate::prelude::*; use crate::prelude::*;
@@ -33,10 +33,14 @@ use crate::util::serde::MaybeUtf8String;
use crate::version::{Current, VersionT}; use crate::version::{Current, VersionT};
use crate::{ARCH, PLATFORM}; use crate::{ARCH, PLATFORM};
#[test]
fn export_bindings_database() {
Public::export_all_to("./bindings/database/startos").unwrap();
}
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct Public { pub struct Public {
pub server_info: ServerInfo, pub server_info: ServerInfo,
pub package_data: AllPackageData, pub package_data: AllPackageData,
@@ -152,7 +156,6 @@ fn get_platform() -> InternedString {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct ServerInfo { pub struct ServerInfo {
#[serde(default = "get_arch")] #[serde(default = "get_arch")]
#[ts(type = "string")] #[ts(type = "string")]
@@ -194,7 +197,6 @@ pub struct ServerInfo {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct NetworkInfo { pub struct NetworkInfo {
pub wifi: WifiInfo, pub wifi: WifiInfo,
pub host: Host, pub host: Host,
@@ -210,7 +212,6 @@ pub struct NetworkInfo {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct DnsSettings { pub struct DnsSettings {
#[ts(type = "string[]")] #[ts(type = "string[]")]
pub dhcp_servers: VecDeque<SocketAddr>, pub dhcp_servers: VecDeque<SocketAddr>,
@@ -221,7 +222,6 @@ pub struct DnsSettings {
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct NetworkInterfaceInfo { pub struct NetworkInterfaceInfo {
pub name: Option<InternedString>, pub name: Option<InternedString>,
pub public: Option<bool>, pub public: Option<bool>,
@@ -269,7 +269,6 @@ impl NetworkInterfaceInfo {
} }
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize, TS, HasModel)] #[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize, TS, HasModel)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
pub struct IpInfo { pub struct IpInfo {
@@ -289,7 +288,6 @@ pub struct IpInfo {
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum NetworkInterfaceType { pub enum NetworkInterfaceType {
Ethernet, Ethernet,
@@ -302,7 +300,6 @@ pub enum NetworkInterfaceType {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct AcmeSettings { pub struct AcmeSettings {
pub contact: Vec<String>, pub contact: Vec<String>,
} }
@@ -323,14 +320,12 @@ impl DbAccessByKey<AcmeSettings> for Database {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct DomainSettings { pub struct DomainSettings {
pub gateway: GatewayId, pub gateway: GatewayId,
} }
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct BackupProgress { pub struct BackupProgress {
pub complete: bool, pub complete: bool,
} }
@@ -338,7 +333,6 @@ pub struct BackupProgress {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct ServerStatus { pub struct ServerStatus {
pub backup_progress: Option<BTreeMap<PackageId, BackupProgress>>, pub backup_progress: Option<BTreeMap<PackageId, BackupProgress>>,
pub updated: bool, pub updated: bool,
@@ -352,7 +346,6 @@ pub struct ServerStatus {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct WifiInfo { pub struct WifiInfo {
pub enabled: bool, pub enabled: bool,
pub interface: Option<String>, pub interface: Option<String>,
@@ -364,7 +357,6 @@ pub struct WifiInfo {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ServerSpecs { pub struct ServerSpecs {
pub cpu: String, pub cpu: String,
pub disk: String, pub disk: String,

View File

@@ -10,6 +10,7 @@ use patch_db::value::InternedString;
pub use patch_db::{HasModel, MutateResult, PatchDb}; pub use patch_db::{HasModel, MutateResult, PatchDb};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::prelude::*; use crate::prelude::*;
@@ -479,6 +480,24 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for JsonKey<T> {
)) ))
} }
} }
impl<T> TS for JsonKey<T> {
type WithoutGenerics = JsonKey<ts_rs::Dummy>;
fn decl() -> String {
format!("type {} = string", Self::name())
}
fn decl_concrete() -> String {
Self::decl()
}
fn name() -> String {
"JsonKey".into()
}
fn inline() -> String {
"string".into()
}
fn inline_flattened() -> String {
Self::inline()
}
}
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct WithTimeData<T> { pub struct WithTimeData<T> {

View File

@@ -6,13 +6,23 @@ use models::PackageId;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
use crate::Error;
use crate::prelude::*; use crate::prelude::*;
use crate::util::PathOrUrl; use crate::util::PathOrUrl;
use crate::Error;
#[test]
fn export_bindings_dependencies() {
use crate::service::effects::dependency::{CheckDependenciesResult, DependencyRequirement};
const OUT_DIR: &str = "./bindings/dependencies";
PackageId::export_all_to(OUT_DIR).unwrap();
DependencyRequirement::export_all_to(OUT_DIR).unwrap();
CheckDependenciesResult::export_all_to(OUT_DIR).unwrap();
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct Dependencies(pub BTreeMap<PackageId, DepInfo>); pub struct Dependencies(pub BTreeMap<PackageId, DepInfo>);
impl Map for Dependencies { impl Map for Dependencies {
type Key = PackageId; type Key = PackageId;
@@ -37,7 +47,7 @@ pub struct DepInfo {
impl TS for DepInfo { impl TS for DepInfo {
type WithoutGenerics = Self; type WithoutGenerics = Self;
fn decl() -> String { fn decl() -> String {
format!("type {} = {}", Self::name(), Self::inline()) format!("type {} = {}", Self::name(), Self::inline_flattened())
} }
fn decl_concrete() -> String { fn decl_concrete() -> String {
Self::decl() Self::decl()
@@ -64,7 +74,6 @@ impl TS for DepInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum MetadataSrc { pub enum MetadataSrc {
Metadata(Metadata), Metadata(Metadata),
S9pk(Option<PathOrUrl>), // backwards compatibility S9pk(Option<PathOrUrl>), // backwards compatibility
@@ -72,7 +81,6 @@ pub enum MetadataSrc {
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Metadata { pub struct Metadata {
pub title: InternedString, pub title: InternedString,
pub icon: PathOrUrl, pub icon: PathOrUrl,

View File

@@ -2,7 +2,7 @@ use std::sync::Arc;
use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{ use rpc_toolkit::{
CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler, from_fn, from_fn_async, from_fn, from_fn_async, CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler,
}; };
use crate::context::{CliContext, DiagnosticContext, RpcContext}; use crate::context::{CliContext, DiagnosticContext, RpcContext};
@@ -17,6 +17,7 @@ pub fn diagnostic<C: Context>() -> ParentHandler<C> {
.subcommand( .subcommand(
"error", "error",
from_fn(error) from_fn(error)
.unknown_ts() // TODO: TS
.with_about("Display diagnostic error") .with_about("Display diagnostic error")
.with_call_remote::<CliContext>(), .with_call_remote::<CliContext>(),
) )
@@ -28,6 +29,7 @@ pub fn diagnostic<C: Context>() -> ParentHandler<C> {
"logs", "logs",
from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>) from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>)
.no_display() .no_display()
.no_ts()
.with_about("Display OS logs"), .with_about("Display OS logs"),
) )
.subcommand( .subcommand(
@@ -38,6 +40,7 @@ pub fn diagnostic<C: Context>() -> ParentHandler<C> {
"kernel-logs", "kernel-logs",
from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>) from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>)
.no_display() .no_display()
.no_ts()
.with_about("Display kernal logs"), .with_about("Display kernal logs"),
) )
.subcommand( .subcommand(

View File

@@ -2,6 +2,7 @@ use std::path::Path;
use color_eyre::eyre::eyre; use color_eyre::eyre::eyre;
use tokio::process::Command; use tokio::process::Command;
use ts_rs::TS;
use crate::Error; use crate::Error;
use crate::disk::fsck::btrfs::{btrfs_check_readonly, btrfs_check_repair}; use crate::disk::fsck::btrfs::{btrfs_check_readonly, btrfs_check_repair};
@@ -11,7 +12,7 @@ use crate::util::Invoke;
pub mod btrfs; pub mod btrfs;
pub mod ext4; pub mod ext4;
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS)]
#[must_use] #[must_use]
pub struct RequiresReboot(pub bool); pub struct RequiresReboot(pub bool);
impl std::ops::BitOrAssign for RequiresReboot { impl std::ops::BitOrAssign for RequiresReboot {

View File

@@ -12,7 +12,6 @@ use crate::prelude::*;
use crate::util::io::create_file; use crate::util::io::create_file;
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum FileType { pub enum FileType {
File, File,

View File

@@ -13,6 +13,7 @@ use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::process::Command; use tokio::process::Command;
use tracing::instrument; use tracing::instrument;
use ts_rs::TS;
use super::mount::filesystem::ReadOnly; use super::mount::filesystem::ReadOnly;
use super::mount::filesystem::block_dev::BlockDev; use super::mount::filesystem::block_dev::BlockDev;
@@ -24,14 +25,14 @@ use crate::util::Invoke;
use crate::util::serde::IoFormat; use crate::util::serde::IoFormat;
use crate::{Error, ResultExt as _}; use crate::{Error, ResultExt as _};
#[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "kebab-case")]
pub enum PartitionTable { pub enum PartitionTable {
Mbr, Mbr,
Gpt, Gpt,
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct DiskInfo { pub struct DiskInfo {
pub logicalname: PathBuf, pub logicalname: PathBuf,
@@ -43,7 +44,7 @@ pub struct DiskInfo {
pub guid: Option<String>, pub guid: Option<String>,
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PartitionInfo { pub struct PartitionInfo {
pub logicalname: PathBuf, pub logicalname: PathBuf,
@@ -54,10 +55,11 @@ pub struct PartitionInfo {
pub guid: Option<String>, pub guid: Option<String>,
} }
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct StartOsRecoveryInfo { pub struct StartOsRecoveryInfo {
pub hostname: Hostname, pub hostname: Hostname,
#[ts(type = "string")]
pub version: exver::Version, pub version: exver::Version,
pub timestamp: DateTime<Utc>, pub timestamp: DateTime<Utc>,
pub password_hash: Option<String>, pub password_hash: Option<String>,

View File

@@ -1,12 +1,14 @@
use imbl_value::InternedString; use imbl_value::InternedString;
use lazy_format::lazy_format; use lazy_format::lazy_format;
use rand::{Rng, rng}; use rand::{Rng, rng};
use serde::{Deserialize, Serialize};
use tokio::process::Command; use tokio::process::Command;
use tracing::instrument; use tracing::instrument;
use ts_rs::TS;
use crate::util::Invoke; use crate::util::Invoke;
use crate::{Error, ErrorKind}; use crate::{Error, ErrorKind};
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
pub struct Hostname(pub InternedString); pub struct Hostname(pub InternedString);
lazy_static::lazy_static! { lazy_static::lazy_static! {

View File

@@ -8,7 +8,7 @@ use const_format::formatcp;
use futures::{StreamExt, TryStreamExt}; use futures::{StreamExt, TryStreamExt};
use itertools::Itertools; use itertools::Itertools;
use models::ResultExt; use models::ResultExt;
use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, Empty, HandlerArgs, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::process::Command; use tokio::process::Command;
use tracing::instrument; use tracing::instrument;
@@ -17,8 +17,8 @@ use ts_rs::TS;
use crate::account::AccountInfo; use crate::account::AccountInfo;
use crate::context::config::ServerConfig; use crate::context::config::ServerConfig;
use crate::context::{CliContext, InitContext, RpcContext}; use crate::context::{CliContext, InitContext, RpcContext};
use crate::db::model::Database;
use crate::db::model::public::ServerStatus; use crate::db::model::public::ServerStatus;
use crate::db::model::Database;
use crate::developer::OS_DEVELOPER_KEY_PATH; use crate::developer::OS_DEVELOPER_KEY_PATH;
use crate::hostname::Hostname; use crate::hostname::Hostname;
use crate::middleware::auth::AuthContext; use crate::middleware::auth::AuthContext;
@@ -35,10 +35,10 @@ use crate::rpc_continuations::{Guid, RpcContinuation};
use crate::s9pk::v2::pack::{CONTAINER_DATADIR, CONTAINER_TOOL}; use crate::s9pk::v2::pack::{CONTAINER_DATADIR, CONTAINER_TOOL};
use crate::ssh::SSH_DIR; use crate::ssh::SSH_DIR;
use crate::system::{get_mem_info, sync_kiosk}; use crate::system::{get_mem_info, sync_kiosk};
use crate::util::io::{IOHook, open_file}; use crate::util::io::{open_file, IOHook};
use crate::util::lshw::lshw; use crate::util::lshw::lshw;
use crate::util::net::WebSocketExt; use crate::util::net::WebSocketExt;
use crate::util::{Invoke, cpupower}; use crate::util::{cpupower, Invoke};
use crate::{Error, MAIN_DATA, PACKAGE_DATA}; use crate::{Error, MAIN_DATA, PACKAGE_DATA};
pub const SYSTEM_REBUILD_PATH: &str = "/media/startos/config/system-rebuild"; pub const SYSTEM_REBUILD_PATH: &str = "/media/startos/config/system-rebuild";
@@ -425,6 +425,7 @@ pub fn init_api<C: Context>() -> ParentHandler<C> {
"logs", "logs",
from_fn_async(crate::logs::cli_logs::<InitContext, Empty>) from_fn_async(crate::logs::cli_logs::<InitContext, Empty>)
.no_display() .no_display()
.no_ts()
.with_about("Display OS logs"), .with_about("Display OS logs"),
) )
.subcommand( .subcommand(
@@ -435,6 +436,7 @@ pub fn init_api<C: Context>() -> ParentHandler<C> {
"kernel-logs", "kernel-logs",
from_fn_async(crate::logs::cli_logs::<InitContext, Empty>) from_fn_async(crate::logs::cli_logs::<InitContext, Empty>)
.no_display() .no_display()
.no_ts()
.with_about("Display kernel logs"), .with_about("Display kernel logs"),
) )
.subcommand("subscribe", from_fn_async(init_progress).no_cli()) .subcommand("subscribe", from_fn_async(init_progress).no_cli())
@@ -448,7 +450,6 @@ pub fn init_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct InitProgressRes { pub struct InitProgressRes {
pub progress: FullProgress, pub progress: FullProgress,
pub guid: Guid, pub guid: Guid,

View File

@@ -112,7 +112,6 @@ impl std::fmt::Display for MinMax {
#[derive(Deserialize, Serialize, TS)] #[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct InstallParams { pub struct InstallParams {
#[ts(type = "string")] #[ts(type = "string")]
registry: Url, registry: Url,
@@ -354,7 +353,6 @@ impl FromArgMatches for CliInstallParams {
} }
#[derive(Deserialize, Serialize, Parser, TS)] #[derive(Deserialize, Serialize, Parser, TS)]
#[ts(export)]
pub struct InstalledVersionParams { pub struct InstalledVersionParams {
id: PackageId, id: PackageId,
} }

View File

@@ -79,8 +79,8 @@ pub use error::{Error, ErrorKind, ResultExt};
use imbl_value::Value; use imbl_value::Value;
use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{ use rpc_toolkit::{
CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler, from_fn, from_fn_async, from_fn, from_fn_async, from_fn_async_local, from_fn_blocking, CallRemoteHandler, Context,
from_fn_async_local, from_fn_blocking, Empty, HandlerExt, ParentHandler,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
@@ -90,12 +90,11 @@ use crate::disk::fsck::RequiresReboot;
use crate::registry::context::{RegistryContext, RegistryUrlParams}; use crate::registry::context::{RegistryContext, RegistryUrlParams};
use crate::system::kiosk; use crate::system::kiosk;
use crate::tunnel::context::TunnelUrlParams; use crate::tunnel::context::TunnelUrlParams;
use crate::util::serde::{HandlerExtSerde, WithIoFormat, display_serializable}; use crate::util::serde::{display_serializable, HandlerExtSerde, WithIoFormat};
#[derive(Deserialize, Serialize, Parser, TS)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[ts(export)]
pub struct EchoParams { pub struct EchoParams {
message: String, message: String,
} }
@@ -106,7 +105,6 @@ pub fn echo<C: Context>(_: C, EchoParams { message }: EchoParams) -> Result<Stri
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum ApiState { pub enum ApiState {
Error, Error,
Initializing, Initializing,
@@ -118,6 +116,70 @@ impl std::fmt::Display for ApiState {
} }
} }
#[test]
fn export_bindings_api_helper() {
std::fs::create_dir_all("./bindings").unwrap();
std::fs::write(
"./bindings/api-helpers.ts",
rpc_toolkit::type_helpers().as_bytes(),
)
.unwrap();
}
#[test]
fn export_bindings_main_apis() {
use rpc_toolkit::HandlerTS;
use crate::context::{InstallContext, SetupContext};
std::fs::create_dir_all("./bindings").unwrap();
std::fs::write(
"./bindings/main-api.ts",
format!(
"export type MainApi = {}",
main_api::<RpcContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/init-api.ts",
format!(
"export type InitApi = {}",
main_api::<InitContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/diagnostic-api.ts",
format!(
"export type DiagnosticApi = {}",
main_api::<DiagnosticContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/setup-api.ts",
format!(
"export type SetupApi = {}",
main_api::<SetupContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/os-install-api.ts",
format!(
"export type OsInstallApi = {}",
main_api::<InstallContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
}
pub fn main_api<C: Context>() -> ParentHandler<C> { pub fn main_api<C: Context>() -> ParentHandler<C> {
let mut api = ParentHandler::new() let mut api = ParentHandler::new()
.subcommand( .subcommand(
@@ -277,7 +339,7 @@ pub fn server<C: Context>() -> ParentHandler<C> {
) )
.subcommand( .subcommand(
"logs", "logs",
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().with_about("Display OS logs"), from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().no_ts().with_about("Display OS logs"),
) )
.subcommand( .subcommand(
"kernel-logs", "kernel-logs",
@@ -285,7 +347,7 @@ pub fn server<C: Context>() -> ParentHandler<C> {
) )
.subcommand( .subcommand(
"kernel-logs", "kernel-logs",
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().with_about("Display Kernel logs"), from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().no_ts().with_about("Display Kernel logs"),
) )
.subcommand( .subcommand(
"metrics", "metrics",
@@ -297,7 +359,7 @@ pub fn server<C: Context>() -> ParentHandler<C> {
.with_call_remote::<CliContext>() .with_call_remote::<CliContext>()
) )
.subcommand( .subcommand(
"follow", "follow",
from_fn_async(system::metrics_follow) from_fn_async(system::metrics_follow)
.no_cli() .no_cli()
) )
@@ -394,6 +456,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
"install", "install",
from_fn_async_local(install::cli_install) from_fn_async_local(install::cli_install)
.no_display() .no_display()
.no_ts()
.with_about("Install a package from a marketplace or via sideloading"), .with_about("Install a package from a marketplace or via sideloading"),
) )
.subcommand( .subcommand(
@@ -497,7 +560,6 @@ pub fn package<C: Context>() -> ParentHandler<C> {
.with_about("List information related to the lxc containers i.e. CPU, Memory, Disk") .with_about("List information related to the lxc containers i.e. CPU, Memory, Disk")
.with_call_remote::<CliContext>(), .with_call_remote::<CliContext>(),
) )
.subcommand("logs", logs::package_logs())
.subcommand( .subcommand(
"logs", "logs",
logs::package_logs().with_about("Display package logs"), logs::package_logs().with_about("Display package logs"),
@@ -506,6 +568,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
"logs", "logs",
from_fn_async(logs::cli_logs::<RpcContext, logs::PackageIdParams>) from_fn_async(logs::cli_logs::<RpcContext, logs::PackageIdParams>)
.no_display() .no_display()
.no_ts()
.with_about("Display package logs"), .with_about("Display package logs"),
) )
.subcommand( .subcommand(
@@ -520,7 +583,16 @@ pub fn package<C: Context>() -> ParentHandler<C> {
.with_about("Execute commands within a service container") .with_about("Execute commands within a service container")
.no_cli(), .no_cli(),
) )
.subcommand("attach", from_fn_async(service::cli_attach).no_display()) .subcommand(
"attach",
from_fn_async(service::cli_attach).no_display().no_ts(),
)
.subcommand(
"list-subcontainers",
from_fn_async(service::list_subcontainers)
.with_about("List all subcontainers for a package")
.no_cli(),
)
.subcommand( .subcommand(
"host", "host",
net::host::host_api::<C>().with_about("Manage network hosts for a package"), net::host::host_api::<C>().with_about("Manage network hosts for a package"),

View File

@@ -15,7 +15,8 @@ use itertools::Itertools;
use models::{FromStrParser, PackageId}; use models::{FromStrParser, PackageId};
use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{ use rpc_toolkit::{
CallRemote, Context, Empty, HandlerArgs, HandlerExt, HandlerFor, ParentHandler, from_fn_async, from_fn_async, CallRemote, Context, Empty, HandlerArgs, HandlerExt, HandlerFor, LeafHandler,
ParentHandler, UnknownTS,
}; };
use serde::de::{self, DeserializeOwned}; use serde::de::{self, DeserializeOwned};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -24,15 +25,16 @@ use tokio::process::{Child, Command};
use tokio_stream::wrappers::LinesStream; use tokio_stream::wrappers::LinesStream;
use tokio_tungstenite::tungstenite::Message; use tokio_tungstenite::tungstenite::Message;
use tracing::instrument; use tracing::instrument;
use ts_rs::TS;
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::error::ResultExt; use crate::error::ResultExt;
use crate::lxc::ContainerId; use crate::lxc::ContainerId;
use crate::prelude::*; use crate::prelude::*;
use crate::rpc_continuations::{Guid, RpcContinuation, RpcContinuations}; use crate::rpc_continuations::{Guid, RpcContinuation, RpcContinuations};
use crate::util::Invoke;
use crate::util::net::WebSocketExt; use crate::util::net::WebSocketExt;
use crate::util::serde::Reversible; use crate::util::serde::Reversible;
use crate::util::Invoke;
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct LogStream { pub struct LogStream {
@@ -109,21 +111,21 @@ async fn ws_handler(
} }
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct LogResponse { pub struct LogResponse {
pub entries: Reversible<LogEntry>, pub entries: Reversible<LogEntry>,
start_cursor: Option<String>, start_cursor: Option<String>,
end_cursor: Option<String>, end_cursor: Option<String>,
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct LogFollowResponse { pub struct LogFollowResponse {
start_cursor: Option<String>, start_cursor: Option<String>,
guid: Guid, guid: Guid,
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct LogEntry { pub struct LogEntry {
timestamp: DateTime<Utc>, timestamp: DateTime<Utc>,
@@ -142,7 +144,7 @@ impl std::fmt::Display for LogEntry {
} }
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug, TS)]
pub struct JournalctlEntry { pub struct JournalctlEntry {
#[serde(rename = "__REALTIME_TIMESTAMP")] #[serde(rename = "__REALTIME_TIMESTAMP")]
pub timestamp: String, pub timestamp: String,
@@ -228,14 +230,15 @@ pub enum LogSource {
pub const SYSTEM_UNIT: &str = "startd"; pub const SYSTEM_UNIT: &str = "startd";
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
pub struct PackageIdParams { pub struct PackageIdParams {
id: PackageId, id: PackageId,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, TS)]
#[ts(type = "number | string")]
pub enum BootIdentifier { pub enum BootIdentifier {
Index(i32), Index(i32),
Id(String), Id(String),
@@ -338,6 +341,11 @@ pub struct LogsParams<Extra: FromArgMatches + Args = Empty> {
#[serde(default)] #[serde(default)]
before: bool, before: bool,
} }
impl<Extra: FromArgMatches + Args + TS> LogsParams<Extra> {
pub fn inline_ty() -> String {
format!("{} & {{ limit: number | null; cursor: string | null; boot: string | number | null; before: boolean }}", Extra::inline_flattened())
}
}
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@@ -354,18 +362,30 @@ pub struct CliLogsParams<Extra: FromArgMatches + Args = Empty> {
#[allow(private_bounds)] #[allow(private_bounds)]
pub fn logs< pub fn logs<
C: Context + AsRef<RpcContinuations>, C: Context + AsRef<RpcContinuations>,
Extra: FromArgMatches + Serialize + DeserializeOwned + Args + Send + Sync + 'static, Extra: FromArgMatches + Serialize + DeserializeOwned + Args + TS + Send + Sync + 'static,
>( >(
source: impl for<'a> LogSourceFn<'a, C, Extra>, source: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> ParentHandler<C, LogsParams<Extra>> { ) -> UnknownTS<ParentHandler<C, LogsParams<Extra>>> {
ParentHandler::new() ParentHandler::new()
.root_handler(logs_nofollow::<C, Extra>(source.clone()).no_cli()) .root_handler(
logs_nofollow::<C, Extra>(source.clone())
.no_cli()
.custom_ts(
LogsParams::<Extra>::inline_ty(),
LogResponse::inline_flattened(),
),
)
.subcommand( .subcommand(
"follow", "follow",
logs_follow::<C, Extra>(source) logs_follow::<C, Extra>(source)
.with_inherited(|params, _| params) .with_inherited(|params, _| params)
.no_cli(), .no_cli()
.custom_ts(
LogsParams::<Extra>::inline_ty(),
LogFollowResponse::inline_flattened(),
),
) )
.unknown_ts()
} }
pub async fn cli_logs<RemoteContext, Extra>( pub async fn cli_logs<RemoteContext, Extra>(
@@ -379,7 +399,7 @@ pub async fn cli_logs<RemoteContext, Extra>(
) -> Result<(), RpcError> ) -> Result<(), RpcError>
where where
CliContext: CallRemote<RemoteContext>, CliContext: CallRemote<RemoteContext>,
Extra: FromArgMatches + Args + Serialize + Send + Sync, Extra: FromArgMatches + Args + TS + Serialize + Send + Sync,
{ {
let method = parent_method let method = parent_method
.into_iter() .into_iter()
@@ -431,10 +451,16 @@ where
fn logs_nofollow<C, Extra>( fn logs_nofollow<C, Extra>(
f: impl for<'a> LogSourceFn<'a, C, Extra>, f: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> impl HandlerFor<C, Params = LogsParams<Extra>, InheritedParams = Empty, Ok = LogResponse, Err = Error> ) -> impl HandlerFor<
C,
Params = LogsParams<Extra>,
InheritedParams = Empty,
Ok = LogResponse,
Err = Error,
> + LeafHandler
where where
C: Context, C: Context,
Extra: FromArgMatches + Args + Send + Sync + 'static, Extra: FromArgMatches + Args + TS + Send + Sync + 'static,
{ {
from_fn_async( from_fn_async(
move |HandlerArgs { move |HandlerArgs {
@@ -466,7 +492,7 @@ where
fn logs_follow< fn logs_follow<
C: Context + AsRef<RpcContinuations>, C: Context + AsRef<RpcContinuations>,
Extra: FromArgMatches + Args + Send + Sync + 'static, Extra: FromArgMatches + Args + TS + Send + Sync + 'static,
>( >(
f: impl for<'a> LogSourceFn<'a, C, Extra>, f: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> impl HandlerFor< ) -> impl HandlerFor<
@@ -475,7 +501,7 @@ fn logs_follow<
InheritedParams = LogsParams<Extra>, InheritedParams = LogsParams<Extra>,
Ok = LogFollowResponse, Ok = LogFollowResponse,
Err = Error, Err = Error,
> { > + LeafHandler {
from_fn_async( from_fn_async(
move |HandlerArgs { move |HandlerArgs {
context, context,
@@ -517,7 +543,7 @@ async fn get_package_id(
Ok(LogSource::Container(container_id)) Ok(LogSource::Container(container_id))
} }
pub fn package_logs() -> ParentHandler<RpcContext, LogsParams<PackageIdParams>> { pub fn package_logs() -> UnknownTS<ParentHandler<RpcContext, LogsParams<PackageIdParams>>> {
logs::<RpcContext, PackageIdParams>(get_package_id) logs::<RpcContext, PackageIdParams>(get_package_id)
} }

View File

@@ -24,6 +24,7 @@ use sha2::Sha256;
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::process::Command; use tokio::process::Command;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use ts_rs::TS;
use crate::auth::{Sessions, check_password, write_shadow}; use crate::auth::{Sessions, check_password, write_shadow};
use crate::context::RpcContext; use crate::context::RpcContext;
@@ -89,7 +90,7 @@ impl AuthContext for RpcContext {
} }
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct LoginRes { pub struct LoginRes {
pub session: InternedString, pub session: InternedString,
@@ -100,7 +101,7 @@ pub trait AsLogoutSessionId {
} }
/// Will need to know when we have logged out from a route /// Will need to know when we have logged out from a route
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, TS)]
pub struct HasLoggedOutSessions(()); pub struct HasLoggedOutSessions(());
impl HasLoggedOutSessions { impl HasLoggedOutSessions {

View File

@@ -26,6 +26,7 @@ use crate::context::{CliContext, RpcContext};
use crate::db::model::Database; use crate::db::model::Database;
use crate::db::model::public::AcmeSettings; use crate::db::model::public::AcmeSettings;
use crate::db::{DbAccess, DbAccessByKey, DbAccessMut}; use crate::db::{DbAccess, DbAccessByKey, DbAccessMut};
use crate::net::ssl::should_use_cert;
use crate::net::tls::{SingleCertResolver, TlsHandler}; use crate::net::tls::{SingleCertResolver, TlsHandler};
use crate::net::web_server::Accept; use crate::net::web_server::Accept;
use crate::prelude::*; use crate::prelude::*;
@@ -63,20 +64,27 @@ where
.and_then(|p| p.as_idx(JsonKey::new_ref(san_info))) .and_then(|p| p.as_idx(JsonKey::new_ref(san_info)))
{ {
let cert = cert.de().log_err()?; let cert = cert.de().log_err()?;
return Some( if cert
CertifiedKey::from_der( .fullchain
cert.fullchain .get(0)
.into_iter() .and_then(|c| should_use_cert(&c.0).log_err())
.map(|c| Ok(CertificateDer::from(c.to_der()?))) .unwrap_or(false)
.collect::<Result<_, Error>>() {
.log_err()?, return Some(
PrivateKeyDer::from(PrivatePkcs8KeyDer::from( CertifiedKey::from_der(
cert.key.0.private_key_to_pkcs8().log_err()?, cert.fullchain
)), .into_iter()
&*self.crypto_provider, .map(|c| Ok(CertificateDer::from(c.to_der()?)))
) .collect::<Result<_, Error>>()
.log_err()?, .log_err()?,
); PrivateKeyDer::from(PrivatePkcs8KeyDer::from(
cert.key.0.private_key_to_pkcs8().log_err()?,
)),
&*self.crypto_provider,
)
.log_err()?,
);
}
} }
if !self.in_progress.send_if_modified(|x| { if !self.in_progress.send_if_modified(|x| {
@@ -307,6 +315,16 @@ where
return Ok(None); return Ok(None);
}; };
let cert = cert.de()?; let cert = cert.de()?;
if !cert
.fullchain
.get(0)
.map(|c| should_use_cert(&c.0))
.transpose()
.map_err(Error::from)?
.unwrap_or(false)
{
return Ok(None);
}
Ok(Some(( Ok(Some((
String::from_utf8( String::from_utf8(
cert.key cert.key
@@ -442,7 +460,7 @@ impl ValueParserFactory for AcmeProvider {
} }
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct InitAcmeParams { pub struct InitAcmeParams {
#[arg(long)] #[arg(long)]
pub provider: AcmeProvider, pub provider: AcmeProvider,
@@ -467,7 +485,7 @@ pub async fn init(
Ok(()) Ok(())
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct RemoveAcmeParams { pub struct RemoveAcmeParams {
#[arg(long)] #[arg(long)]
pub provider: AcmeProvider, pub provider: AcmeProvider,

View File

@@ -32,6 +32,7 @@ use rpc_toolkit::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::net::{TcpListener, UdpSocket}; use tokio::net::{TcpListener, UdpSocket};
use tracing::instrument; use tracing::instrument;
use ts_rs::TS;
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::db::model::Database; use crate::db::model::Database;
@@ -99,7 +100,7 @@ pub fn dns_api<C: Context>() -> ParentHandler<C> {
) )
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct QueryDnsParams { pub struct QueryDnsParams {
pub fqdn: InternedString, pub fqdn: InternedString,
} }
@@ -138,7 +139,7 @@ pub fn query_dns<C: Context>(
.map_err(Error::from) .map_err(Error::from)
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct SetStaticDnsParams { pub struct SetStaticDnsParams {
pub servers: Option<Vec<String>>, pub servers: Option<Vec<String>>,
} }

View File

@@ -13,6 +13,7 @@ use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::process::Command; use tokio::process::Command;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use ts_rs::TS;
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::db::model::public::NetworkInterfaceInfo; use crate::db::model::public::NetworkInterfaceInfo;
@@ -448,10 +449,10 @@ fn err_has_exited<T>(_: T) -> Error {
) )
} }
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
pub struct ForwardTable(pub BTreeMap<u16, ForwardTarget>); pub struct ForwardTable(pub BTreeMap<u16, ForwardTarget>);
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
pub struct ForwardTarget { pub struct ForwardTarget {
pub target: SocketAddrV4, pub target: SocketAddrV4,
pub filter: String, pub filter: String,

View File

@@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::future::Future; use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV6}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV6};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::task::{Poll, ready}; use std::task::{ready, Poll};
use std::time::Duration; use std::time::Duration;
use clap::Parser; use clap::Parser;
@@ -17,7 +17,7 @@ use itertools::Itertools;
use models::GatewayId; use models::GatewayId;
use nix::net::if_::if_nametoindex; use nix::net::if_::if_nametoindex;
use patch_db::json_ptr::JsonPointer; use patch_db::json_ptr::JsonPointer;
use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, HandlerArgs, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::net::TcpListener; use tokio::net::TcpListener;
@@ -29,28 +29,29 @@ use zbus::proxy::{PropertyChanged, PropertyStream, SignalStream};
use zbus::zvariant::{ use zbus::zvariant::{
DeserializeDict, Dict, OwnedObjectPath, OwnedValue, Type as ZType, Value as ZValue, DeserializeDict, Dict, OwnedObjectPath, OwnedValue, Type as ZType, Value as ZValue,
}; };
use zbus::{Connection, proxy}; use zbus::{proxy, Connection};
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::db::model::Database;
use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType}; use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType};
use crate::db::model::Database;
use crate::net::forward::START9_BRIDGE_IFACE; use crate::net::forward::START9_BRIDGE_IFACE;
use crate::net::gateway::device::DeviceProxy; use crate::net::gateway::device::DeviceProxy;
use crate::net::utils::ipv6_is_link_local; use crate::net::utils::ipv6_is_link_local;
use crate::net::web_server::{Accept, AcceptStream, Acceptor, MetadataVisitor}; use crate::net::web_server::{Accept, AcceptStream, Acceptor, MetadataVisitor};
use crate::prelude::*; use crate::prelude::*;
use crate::util::Invoke;
use crate::util::collections::OrdMapIterMut; use crate::util::collections::OrdMapIterMut;
use crate::util::future::Until; use crate::util::future::Until;
use crate::util::io::open_file; use crate::util::io::open_file;
use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::serde::{display_serializable, HandlerExtSerde};
use crate::util::sync::{SyncMutex, Watch}; use crate::util::sync::{SyncMutex, Watch};
use crate::util::Invoke;
pub fn gateway_api<C: Context>() -> ParentHandler<C> { pub fn gateway_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new() ParentHandler::new()
.subcommand( .subcommand(
"list", "list",
from_fn_async(list_interfaces) from_fn_async(list_interfaces)
.custom_ts("{}".into(), BTreeMap::<GatewayId, NetworkInterfaceInfo>::inline_flattened())
.with_display_serializable() .with_display_serializable()
.with_custom_display_fn(|HandlerArgs { params, .. }, res| { .with_custom_display_fn(|HandlerArgs { params, .. }, res| {
use prettytable::*; use prettytable::*;
@@ -130,7 +131,6 @@ async fn list_interfaces(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct NetworkInterfaceSetPublicParams { struct NetworkInterfaceSetPublicParams {
gateway: GatewayId, gateway: GatewayId,
public: Option<bool>, public: Option<bool>,
@@ -147,7 +147,6 @@ async fn set_public(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct UnsetPublicParams { struct UnsetPublicParams {
gateway: GatewayId, gateway: GatewayId,
} }
@@ -163,7 +162,6 @@ async fn unset_public(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct ForgetGatewayParams { struct ForgetGatewayParams {
gateway: GatewayId, gateway: GatewayId,
} }
@@ -176,7 +174,6 @@ async fn forget_iface(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct RenameGatewayParams { struct RenameGatewayParams {
id: GatewayId, id: GatewayId,
name: InternedString, name: InternedString,
@@ -404,6 +401,12 @@ async fn watcher(
) { ) {
loop { loop {
let res: Result<(), Error> = async { let res: Result<(), Error> = async {
Command::new("systemctl")
.arg("start")
.arg("NetworkManager")
.invoke(ErrorKind::Network)
.await?;
let connection = Connection::system().await?; let connection = Connection::system().await?;
let netman_proxy = NetworkManagerProxy::new(&connection).await?; let netman_proxy = NetworkManagerProxy::new(&connection).await?;
@@ -435,49 +438,60 @@ async fn watcher(
loop { loop {
until until
.run(async { .run(async {
let devices = netman_proxy.all_devices().await?; loop {
let mut ifaces = BTreeSet::new(); let devices = netman_proxy.all_devices().await?;
let mut jobs = Vec::new(); if devices.is_empty() {
for device in devices { tracing::warn!(
use futures::future::Either; "NetworkManager returned no devices. Trying again..."
);
let device_proxy = tokio::time::sleep(Duration::from_secs(1)).await;
device::DeviceProxy::new(&connection, device.clone()).await?;
let iface = InternedString::intern(device_proxy.ip_interface().await?);
if iface.is_empty() {
continue; continue;
} }
let iface: GatewayId = iface.into(); let mut ifaces = BTreeSet::new();
if watch_activation.peek(|a| a.contains_key(&iface)) { let mut jobs = Vec::new();
jobs.push(Either::Left(watch_activated( for device in devices {
use futures::future::Either;
let device_proxy =
device::DeviceProxy::new(&connection, device.clone()).await?;
let iface =
InternedString::intern(device_proxy.ip_interface().await?);
if iface.is_empty() {
continue;
}
let iface: GatewayId = iface.into();
if watch_activation.peek(|a| a.contains_key(&iface)) {
jobs.push(Either::Left(watch_activated(
&connection,
device_proxy.clone(),
iface.clone(),
&watch_activation,
)));
}
jobs.push(Either::Right(watch_ip(
&connection, &connection,
device_proxy.clone(), device_proxy.clone(),
iface.clone(), iface.clone(),
&watch_activation, &watch_ip_info,
))); )));
ifaces.insert(iface);
} }
jobs.push(Either::Right(watch_ip( watch_ip_info.send_if_modified(|m| {
&connection, let mut changed = false;
device_proxy.clone(), for (iface, info) in OrdMapIterMut::from(m) {
iface.clone(), if !ifaces.contains(iface) {
&watch_ip_info, info.ip_info = None;
))); changed = true;
ifaces.insert(iface); }
}
watch_ip_info.send_if_modified(|m| {
let mut changed = false;
for (iface, info) in OrdMapIterMut::from(m) {
if !ifaces.contains(iface) {
info.ip_info = None;
changed = true;
} }
} changed
changed });
}); futures::future::try_join_all(jobs).await?;
futures::future::try_join_all(jobs).await?;
break;
}
Ok::<_, Error>(()) Ok::<_, Error>(())
}) })
.await?; .await?;

View File

@@ -16,7 +16,7 @@ use crate::net::tor::OnionAddress;
use crate::prelude::*; use crate::prelude::*;
use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::serde::{HandlerExtSerde, display_serializable};
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
#[serde(rename_all_fields = "camelCase")] #[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")] #[serde(tag = "kind")]
@@ -235,7 +235,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
) )
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct AddPublicDomainParams { pub struct AddPublicDomainParams {
pub fqdn: InternedString, pub fqdn: InternedString,
#[arg(long)] #[arg(long)]
@@ -282,7 +282,7 @@ pub async fn add_public_domain<Kind: HostApiKind>(
.with_kind(ErrorKind::Unknown)? .with_kind(ErrorKind::Unknown)?
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct RemoveDomainParams { pub struct RemoveDomainParams {
pub fqdn: InternedString, pub fqdn: InternedString,
} }
@@ -305,7 +305,7 @@ pub async fn remove_public_domain<Kind: HostApiKind>(
Ok(()) Ok(())
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct AddPrivateDomainParams { pub struct AddPrivateDomainParams {
pub fqdn: InternedString, pub fqdn: InternedString,
} }
@@ -347,7 +347,7 @@ pub async fn remove_private_domain<Kind: HostApiKind>(
Ok(()) Ok(())
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct OnionParams { pub struct OnionParams {
pub onion: String, pub onion: String,
} }

View File

@@ -19,7 +19,6 @@ use crate::prelude::*;
use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::serde::{HandlerExtSerde, display_serializable};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, TS)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct BindId { pub struct BindId {
pub id: HostId, pub id: HostId,
@@ -46,7 +45,6 @@ impl FromStr for BindId {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindInfo { pub struct BindInfo {
pub enabled: bool, pub enabled: bool,
pub options: BindOptions, pub options: BindOptions,
@@ -55,7 +53,6 @@ pub struct BindInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct NetInfo { pub struct NetInfo {
#[ts(as = "BTreeSet::<GatewayId>")] #[ts(as = "BTreeSet::<GatewayId>")]
#[serde(default)] #[serde(default)]
@@ -145,7 +142,6 @@ impl InterfaceFilter for NetInfo {
} }
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS)] #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Security { pub struct Security {
pub ssl: bool, pub ssl: bool,
@@ -153,7 +149,6 @@ pub struct Security {
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindOptions { pub struct BindOptions {
pub preferred_external_port: u16, pub preferred_external_port: u16,
pub add_ssl: Option<AddSslOptions>, pub add_ssl: Option<AddSslOptions>,
@@ -162,7 +157,6 @@ pub struct BindOptions {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, TS)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddSslOptions { pub struct AddSslOptions {
pub preferred_external_port: u16, pub preferred_external_port: u16,
// #[serde(default)] // #[serde(default)]
@@ -234,7 +228,6 @@ pub async fn list_bindings<Kind: HostApiKind>(
#[derive(Deserialize, Serialize, Parser, TS)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindingGatewaySetEnabledParams { pub struct BindingGatewaySetEnabledParams {
internal_port: u16, internal_port: u16,
gateway: GatewayId, gateway: GatewayId,

View File

@@ -25,7 +25,6 @@ pub mod binding;
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct Host { pub struct Host {
pub bindings: BTreeMap<u16, BindInfo>, pub bindings: BTreeMap<u16, BindInfo>,
#[ts(type = "string[]")] #[ts(type = "string[]")]
@@ -74,7 +73,6 @@ impl Host {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct Hosts(pub BTreeMap<HostId, Host>); pub struct Hosts(pub BTreeMap<HostId, Host>);
impl Map for Hosts { impl Map for Hosts {
@@ -164,12 +162,12 @@ impl Model<Host> {
} }
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct RequiresPackageId { pub struct RequiresPackageId {
package: PackageId, package: PackageId,
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct RequiresHostId { pub struct RequiresHostId {
host: HostId, host: HostId,
} }

View File

@@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")] #[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")] #[serde(tag = "kind")]
@@ -30,7 +29,6 @@ impl HostnameInfo {
} }
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GatewayInfo { pub struct GatewayInfo {
pub id: GatewayId, pub id: GatewayId,
@@ -39,7 +37,6 @@ pub struct GatewayInfo {
} }
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct OnionHostname { pub struct OnionHostname {
#[ts(type = "string")] #[ts(type = "string")]
@@ -54,7 +51,6 @@ impl OnionHostname {
} }
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")] #[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")] #[serde(tag = "kind")]
@@ -96,7 +92,6 @@ impl IpHostname {
} }
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ServiceInterface { pub struct ServiceInterface {
pub id: ServiceInterfaceId, pub id: ServiceInterfaceId,
@@ -109,7 +104,6 @@ pub struct ServiceInterface {
} }
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub enum ServiceInterfaceType { pub enum ServiceInterfaceType {
Ui, Ui,
@@ -118,7 +112,6 @@ pub enum ServiceInterfaceType {
} }
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AddressInfo { pub struct AddressInfo {
pub username: Option<String>, pub username: Option<String>,

View File

@@ -19,7 +19,7 @@ use openssl::x509::extension::{
AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName, AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName,
SubjectKeyIdentifier, SubjectKeyIdentifier,
}; };
use openssl::x509::{X509, X509Builder, X509NameBuilder}; use openssl::x509::{X509, X509Builder, X509NameBuilder, X509Ref};
use openssl::*; use openssl::*;
use patch_db::HasModel; use patch_db::HasModel;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -48,6 +48,17 @@ pub fn gen_nistp256() -> Result<PKey<Private>, ErrorStack> {
)?)?) )?)?)
} }
pub fn should_use_cert(cert: &X509Ref) -> Result<bool, ErrorStack> {
Ok(cert
.not_before()
.compare(Asn1Time::days_from_now(0)?.as_ref())?
== Ordering::Less
&& cert
.not_after()
.compare(Asn1Time::days_from_now(30)?.as_ref())?
== Ordering::Greater)
}
#[derive(Debug, Deserialize, Serialize, HasModel)] #[derive(Debug, Deserialize, Serialize, HasModel)]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@@ -83,30 +94,8 @@ impl Model<CertStore> {
.map(|m| m.de()) .map(|m| m.de())
.transpose()? .transpose()?
{ {
if cert_data if should_use_cert(&cert_data.certs.ed25519)?
.certs && should_use_cert(&cert_data.certs.nistp256)?
.ed25519
.not_before()
.compare(Asn1Time::days_from_now(0)?.as_ref())?
== Ordering::Less
&& cert_data
.certs
.ed25519
.not_after()
.compare(Asn1Time::days_from_now(30)?.as_ref())?
== Ordering::Greater
&& cert_data
.certs
.nistp256
.not_before()
.compare(Asn1Time::days_from_now(0)?.as_ref())?
== Ordering::Less
&& cert_data
.certs
.nistp256
.not_after()
.compare(Asn1Time::days_from_now(30)?.as_ref())?
== Ordering::Greater
{ {
return Ok(FullchainCertData { return Ok(FullchainCertData {
root: self.as_root_cert().de()?.0, root: self.as_root_cert().de()?.0,
@@ -251,12 +240,16 @@ impl CertPair {
} }
} }
pub async fn root_ca_start_time() -> Result<SystemTime, Error> { pub async fn root_ca_start_time() -> SystemTime {
Ok(if check_time_is_synchronized().await? { if check_time_is_synchronized()
.await
.log_err()
.unwrap_or(false)
{
SystemTime::now() SystemTime::now()
} else { } else {
*SOURCE_DATE *SOURCE_DATE
}) }
} }
const EC_CURVE_NAME: nid::Nid = nid::Nid::X9_62_PRIME256V1; const EC_CURVE_NAME: nid::Nid = nid::Nid::X9_62_PRIME256V1;

View File

@@ -357,7 +357,7 @@ pub fn display_services(
Ok(()) Ok(())
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, TS)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum OnionServiceState { pub enum OnionServiceState {
Shutdown, Shutdown,
@@ -383,7 +383,7 @@ impl From<ArtiOnionServiceState> for OnionServiceState {
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct OnionServiceInfo { pub struct OnionServiceInfo {
pub state: OnionServiceState, pub state: OnionServiceState,

View File

@@ -15,7 +15,7 @@ use imbl::OrdMap;
use imbl_value::InternedString; use imbl_value::InternedString;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use rpc_toolkit::{Context, Empty, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, Empty, HandlerExt, ParentHandler, UnknownTS};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::process::Command; use tokio::process::Command;
@@ -27,16 +27,16 @@ use tracing::instrument;
use ts_rs::TS; use ts_rs::TS;
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::logs::{LogSource, LogsParams, journalctl}; use crate::logs::{journalctl, LogSource, LogsParams};
use crate::prelude::*; use crate::prelude::*;
use crate::util::Invoke;
use crate::util::collections::ordmap_retain; use crate::util::collections::ordmap_retain;
use crate::util::io::{ReadWriter, write_file_atomic}; use crate::util::io::{write_file_atomic, ReadWriter};
use crate::util::serde::{ use crate::util::serde::{
BASE64, Base64, HandlerExtSerde, WithIoFormat, deserialize_from_str, display_serializable, deserialize_from_str, display_serializable, serialize_display, Base64, HandlerExtSerde,
serialize_display, WithIoFormat, BASE64,
}; };
use crate::util::sync::Watch; use crate::util::sync::Watch;
use crate::util::Invoke;
pub const SYSTEMD_UNIT: &str = "tor@default"; pub const SYSTEMD_UNIT: &str = "tor@default";
const STARTING_HEALTH_TIMEOUT: u64 = 120; // 2min const STARTING_HEALTH_TIMEOUT: u64 = 120; // 2min
@@ -45,7 +45,8 @@ const TOR_CONTROL: SocketAddr =
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 1, 1), 9051)); SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 1, 1), 9051));
const TOR_SOCKS: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 1, 1), 9050)); const TOR_SOCKS: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 1, 1), 9050));
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, TS)]
#[ts(type = "string")]
pub struct OnionAddress(OnionAddressV3); pub struct OnionAddress(OnionAddressV3);
impl std::fmt::Display for OnionAddress { impl std::fmt::Display for OnionAddress {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -255,6 +256,7 @@ pub fn tor_api<C: Context>() -> ParentHandler<C> {
"logs", "logs",
from_fn_async(crate::logs::cli_logs::<RpcContext, Empty>) from_fn_async(crate::logs::cli_logs::<RpcContext, Empty>)
.no_display() .no_display()
.no_ts()
.with_about("Display Tor logs"), .with_about("Display Tor logs"),
) )
.subcommand( .subcommand(
@@ -312,7 +314,7 @@ pub async fn generate_key(ctx: RpcContext) -> Result<OnionAddress, Error> {
.result .result
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
pub struct AddKeyParams { pub struct AddKeyParams {
pub key: Base64<[u8; 64]>, pub key: Base64<[u8; 64]>,
} }
@@ -386,7 +388,7 @@ pub async fn list_services(ctx: RpcContext, _: Empty) -> Result<Vec<OnionAddress
ctx.net_controller.tor.list_services().await ctx.net_controller.tor.list_services().await
} }
pub fn logs() -> ParentHandler<RpcContext, LogsParams> { pub fn logs() -> UnknownTS<ParentHandler<RpcContext, LogsParams>> {
crate::logs::logs::<RpcContext, Empty>(|_: &RpcContext, _| async { crate::logs::logs::<RpcContext, Empty>(|_: &RpcContext, _| async {
Ok(LogSource::Unit(SYSTEMD_UNIT)) Ok(LogSource::Unit(SYSTEMD_UNIT))
}) })

View File

@@ -32,7 +32,6 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
pub struct AddTunnelParams { pub struct AddTunnelParams {
name: InternedString, name: InternedString,
config: String, config: String,
@@ -104,7 +103,6 @@ pub async fn add_tunnel(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
pub struct RemoveTunnelParams { pub struct RemoveTunnelParams {
id: GatewayId, id: GatewayId,
} }

View File

@@ -134,7 +134,6 @@ impl VHostController {
pub fn dump_table( pub fn dump_table(
&self, &self,
) -> BTreeMap<JsonKey<u16>, BTreeMap<JsonKey<Option<InternedString>>, EqSet<String>>> { ) -> BTreeMap<JsonKey<u16>, BTreeMap<JsonKey<Option<InternedString>>, EqSet<String>>> {
let ip_info = self.interfaces.watcher.ip_info();
self.servers.peek(|s| { self.servers.peek(|s| {
s.iter() s.iter()
.map(|(k, v)| { .map(|(k, v)| {
@@ -352,7 +351,6 @@ where
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum AlpnInfo { pub enum AlpnInfo {
Reflect, Reflect,
Specified(Vec<MaybeUtf8String>), Specified(Vec<MaybeUtf8String>),

View File

@@ -343,22 +343,23 @@ pub async fn remove(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result<
.result?; .result?;
Ok(()) Ok(())
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct WifiListInfo { pub struct WifiListInfo {
ssids: HashMap<Ssid, SignalStrength>, ssids: HashMap<Ssid, SignalStrength>,
connected: Option<Ssid>, connected: Option<Ssid>,
#[ts(type = "sttring | null")]
country: Option<CountryCode>, country: Option<CountryCode>,
ethernet: bool, ethernet: bool,
available_wifi: Vec<WifiListOut>, available_wifi: Vec<WifiListOut>,
} }
#[derive(serde::Serialize, serde::Deserialize, Clone)] #[derive(serde::Serialize, serde::Deserialize, Clone, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct WifiListInfoLow { pub struct WifiListInfoLow {
strength: SignalStrength, strength: SignalStrength,
security: Vec<String>, security: Vec<String>,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct WifiListOut { pub struct WifiListOut {
ssid: Ssid, ssid: Ssid,
@@ -589,7 +590,7 @@ pub struct NetworkId(String);
/// Ssid are the names of the wifis, usually human readable. /// Ssid are the names of the wifis, usually human readable.
#[derive( #[derive(
Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, TS,
)] )]
pub struct Ssid(String); pub struct Ssid(String);
@@ -606,6 +607,7 @@ pub struct Ssid(String);
Hash, Hash,
serde::Serialize, serde::Serialize,
serde::Deserialize, serde::Deserialize,
TS,
)] )]
pub struct SignalStrength(u8); pub struct SignalStrength(u8);

View File

@@ -388,7 +388,7 @@ impl Map for Notifications {
} }
} }
#[derive(Debug, Serialize, Deserialize, HasModel)] #[derive(Debug, Serialize, Deserialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
pub struct Notification { pub struct Notification {
@@ -403,7 +403,7 @@ pub struct Notification {
pub seen: bool, pub seen: bool,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct NotificationWithId { pub struct NotificationWithId {
id: u32, id: u32,

View File

@@ -196,7 +196,6 @@ impl std::ops::AddAssign<u64> for Progress {
} }
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct NamedProgress { pub struct NamedProgress {
#[ts(type = "string")] #[ts(type = "string")]
pub name: InternedString, pub name: InternedString,
@@ -204,7 +203,6 @@ pub struct NamedProgress {
} }
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct FullProgress { pub struct FullProgress {
pub overall: Progress, pub overall: Progress,
pub phases: Vec<NamedProgress>, pub phases: Vec<NamedProgress>,

View File

@@ -32,6 +32,7 @@ pub fn admin_api<C: Context>() -> ParentHandler<C> {
"add", "add",
from_fn_async(cli_add_admin) from_fn_async(cli_add_admin)
.no_display() .no_display()
.no_ts()
.with_about("Add admin signer"), .with_about("Add admin signer"),
) )
.subcommand( .subcommand(
@@ -72,7 +73,7 @@ fn signers_api<C: Context>() -> ParentHandler<C> {
) )
.subcommand( .subcommand(
"add", "add",
from_fn_async(cli_add_signer).with_about("Add signer"), from_fn_async(cli_add_signer).no_ts().with_about("Add signer"),
) )
.subcommand( .subcommand(
"edit", "edit",
@@ -172,7 +173,6 @@ pub async fn add_signer(ctx: RegistryContext, signer: SignerInfo) -> Result<Guid
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[ts(export)]
pub struct EditSignerParams { pub struct EditSignerParams {
pub id: Guid, pub id: Guid,
#[arg(short = 'n', long)] #[arg(short = 'n', long)]
@@ -280,7 +280,6 @@ pub async fn cli_add_signer(
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddAdminParams { pub struct AddAdminParams {
pub signer: Guid, pub signer: Guid,
} }
@@ -305,7 +304,6 @@ pub async fn add_admin(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveAdminParams { pub struct RemoveAdminParams {
pub signer: Guid, pub signer: Guid,
} }

View File

@@ -22,7 +22,6 @@ use crate::upload::UploadingFile;
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RegistryAsset<Commitment> { pub struct RegistryAsset<Commitment> {
#[ts(type = "string")] #[ts(type = "string")]
pub published_at: DateTime<Utc>, pub published_at: DateTime<Utc>,

View File

@@ -22,18 +22,24 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
"dump", "dump",
from_fn_async(cli_dump) from_fn_async(cli_dump)
.with_display_serializable() .with_display_serializable()
.no_ts()
.with_about("Filter/query db to display tables and records"), .with_about("Filter/query db to display tables and records"),
) )
.subcommand( .subcommand(
"dump", "dump",
from_fn_async(dump) from_fn_async(dump)
.with_metadata("admin", Value::Bool(true)) .with_metadata("admin", Value::Bool(true))
.no_cli(), .no_cli()
.custom_ts(
DumpParams::inline_flattened(),
format!("{{ id: number; value: unknown }}"),
),
) )
.subcommand( .subcommand(
"apply", "apply",
from_fn_async(cli_apply) from_fn_async(cli_apply)
.no_display() .no_display()
.no_ts()
.with_about("Update a db record"), .with_about("Update a db record"),
) )
.subcommand( .subcommand(

View File

@@ -47,7 +47,6 @@ pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
#[derive(Debug, Default, Deserialize, Serialize, TS)] #[derive(Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RegistryInfo { pub struct RegistryInfo {
pub name: Option<String>, pub name: Option<String>,
pub icon: Option<DataUrl<'static>>, pub icon: Option<DataUrl<'static>>,
@@ -66,7 +65,6 @@ pub async fn get_info(ctx: RegistryContext) -> Result<RegistryInfo, Error> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetNameParams { pub struct SetNameParams {
pub name: String, pub name: String,
} }
@@ -83,7 +81,6 @@ pub async fn set_name(
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetIconParams { pub struct SetIconParams {
pub icon: DataUrl<'static>, pub icon: DataUrl<'static>,
} }
@@ -101,7 +98,6 @@ pub async fn set_icon(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CliSetIconParams { pub struct CliSetIconParams {
pub icon: PathBuf, pub icon: PathBuf,
} }

View File

@@ -11,7 +11,6 @@ use crate::context::CliContext;
use crate::middleware::cors::Cors; use crate::middleware::cors::Cors;
use crate::middleware::signature::SignatureAuth; use crate::middleware::signature::SignatureAuth;
use crate::net::static_server::{bad_request, not_found, server_error}; use crate::net::static_server::{bad_request, not_found, server_error};
use crate::net::web_server::{Accept, WebServer};
use crate::prelude::*; use crate::prelude::*;
use crate::registry::context::RegistryContext; use crate::registry::context::RegistryContext;
use crate::registry::device_info::DeviceInfoMiddleware; use crate::registry::device_info::DeviceInfoMiddleware;
@@ -43,7 +42,6 @@ impl RegistryDatabase {}
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct FullIndex { pub struct FullIndex {
pub name: Option<String>, pub name: Option<String>,
pub icon: Option<DataUrl<'static>>, pub icon: Option<DataUrl<'static>>,

View File

@@ -75,7 +75,6 @@ pub fn remove_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddAssetParams { pub struct AddAssetParams {
#[ts(type = "string")] #[ts(type = "string")]
pub version: Version, pub version: Version,
@@ -283,7 +282,6 @@ pub async fn cli_add_asset(
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveAssetParams { pub struct RemoveAssetParams {
#[ts(type = "string")] #[ts(type = "string")]
pub version: Version, pub version: Version,

View File

@@ -30,6 +30,7 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
"iso", "iso",
from_fn_async(cli_get_os_asset) from_fn_async(cli_get_os_asset)
.no_display() .no_display()
.no_ts()
.with_about("Download iso"), .with_about("Download iso"),
) )
.subcommand("img", from_fn_async(get_img).no_cli()) .subcommand("img", from_fn_async(get_img).no_cli())
@@ -37,6 +38,7 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
"img", "img",
from_fn_async(cli_get_os_asset) from_fn_async(cli_get_os_asset)
.no_display() .no_display()
.no_ts()
.with_about("Download img"), .with_about("Download img"),
) )
.subcommand("squashfs", from_fn_async(get_squashfs).no_cli()) .subcommand("squashfs", from_fn_async(get_squashfs).no_cli())
@@ -44,13 +46,13 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
"squashfs", "squashfs",
from_fn_async(cli_get_os_asset) from_fn_async(cli_get_os_asset)
.no_display() .no_display()
.no_ts()
.with_about("Download squashfs"), .with_about("Download squashfs"),
) )
} }
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetOsAssetParams { pub struct GetOsAssetParams {
#[ts(type = "string")] #[ts(type = "string")]
pub version: Version, pub version: Version,

View File

@@ -11,6 +11,7 @@ pub fn asset_api<C: Context>() -> ParentHandler<C> {
"add", "add",
from_fn_async(add::cli_add_asset) from_fn_async(add::cli_add_asset)
.no_display() .no_display()
.no_ts()
.with_about("Add asset to registry"), .with_about("Add asset to registry"),
) )
.subcommand("remove", add::remove_api::<C>()) .subcommand("remove", add::remove_api::<C>())
@@ -19,6 +20,7 @@ pub fn asset_api<C: Context>() -> ParentHandler<C> {
"sign", "sign",
from_fn_async(sign::cli_sign_asset) from_fn_async(sign::cli_sign_asset)
.no_display() .no_display()
.no_ts()
.with_about("Sign file and add to registry index"), .with_about("Sign file and add to registry index"),
) )
// TODO: remove signature api // TODO: remove signature api

View File

@@ -49,7 +49,6 @@ pub fn sign_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SignAssetParams { pub struct SignAssetParams {
#[ts(type = "string")] #[ts(type = "string")]
version: Version, version: Version,

View File

@@ -14,7 +14,6 @@ use crate::sign::commitment::blake3::Blake3Commitment;
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct OsIndex { pub struct OsIndex {
pub versions: OsVersionInfoMap, pub versions: OsVersionInfoMap,
} }
@@ -37,7 +36,6 @@ impl Map for OsVersionInfoMap {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct OsVersionInfo { pub struct OsVersionInfo {
pub headline: String, pub headline: String,
pub release_notes: String, pub release_notes: String,

View File

@@ -46,6 +46,10 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
"get", "get",
from_fn_async(get_version) from_fn_async(get_version)
.with_metadata("get_device_info", Value::Bool(true)) .with_metadata("get_device_info", Value::Bool(true))
.custom_ts(
GetOsVersionParams::inline_flattened(),
BTreeMap::<String, OsVersionInfo>::inline_flattened(),
)
.with_display_serializable() .with_display_serializable()
.with_custom_display_fn(|handle, result| { .with_custom_display_fn(|handle, result| {
display_version_info(handle.params, result) display_version_info(handle.params, result)
@@ -58,7 +62,6 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddVersionParams { pub struct AddVersionParams {
#[ts(type = "string")] #[ts(type = "string")]
pub version: Version, pub version: Version,
@@ -106,7 +109,6 @@ pub async fn add_version(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveVersionParams { pub struct RemoveVersionParams {
#[ts(type = "string")] #[ts(type = "string")]
pub version: Version, pub version: Version,
@@ -131,7 +133,6 @@ pub async fn remove_version(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetOsVersionParams { pub struct GetOsVersionParams {
#[ts(type = "string | null")] #[ts(type = "string | null")]
#[arg(long = "src")] #[arg(long = "src")]

View File

@@ -45,7 +45,6 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct VersionSignerParams { pub struct VersionSignerParams {
#[ts(type = "string")] #[ts(type = "string")]
pub version: Version, pub version: Version,
@@ -108,7 +107,6 @@ pub async fn remove_version_signer(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ListVersionSignersParams { pub struct ListVersionSignersParams {
#[ts(type = "string")] #[ts(type = "string")]
pub version: Version, pub version: Version,

View File

@@ -26,7 +26,6 @@ use crate::util::io::TrackingIO;
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddPackageParams { pub struct AddPackageParams {
#[ts(type = "string")] #[ts(type = "string")]
pub url: Url, pub url: Url,
@@ -163,7 +162,6 @@ pub async fn cli_add_package(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemovePackageParams { pub struct RemovePackageParams {
pub id: PackageId, pub id: PackageId,
pub version: VersionString, pub version: VersionString,

View File

@@ -61,7 +61,6 @@ pub fn category_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddCategoryParams { pub struct AddCategoryParams {
#[ts(type = "string")] #[ts(type = "string")]
pub id: InternedString, pub id: InternedString,
@@ -87,7 +86,6 @@ pub async fn add_category(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveCategoryParams { pub struct RemoveCategoryParams {
#[ts(type = "string")] #[ts(type = "string")]
pub id: InternedString, pub id: InternedString,
@@ -112,7 +110,6 @@ pub async fn remove_category(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddPackageToCategoryParams { pub struct AddPackageToCategoryParams {
#[ts(type = "string")] #[ts(type = "string")]
pub id: InternedString, pub id: InternedString,
@@ -141,7 +138,6 @@ pub async fn add_package(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemovePackageFromCategoryParams { pub struct RemovePackageFromCategoryParams {
#[ts(type = "string")] #[ts(type = "string")]
pub id: InternedString, pub id: InternedString,

View File

@@ -19,7 +19,6 @@ use crate::util::serde::{WithIoFormat, display_serializable};
Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS, ValueEnum, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS, ValueEnum,
)] )]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum PackageDetailLevel { pub enum PackageDetailLevel {
None, None,
Short, Short,
@@ -33,7 +32,6 @@ impl Default for PackageDetailLevel {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct PackageInfoShort { pub struct PackageInfoShort {
pub release_notes: String, pub release_notes: String,
} }
@@ -41,7 +39,6 @@ pub struct PackageInfoShort {
#[derive(Debug, Deserialize, Serialize, TS, Parser)] #[derive(Debug, Deserialize, Serialize, TS, Parser)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[ts(export)]
pub struct GetPackageParams { pub struct GetPackageParams {
pub id: Option<PackageId>, pub id: Option<PackageId>,
#[ts(type = "string | null")] #[ts(type = "string | null")]
@@ -60,7 +57,6 @@ pub struct GetPackageParams {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetPackageResponse { pub struct GetPackageResponse {
#[ts(type = "string[]")] #[ts(type = "string[]")]
pub categories: BTreeSet<InternedString>, pub categories: BTreeSet<InternedString>,
@@ -103,7 +99,6 @@ impl GetPackageResponse {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetPackageResponseFull { pub struct GetPackageResponseFull {
#[ts(type = "string[]")] #[ts(type = "string[]")]
pub categories: BTreeSet<InternedString>, pub categories: BTreeSet<InternedString>,

View File

@@ -23,7 +23,6 @@ use crate::sign::{AnySignature, AnyVerifyingKey};
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct PackageIndex { pub struct PackageIndex {
pub categories: BTreeMap<InternedString, Category>, pub categories: BTreeMap<InternedString, Category>,
pub packages: BTreeMap<PackageId, PackageInfo>, pub packages: BTreeMap<PackageId, PackageInfo>,
@@ -32,7 +31,6 @@ pub struct PackageIndex {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct PackageInfo { pub struct PackageInfo {
pub authorized: BTreeSet<Guid>, pub authorized: BTreeSet<Guid>,
pub versions: BTreeMap<VersionString, PackageVersionInfo>, pub versions: BTreeMap<VersionString, PackageVersionInfo>,
@@ -43,7 +41,6 @@ pub struct PackageInfo {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct Category { pub struct Category {
pub name: String, pub name: String,
} }
@@ -51,7 +48,6 @@ pub struct Category {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct DependencyMetadata { pub struct DependencyMetadata {
#[ts(type = "string | null")] #[ts(type = "string | null")]
pub title: Option<InternedString>, pub title: Option<InternedString>,
@@ -63,7 +59,6 @@ pub struct DependencyMetadata {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct PackageVersionInfo { pub struct PackageVersionInfo {
#[ts(type = "string")] #[ts(type = "string")]
pub title: InternedString, pub title: InternedString,

View File

@@ -29,6 +29,7 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
"add", "add",
from_fn_async(add::cli_add_package) from_fn_async(add::cli_add_package)
.no_display() .no_display()
.no_ts()
.with_about("Add package to registry index"), .with_about("Add package to registry index"),
) )
.subcommand( .subcommand(

View File

@@ -45,7 +45,6 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct PackageSignerParams { pub struct PackageSignerParams {
pub id: PackageId, pub id: PackageId,
pub signer: Guid, pub signer: Guid,
@@ -107,7 +106,6 @@ pub async fn remove_package_signer(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")] #[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ListPackageSignersParams { pub struct ListPackageSignersParams {
pub id: PackageId, pub id: PackageId,
} }

View File

@@ -15,7 +15,6 @@ use crate::sign::{AnySignature, AnyVerifyingKey, SignatureScheme};
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct SignerInfo { pub struct SignerInfo {
pub name: String, pub name: String,
pub contact: Vec<ContactInfo>, pub contact: Vec<ContactInfo>,
@@ -24,7 +23,6 @@ pub struct SignerInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq)] #[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
// TODO: better types // TODO: better types
pub enum ContactInfo { pub enum ContactInfo {
Email(String), Email(String),
@@ -61,7 +59,6 @@ impl ValueParserFactory for ContactInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum AcceptSigners { pub enum AcceptSigners {
#[serde(skip)] #[serde(skip)]
Accepted, Accepted,

View File

@@ -25,11 +25,13 @@ pub fn s9pk() -> ParentHandler<CliContext> {
"pack", "pack",
from_fn_async(super::v2::pack::pack) from_fn_async(super::v2::pack::pack)
.no_display() .no_display()
.no_ts()
.with_about("Package s9pk input files into valid s9pk"), .with_about("Package s9pk input files into valid s9pk"),
) )
.subcommand( .subcommand(
"list-ingredients", "list-ingredients",
from_fn_async(super::v2::pack::list_ingredients) from_fn_async(super::v2::pack::list_ingredients)
.no_ts()
.with_custom_display_fn(|_, ingredients| { .with_custom_display_fn(|_, ingredients| {
ingredients ingredients
.into_iter() .into_iter()
@@ -49,16 +51,17 @@ pub fn s9pk() -> ParentHandler<CliContext> {
) )
.subcommand( .subcommand(
"edit", "edit",
edit().with_about("Commands to add an image to an s9pk or edit the manifest"), edit().no_ts().with_about("Commands to add an image to an s9pk or edit the manifest"),
) )
.subcommand( .subcommand(
"inspect", "inspect",
inspect().with_about("Commands to display file paths, file contents, or manifest"), inspect().no_ts().with_about("Commands to display file paths, file contents, or manifest"),
) )
.subcommand( .subcommand(
"convert", "convert",
from_fn_async(convert) from_fn_async(convert)
.no_display() .no_display()
.no_ts()
.with_about("Convert s9pk from v1 to v2"), .with_about("Convert s9pk from v1 to v2"),
) )
} }

View File

@@ -5,7 +5,7 @@ use color_eyre::eyre::eyre;
use exver::{Version, VersionRange}; use exver::{Version, VersionRange};
use imbl_value::InternedString; use imbl_value::InternedString;
pub use models::PackageId; pub use models::PackageId;
use models::{ImageId, VolumeId, mime}; use models::{mime, ImageId, VolumeId};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
use url::Url; use url::Url;
@@ -16,10 +16,15 @@ use crate::s9pk::git_hash::GitHash;
use crate::s9pk::merkle_archive::directory_contents::DirectoryContents; use crate::s9pk::merkle_archive::directory_contents::DirectoryContents;
use crate::s9pk::merkle_archive::expected::{Expected, Filter}; use crate::s9pk::merkle_archive::expected::{Expected, Filter};
use crate::s9pk::v2::pack::ImageConfig; use crate::s9pk::v2::pack::ImageConfig;
use crate::util::VersionString;
use crate::util::serde::Regex; use crate::util::serde::Regex;
use crate::util::VersionString;
use crate::version::{Current, VersionT}; use crate::version::{Current, VersionT};
#[test]
fn export_bindings_manifest() {
Manifest::export_all_to("./bindings/manifest").unwrap();
}
fn current_version() -> Version { fn current_version() -> Version {
Current::default().semver() Current::default().semver()
} }
@@ -27,7 +32,6 @@ fn current_version() -> Version {
#[derive(Clone, Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Clone, Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct Manifest { pub struct Manifest {
pub id: PackageId, pub id: PackageId,
#[ts(type = "string")] #[ts(type = "string")]
@@ -167,7 +171,6 @@ impl Manifest {
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct HardwareRequirements { pub struct HardwareRequirements {
#[serde(default)] #[serde(default)]
pub device: Vec<DeviceFilter>, pub device: Vec<DeviceFilter>,
@@ -179,7 +182,6 @@ pub struct HardwareRequirements {
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct DeviceFilter { pub struct DeviceFilter {
#[ts(type = "\"processor\" | \"display\"")] #[ts(type = "\"processor\" | \"display\"")]
pub class: InternedString, pub class: InternedString,
@@ -189,7 +191,6 @@ pub struct DeviceFilter {
} }
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct Description { pub struct Description {
pub short: String, pub short: String,
pub long: String, pub long: String,
@@ -214,7 +215,6 @@ impl Description {
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Alerts { pub struct Alerts {
pub install: Option<String>, pub install: Option<String>,
pub uninstall: Option<String>, pub uninstall: Option<String>,

View File

@@ -248,7 +248,6 @@ impl PackParams {
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ImageConfig { pub struct ImageConfig {
pub source: ImageSource, pub source: ImageSource,
#[ts(type = "string[]")] #[ts(type = "string[]")]
@@ -336,7 +335,6 @@ impl clap::FromArgMatches for ImageConfig {
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(untagged)] #[serde(untagged)]
#[ts(export)]
pub enum BuildArg { pub enum BuildArg {
String(String), String(String),
EnvVar { env: String }, EnvVar { env: String },
@@ -344,7 +342,6 @@ pub enum BuildArg {
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum ImageSource { pub enum ImageSource {
Packed, Packed,
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@@ -626,7 +623,6 @@ fn tar2sqfs(dest: impl AsRef<Path>) -> Result<Command, Error> {
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ImageMetadata { pub struct ImageMetadata {
pub workdir: PathBuf, pub workdir: PathBuf,
#[ts(type = "string")] #[ts(type = "string")]

View File

@@ -1,9 +1,9 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use models::{ActionId, PackageId, ReplayId}; use models::{ActionId, PackageId, ReplayId};
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
use crate::action::{ActionInput, ActionResult, display_action_result}; use crate::action::{display_action_result, ActionInput, ActionResult};
use crate::db::model::package::{ use crate::db::model::package::{
ActionMetadata, Task, TaskCondition, TaskEntry, TaskSeverity, TaskTrigger, ActionMetadata, Task, TaskCondition, TaskEntry, TaskSeverity, TaskTrigger,
}; };
@@ -44,7 +44,6 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ExportActionParams { pub struct ExportActionParams {
id: ActionId, id: ActionId,
@@ -77,7 +76,6 @@ pub async fn export_action(
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ClearActionsParams { pub struct ClearActionsParams {
#[arg(long)] #[arg(long)]
@@ -110,7 +108,6 @@ async fn clear_actions(
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetActionInputParams { pub struct GetActionInputParams {
#[serde(default)] #[serde(default)]
#[ts(skip)] #[ts(skip)]
@@ -148,7 +145,6 @@ async fn get_action_input(
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RunActionParams { pub struct RunActionParams {
#[serde(default)] #[serde(default)]
#[ts(skip)] #[ts(skip)]
@@ -157,8 +153,8 @@ pub struct RunActionParams {
#[ts(optional)] #[ts(optional)]
package_id: Option<PackageId>, package_id: Option<PackageId>,
action_id: ActionId, action_id: ActionId,
#[ts(type = "any")] #[ts(optional, type = "unknown")]
input: Value, input: Option<Value>,
} }
async fn run_action( async fn run_action(
context: EffectContext, context: EffectContext,
@@ -171,6 +167,8 @@ async fn run_action(
) -> Result<Option<ActionResult>, Error> { ) -> Result<Option<ActionResult>, Error> {
let context = context.deref()?; let context = context.deref()?;
let input = input.unwrap_or_default();
let package_id = package_id.as_ref().unwrap_or(&context.seed.id); let package_id = package_id.as_ref().unwrap_or(&context.seed.id);
if package_id != &context.seed.id { if package_id != &context.seed.id {
@@ -195,7 +193,6 @@ async fn run_action(
#[derive(Clone, Debug, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CreateTaskParams { pub struct CreateTaskParams {
#[serde(default)] #[serde(default)]
#[ts(skip)] #[ts(skip)]
@@ -283,7 +280,6 @@ async fn create_task(
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(type = "{ only: string[] } | { except: string[] }")] #[ts(type = "{ only: string[] } | { except: string[] }")]
#[ts(export)]
pub struct ClearTasksParams { pub struct ClearTasksParams {
#[arg(long, conflicts_with = "except")] #[arg(long, conflicts_with = "except")]
pub only: Option<Vec<ReplayId>>, pub only: Option<Vec<ReplayId>>,

View File

@@ -293,7 +293,6 @@ impl CallbackHandlers {
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(type = "{ only: number[] } | { except: number[] }")] #[ts(type = "{ only: number[] } | { except: number[] }")]
#[ts(export)]
pub struct ClearCallbacksParams { pub struct ClearCallbacksParams {
#[arg(long, conflicts_with = "except")] #[arg(long, conflicts_with = "except")]
pub only: Option<Vec<CallbackId>>, pub only: Option<Vec<CallbackId>>,

View File

@@ -35,7 +35,6 @@ pub async fn shutdown(context: EffectContext, EventId { event_id }: EventId) ->
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetStatusParams { pub struct GetStatusParams {
#[ts(optional)] #[ts(optional)]
pub package_id: Option<PackageId>, pub package_id: Option<PackageId>,
@@ -76,7 +75,6 @@ pub async fn get_status(
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum SetMainStatusStatus { pub enum SetMainStatusStatus {
Running, Running,
Stopped, Stopped,
@@ -100,7 +98,6 @@ impl ValueParserFactory for SetMainStatusStatus {
#[derive(Debug, Clone, Serialize, Deserialize, Parser, TS)] #[derive(Debug, Clone, Serialize, Deserialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetMainStatus { pub struct SetMainStatus {
status: SetMainStatusStatus, status: SetMainStatusStatus,
} }

View File

@@ -22,7 +22,6 @@ use crate::status::health_check::NamedHealthCheckResult;
use crate::volume::data_dir; use crate::volume::data_dir;
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MountTarget { pub struct MountTarget {
package_id: PackageId, package_id: PackageId,
@@ -32,7 +31,6 @@ pub struct MountTarget {
filetype: FileType, filetype: FileType,
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MountParams { pub struct MountParams {
location: PathBuf, location: PathBuf,
@@ -98,7 +96,6 @@ pub async fn get_installed_packages(context: EffectContext) -> Result<BTreeSet<P
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum DependencyKind { pub enum DependencyKind {
Exists, Exists,
Running, Running,
@@ -106,7 +103,6 @@ pub enum DependencyKind {
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase", tag = "kind")] #[serde(rename_all = "camelCase", tag = "kind")]
#[serde(rename_all_fields = "camelCase")] #[serde(rename_all_fields = "camelCase")]
#[ts(export)]
pub enum DependencyRequirement { pub enum DependencyRequirement {
Running { Running {
id: PackageId, id: PackageId,
@@ -170,7 +166,6 @@ impl ValueParserFactory for DependencyRequirement {
#[derive(Deserialize, Serialize, Parser, TS)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[command(rename_all = "camelCase")] #[command(rename_all = "camelCase")]
#[ts(export)]
pub struct SetDependenciesParams { pub struct SetDependenciesParams {
dependencies: Vec<DependencyRequirement>, dependencies: Vec<DependencyRequirement>,
} }
@@ -271,14 +266,12 @@ pub async fn get_dependencies(context: EffectContext) -> Result<Vec<DependencyRe
#[derive(Debug, Clone, Serialize, Deserialize, Parser, TS)] #[derive(Debug, Clone, Serialize, Deserialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CheckDependenciesParam { pub struct CheckDependenciesParam {
#[ts(optional)] #[ts(optional)]
package_ids: Option<Vec<PackageId>>, package_ids: Option<Vec<PackageId>>,
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CheckDependenciesResult { pub struct CheckDependenciesResult {
package_id: PackageId, package_id: PackageId,
#[ts(type = "string | null")] #[ts(type = "string | null")]

View File

@@ -6,7 +6,6 @@ use crate::status::health_check::NamedHealthCheckResult;
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetHealth { pub struct SetHealth {
id: HealthCheckId, id: HealthCheckId,
#[serde(flatten)] #[serde(flatten)]

View File

@@ -1,17 +1,18 @@
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn, from_fn_async, from_fn_blocking}; use rpc_toolkit::{from_fn, from_fn_async, from_fn_blocking, Context, HandlerExt, ParentHandler};
use ts_rs::TS;
use crate::prelude::*; use crate::prelude::*;
use crate::service::cli::ContainerCliContext; use crate::service::cli::ContainerCliContext;
use crate::service::effects::context::EffectContext; use crate::service::effects::context::EffectContext;
use crate::{HOST_IP, echo}; use crate::{echo, HOST_IP};
mod action; mod action;
pub mod callbacks; pub mod callbacks;
pub mod context; pub mod context;
mod control; mod control;
mod dependency; pub mod dependency;
mod health; mod health;
mod net; mod net;
mod prelude; mod prelude;
@@ -19,6 +20,22 @@ mod subcontainer;
mod system; mod system;
mod version; mod version;
#[test]
fn export_bindings_service_effects_api() {
use rpc_toolkit::HandlerTS;
std::fs::create_dir_all("./bindings").unwrap();
std::fs::write(
"./bindings/service-effects-api.ts",
format!(
"export type ServiceEffectsApi = {}",
handler::<EffectContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
}
pub fn handler<C: Context>() -> ParentHandler<C> { pub fn handler<C: Context>() -> ParentHandler<C> {
ParentHandler::new() ParentHandler::new()
.subcommand("git-info", from_fn(|_: C| crate::version::git_info())) .subcommand("git-info", from_fn(|_: C| crate::version::git_info()))
@@ -96,20 +113,31 @@ pub fn handler<C: Context>() -> ParentHandler<C> {
ParentHandler::<C>::new() ParentHandler::<C>::new()
.subcommand( .subcommand(
"launch", "launch",
from_fn_blocking(subcontainer::launch).no_display(), from_fn_blocking(subcontainer::launch).no_display().no_ts(),
) )
.subcommand( .subcommand(
"launch-init", "launch-init",
from_fn_blocking(subcontainer::launch_init).no_display(), from_fn_blocking(subcontainer::launch_init)
.no_display()
.no_ts(),
)
.subcommand(
"exec",
from_fn_blocking(subcontainer::exec).no_display().no_ts(),
) )
.subcommand("exec", from_fn_blocking(subcontainer::exec).no_display())
.subcommand( .subcommand(
"exec-command", "exec-command",
from_fn_blocking(subcontainer::exec_command).no_display(), from_fn_blocking(subcontainer::exec_command)
.no_display()
.no_ts(),
) )
.subcommand( .subcommand(
"create-fs", "create-fs",
from_fn_async(subcontainer::create_subcontainer_fs) from_fn_async(subcontainer::create_subcontainer_fs)
.custom_ts(
subcontainer::CreateSubcontainerFsParams::inline_flattened(),
"[string, string]".into(),
)
.with_custom_display_fn(|_, (path, _)| Ok(println!("{}", path.display()))) .with_custom_display_fn(|_, (path, _)| Ok(println!("{}", path.display())))
.with_call_remote::<ContainerCliContext>(), .with_call_remote::<ContainerCliContext>(),
) )

View File

@@ -5,7 +5,6 @@ use crate::service::effects::prelude::*;
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindParams { pub struct BindParams {
id: HostId, id: HostId,
internal_port: u16, internal_port: u16,
@@ -30,7 +29,6 @@ pub async fn bind(
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ClearBindingsParams { pub struct ClearBindingsParams {
#[serde(default)] #[serde(default)]
@@ -52,7 +50,6 @@ pub async fn clear_bindings(
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetServicePortForwardParams { pub struct GetServicePortForwardParams {
#[ts(optional)] #[ts(optional)]

View File

@@ -7,7 +7,6 @@ use crate::service::rpc::CallbackId;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetHostInfoParams { pub struct GetHostInfoParams {
host_id: HostId, host_id: HostId,
#[ts(optional)] #[ts(optional)]

View File

@@ -8,7 +8,6 @@ use crate::service::rpc::CallbackId;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetContainerIpParams { pub struct GetContainerIpParams {
#[ts(optional)] #[ts(optional)]
package_id: Option<PackageId>, package_id: Option<PackageId>,

View File

@@ -9,7 +9,6 @@ use crate::service::effects::prelude::*;
use crate::service::rpc::CallbackId; use crate::service::rpc::CallbackId;
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ExportServiceInterfaceParams { pub struct ExportServiceInterfaceParams {
id: ServiceInterfaceId, id: ServiceInterfaceId,
@@ -83,7 +82,6 @@ pub async fn export_service_interface(
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetServiceInterfaceParams { pub struct GetServiceInterfaceParams {
#[ts(optional)] #[ts(optional)]
package_id: Option<PackageId>, package_id: Option<PackageId>,
@@ -124,7 +122,6 @@ pub async fn get_service_interface(
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ListServiceInterfacesParams { pub struct ListServiceInterfacesParams {
#[ts(optional)] #[ts(optional)]
@@ -167,7 +164,6 @@ pub async fn list_service_interfaces(
} }
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ClearServiceInterfacesParams { pub struct ClearServiceInterfacesParams {
pub except: Vec<ServiceInterfaceId>, pub except: Vec<ServiceInterfaceId>,

View File

@@ -14,7 +14,6 @@ use crate::util::serde::Pem;
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS, PartialEq, Eq)] #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS, PartialEq, Eq)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum Algorithm { pub enum Algorithm {
Ecdsa, Ecdsa,
Ed25519, Ed25519,
@@ -22,7 +21,6 @@ pub enum Algorithm {
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetSslCertificateParams { pub struct GetSslCertificateParams {
#[ts(type = "string[]")] #[ts(type = "string[]")]
hostnames: BTreeSet<InternedString>, hostnames: BTreeSet<InternedString>,
@@ -144,7 +142,6 @@ pub async fn get_ssl_certificate(
#[derive(Debug, Clone, Serialize, Deserialize, TS)] #[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetSslKeyParams { pub struct GetSslKeyParams {
#[ts(type = "string[]")] #[ts(type = "string[]")]
hostnames: BTreeSet<InternedString>, hostnames: BTreeSet<InternedString>,

View File

@@ -8,7 +8,6 @@ pub(super) use crate::service::effects::context::EffectContext;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct EventId { pub struct EventId {
#[serde(default)] #[serde(default)]
#[arg(default_value_t, long)] #[arg(default_value_t, long)]

View File

@@ -23,7 +23,6 @@ use sync_dummy as sync;
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct DestroySubcontainerFsParams { pub struct DestroySubcontainerFsParams {
guid: Guid, guid: Guid,
} }
@@ -70,7 +69,6 @@ pub async fn destroy_subcontainer_fs(
#[derive(Debug, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CreateSubcontainerFsParams { pub struct CreateSubcontainerFsParams {
image_id: ImageId, image_id: ImageId,
#[ts(type = "string | null")] #[ts(type = "string | null")]

View File

@@ -150,31 +150,39 @@ impl ExecParams {
cmd.env(k, v); cmd.env(k, v);
} }
if let Some(uid) = user.as_deref().and_then(|u| u.parse::<u32>().ok()) { if let Some((uid, gid)) =
cmd.uid(uid); if let Some(uid) = user.as_deref().and_then(|u| u.parse::<u32>().ok()) {
} else if let Some(user) = user { Some((uid, uid))
let passwd = std::fs::read_to_string("/etc/passwd") } else if let Some(user) = user {
.with_ctx(|_| (ErrorKind::Filesystem, "read /etc/passwd")); let passwd = std::fs::read_to_string("/etc/passwd")
if passwd.is_err() && user == "root" { .with_ctx(|_| (ErrorKind::Filesystem, "read /etc/passwd"));
cmd.uid(0); Some(if passwd.is_err() && user == "root" {
cmd.gid(0); (0, 0)
} else {
let (uid, gid) = passwd?
.lines()
.find_map(|l| {
let mut split = l.trim().split(":");
if user != split.next()? {
return None;
}
split.next(); // throw away x
Some((split.next()?.parse().ok()?, split.next()?.parse().ok()?))
// uid gid
})
.or_not_found(lazy_format!("{user} in /etc/passwd"))?;
(uid, gid)
})
} else { } else {
let (uid, gid) = passwd? None
.lines()
.find_map(|l| {
let mut split = l.trim().split(":");
if user != split.next()? {
return None;
}
split.next(); // throw away x
Some((split.next()?.parse().ok()?, split.next()?.parse().ok()?))
// uid gid
})
.or_not_found(lazy_format!("{user} in /etc/passwd"))?;
cmd.uid(uid);
cmd.gid(gid);
} }
}; {
std::os::unix::fs::chown("/proc/self/fd/0", Some(uid), Some(gid)).log_err();
std::os::unix::fs::chown("/proc/self/fd/1", Some(uid), Some(gid)).log_err();
std::os::unix::fs::chown("/proc/self/fd/2", Some(uid), Some(gid)).log_err();
cmd.uid(uid);
cmd.gid(gid);
}
if let Some(workdir) = workdir { if let Some(workdir) = workdir {
cmd.current_dir(workdir); cmd.current_dir(workdir);
} else { } else {

View File

@@ -4,7 +4,6 @@ use crate::service::rpc::CallbackId;
use crate::system::SmtpValue; use crate::system::SmtpValue;
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GetSystemSmtpParams { pub struct GetSystemSmtpParams {
#[arg(skip)] #[arg(skip)]

View File

@@ -7,7 +7,6 @@ use crate::volume::PKG_VOLUME_DIR;
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)] #[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetDataVersionParams { pub struct SetDataVersionParams {
#[ts(type = "string")] #[ts(type = "string")]
version: Option<String>, version: Option<String>,

View File

@@ -725,6 +725,8 @@ pub struct AttachParams {
name: Option<InternedString>, name: Option<InternedString>,
#[ts(type = "string | null")] #[ts(type = "string | null")]
image_id: Option<ImageId>, image_id: Option<ImageId>,
#[ts(type = "string | null")]
user: Option<InternedString>,
} }
pub async fn attach( pub async fn attach(
ctx: RpcContext, ctx: RpcContext,
@@ -738,6 +740,7 @@ pub async fn attach(
subcontainer, subcontainer,
image_id, image_id,
name, name,
user,
}: AttachParams, }: AttachParams,
) -> Result<Guid, Error> { ) -> Result<Guid, Error> {
let (container_id, subcontainer_id, image_id, workdir, root_command) = { let (container_id, subcontainer_id, image_id, workdir, root_command) = {
@@ -814,9 +817,26 @@ pub async fn attach(
.join("etc") .join("etc")
.join("passwd"); .join("passwd");
let root_command = get_passwd_root_command(passwd).await; let image_meta = serde_json::from_str::<Value>(
&tokio::fs::read_to_string(
root_dir
.join("media/startos/images/")
.join(&image_id)
.with_extension("json"),
)
.await?,
)
.with_kind(ErrorKind::Deserialization)?;
let workdir = attach_workdir(&image_id, &root_dir).await?; let root_command = get_passwd_command(
passwd,
user.as_deref()
.or_else(|| image_meta["user"].as_str())
.unwrap_or("root"),
)
.await;
let workdir = image_meta["workdir"].as_str().map(|s| s.to_owned());
if subcontainer_ids.len() > 1 { if subcontainer_ids.len() > 1 {
let subcontainer_ids = subcontainer_ids let subcontainer_ids = subcontainer_ids
@@ -849,6 +869,7 @@ pub async fn attach(
pty_size: Option<TermSize>, pty_size: Option<TermSize>,
image_id: ImageId, image_id: ImageId,
workdir: Option<String>, workdir: Option<String>,
user: Option<InternedString>,
root_command: &RootCommand, root_command: &RootCommand,
) -> Result<(), Error> { ) -> Result<(), Error> {
use axum::extract::ws::Message; use axum::extract::ws::Message;
@@ -871,6 +892,10 @@ pub async fn attach(
.with_extension("env"), .with_extension("env"),
); );
if let Some(user) = user {
cmd.arg("--user").arg(&*user);
}
if let Some(workdir) = workdir { if let Some(workdir) = workdir {
cmd.arg("--workdir").arg(workdir); cmd.arg("--workdir").arg(workdir);
} }
@@ -1032,6 +1057,7 @@ pub async fn attach(
pty_size, pty_size,
image_id, image_id,
workdir, workdir,
user,
&root_command, &root_command,
) )
.await .await
@@ -1051,19 +1077,46 @@ pub async fn attach(
Ok(guid) Ok(guid)
} }
async fn attach_workdir(image_id: &ImageId, root_dir: &Path) -> Result<Option<String>, Error> { #[derive(Deserialize, Serialize, TS)]
let path_str = root_dir.join("media/startos/images/"); #[serde(rename_all = "camelCase")]
pub struct ListSubcontainersParams {
let mut subcontainer_json = pub id: PackageId,
tokio::fs::File::open(path_str.join(image_id).with_extension("json")).await?;
let mut contents = vec![];
subcontainer_json.read_to_end(&mut contents).await?;
let subcontainer_json: serde_json::Value =
serde_json::from_slice(&contents).with_kind(ErrorKind::Filesystem)?;
Ok(subcontainer_json["workdir"].as_str().map(|x| x.to_string()))
} }
async fn get_passwd_root_command(etc_passwd_path: PathBuf) -> RootCommand { #[derive(Clone, Debug, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
pub struct SubcontainerInfo {
pub name: InternedString,
pub image_id: ImageId,
}
pub async fn list_subcontainers(
ctx: RpcContext,
ListSubcontainersParams { id }: ListSubcontainersParams,
) -> Result<BTreeMap<Guid, SubcontainerInfo>, Error> {
let service = ctx.services.get(&id).await;
let service_ref = service.as_ref().or_not_found(&id)?;
let container = &service_ref.seed.persistent_container;
let subcontainers = container.subcontainers.lock().await;
let result: BTreeMap<Guid, SubcontainerInfo> = subcontainers
.iter()
.map(|(guid, subcontainer)| {
(
guid.clone(),
SubcontainerInfo {
name: subcontainer.name.clone(),
image_id: subcontainer.image_id.clone(),
},
)
})
.collect();
Ok(result)
}
async fn get_passwd_command(etc_passwd_path: PathBuf, user: &str) -> RootCommand {
async { async {
let mut file = tokio::fs::File::open(etc_passwd_path).await?; let mut file = tokio::fs::File::open(etc_passwd_path).await?;
@@ -1074,8 +1127,8 @@ async fn get_passwd_root_command(etc_passwd_path: PathBuf) -> RootCommand {
for line in contents.split('\n') { for line in contents.split('\n') {
let line_information = line.split(':').collect::<Vec<_>>(); let line_information = line.split(':').collect::<Vec<_>>();
if let (Some(&"root"), Some(shell)) = if let (Some(&u), Some(shell)) = (line_information.first(), line_information.last())
(line_information.first(), line_information.last()) && u == user
{ {
return Ok(shell.to_string()); return Ok(shell.to_string());
} }
@@ -1106,6 +1159,8 @@ pub struct CliAttachParams {
#[arg(long, short)] #[arg(long, short)]
name: Option<InternedString>, name: Option<InternedString>,
#[arg(long, short)] #[arg(long, short)]
user: Option<InternedString>,
#[arg(long, short)]
image_id: Option<ImageId>, image_id: Option<ImageId>,
} }
#[instrument[skip_all]] #[instrument[skip_all]]
@@ -1147,6 +1202,7 @@ pub async fn cli_attach(
"subcontainer": params.subcontainer, "subcontainer": params.subcontainer,
"imageId": params.image_id, "imageId": params.image_id,
"name": params.name, "name": params.name,
"user": params.user,
}), }),
) )
.await?, .await?,

View File

@@ -8,7 +8,7 @@ use const_format::formatcp;
use josekit::jwk::Jwk; use josekit::jwk::Jwk;
use patch_db::json_ptr::ROOT; use patch_db::json_ptr::ROOT;
use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{Context, Empty, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, Empty, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::process::Command; use tokio::process::Command;
@@ -24,24 +24,24 @@ use crate::context::rpc::InitRpcContextPhases;
use crate::context::setup::SetupResult; use crate::context::setup::SetupResult;
use crate::context::{RpcContext, SetupContext}; use crate::context::{RpcContext, SetupContext};
use crate::db::model::Database; use crate::db::model::Database;
use crate::disk::REPAIR_DISK_PATH;
use crate::disk::fsck::RepairStrategy; use crate::disk::fsck::RepairStrategy;
use crate::disk::main::DEFAULT_PASSWORD; use crate::disk::main::DEFAULT_PASSWORD;
use crate::disk::mount::filesystem::ReadWrite;
use crate::disk::mount::filesystem::cifs::Cifs; use crate::disk::mount::filesystem::cifs::Cifs;
use crate::disk::mount::filesystem::ReadWrite;
use crate::disk::mount::guard::{GenericMountGuard, TmpMountGuard}; use crate::disk::mount::guard::{GenericMountGuard, TmpMountGuard};
use crate::disk::util::{DiskInfo, StartOsRecoveryInfo, pvscan, recovery_info}; use crate::disk::util::{pvscan, recovery_info, DiskInfo, StartOsRecoveryInfo};
use crate::init::{InitPhases, InitResult, init}; use crate::disk::REPAIR_DISK_PATH;
use crate::init::{init, InitPhases, InitResult};
use crate::net::ssl::root_ca_start_time; use crate::net::ssl::root_ca_start_time;
use crate::prelude::*; use crate::prelude::*;
use crate::progress::{FullProgress, PhaseProgressTrackerHandle, ProgressUnits}; use crate::progress::{FullProgress, PhaseProgressTrackerHandle, ProgressUnits};
use crate::rpc_continuations::Guid; use crate::rpc_continuations::Guid;
use crate::shutdown::Shutdown; use crate::shutdown::Shutdown;
use crate::system::sync_kiosk; use crate::system::sync_kiosk;
use crate::util::Invoke;
use crate::util::crypto::EncryptedWire; use crate::util::crypto::EncryptedWire;
use crate::util::io::{Counter, create_file, dir_copy, dir_size}; use crate::util::io::{create_file, dir_copy, dir_size, Counter};
use crate::{DATA_DIR, Error, ErrorKind, MAIN_DATA, PACKAGE_DATA, PLATFORM, ResultExt}; use crate::util::Invoke;
use crate::{Error, ErrorKind, ResultExt, DATA_DIR, MAIN_DATA, PACKAGE_DATA, PLATFORM};
pub fn setup<C: Context>() -> ParentHandler<C> { pub fn setup<C: Context>() -> ParentHandler<C> {
ParentHandler::new() ParentHandler::new()
@@ -60,13 +60,16 @@ pub fn setup<C: Context>() -> ParentHandler<C> {
"get-pubkey", "get-pubkey",
from_fn_async(get_pubkey) from_fn_async(get_pubkey)
.with_metadata("authenticated", Value::Bool(false)) .with_metadata("authenticated", Value::Bool(false))
.no_cli(), .no_cli()
.custom_ts("{}".to_string(), "unknown".to_string()),
) )
.subcommand("exit", from_fn_async(exit).no_cli()) .subcommand("exit", from_fn_async(exit).no_cli())
.subcommand("logs", crate::system::logs::<SetupContext>()) .subcommand("logs", crate::system::logs::<SetupContext>().no_ts())
.subcommand( .subcommand(
"logs", "logs",
from_fn_async(crate::logs::cli_logs::<SetupContext, Empty>).no_display(), from_fn_async(crate::logs::cli_logs::<SetupContext, Empty>)
.no_display()
.no_ts(),
) )
.subcommand("restart", from_fn_async(restart).no_cli()) .subcommand("restart", from_fn_async(restart).no_cli())
} }
@@ -124,7 +127,6 @@ async fn setup_init(
#[derive(Deserialize, Serialize, TS)] #[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AttachParams { pub struct AttachParams {
#[serde(rename = "startOsPassword")] #[serde(rename = "startOsPassword")]
password: Option<EncryptedWire>, password: Option<EncryptedWire>,
@@ -203,7 +205,6 @@ pub async fn attach(
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
#[serde(tag = "status")] #[serde(tag = "status")]
pub enum SetupStatusRes { pub enum SetupStatusRes {
Complete(SetupResult), Complete(SetupResult),
@@ -212,7 +213,6 @@ pub enum SetupStatusRes {
#[derive(Debug, Deserialize, Serialize, TS)] #[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetupProgress { pub struct SetupProgress {
pub progress: FullProgress, pub progress: FullProgress,
pub guid: Guid, pub guid: Guid,
@@ -249,7 +249,6 @@ pub fn cifs<C: Context>() -> ParentHandler<C> {
#[derive(Deserialize, Serialize, TS)] #[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct VerifyCifsParams { pub struct VerifyCifsParams {
hostname: String, hostname: String,
path: PathBuf, path: PathBuf,
@@ -306,7 +305,6 @@ pub enum RecoverySource<Password> {
#[derive(Deserialize, Serialize, TS)] #[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetupExecuteParams { pub struct SetupExecuteParams {
start_os_logicalname: PathBuf, start_os_logicalname: PathBuf,
start_os_password: EncryptedWire, start_os_password: EncryptedWire,
@@ -499,7 +497,7 @@ async fn fresh_setup(
.. ..
}: SetupExecuteProgress, }: SetupExecuteProgress,
) -> Result<(SetupResult, RpcContext), Error> { ) -> Result<(SetupResult, RpcContext), Error> {
let account = AccountInfo::new(start_os_password, root_ca_start_time().await?)?; let account = AccountInfo::new(start_os_password, root_ca_start_time().await)?;
let db = ctx.db().await?; let db = ctx.db().await?;
let kiosk = Some(kiosk.unwrap_or(true)).filter(|_| &*PLATFORM != "raspberrypi"); let kiosk = Some(kiosk.unwrap_or(true)).filter(|_| &*PLATFORM != "raspberrypi");
sync_kiosk(kiosk).await?; sync_kiosk(kiosk).await?;

View File

@@ -15,7 +15,6 @@ use crate::util::serde::Base64;
#[derive(Clone, Debug, Deserialize, Serialize, HasModel, PartialEq, Eq, TS)] #[derive(Clone, Debug, Deserialize, Serialize, HasModel, PartialEq, Eq, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct Blake3Commitment { pub struct Blake3Commitment {
pub hash: Base64<[u8; 32]>, pub hash: Base64<[u8; 32]>,
#[ts(type = "number")] #[ts(type = "number")]

View File

@@ -14,7 +14,6 @@ use crate::util::serde::Base64;
#[derive(Debug, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct MerkleArchiveCommitment { pub struct MerkleArchiveCommitment {
pub root_sighash: Base64<[u8; 32]>, pub root_sighash: Base64<[u8; 32]>,
#[ts(type = "number")] #[ts(type = "number")]

View File

@@ -20,7 +20,6 @@ use crate::util::serde::Base64;
#[derive(Clone, Debug, Deserialize, Serialize, HasModel, PartialEq, Eq, TS)] #[derive(Clone, Debug, Deserialize, Serialize, HasModel, PartialEq, Eq, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct RequestCommitment { pub struct RequestCommitment {
#[ts(type = "number")] #[ts(type = "number")]
pub timestamp: i64, pub timestamp: i64,

View File

@@ -119,7 +119,7 @@ impl SignatureScheme for AnyScheme {
} }
#[derive(Clone, Debug, PartialEq, Eq, TS)] #[derive(Clone, Debug, PartialEq, Eq, TS)]
#[ts(export, type = "string")] #[ts(type = "string")]
#[non_exhaustive] #[non_exhaustive]
pub enum AnySigningKey { pub enum AnySigningKey {
Ed25519(<Ed25519 as SignatureScheme>::SigningKey), Ed25519(<Ed25519 as SignatureScheme>::SigningKey),
@@ -191,7 +191,7 @@ impl Serialize for AnySigningKey {
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, TS)] #[derive(Clone, Debug, PartialEq, Eq, Hash, TS)]
#[ts(export, type = "string")] #[ts(type = "string")]
#[non_exhaustive] #[non_exhaustive]
pub enum AnyVerifyingKey { pub enum AnyVerifyingKey {
Ed25519(<Ed25519 as SignatureScheme>::VerifyingKey), Ed25519(<Ed25519 as SignatureScheme>::VerifyingKey),
@@ -278,7 +278,7 @@ impl digest::Update for AnyDigest {
} }
#[derive(Clone, Debug, PartialEq, Eq, TS)] #[derive(Clone, Debug, PartialEq, Eq, TS)]
#[ts(export, type = "string")] #[ts(type = "string")]
pub enum AnySignature { pub enum AnySignature {
Ed25519(<Ed25519 as SignatureScheme>::Signature), Ed25519(<Ed25519 as SignatureScheme>::Signature),
} }

View File

@@ -59,7 +59,7 @@ impl ValueParserFactory for SshPubKey {
} }
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SshKeyResponse { pub struct SshKeyResponse {
pub alg: String, pub alg: String,

View File

@@ -8,7 +8,7 @@ use color_eyre::eyre::eyre;
use futures::{FutureExt, TryStreamExt}; use futures::{FutureExt, TryStreamExt};
use imbl::vector; use imbl::vector;
use imbl_value::InternedString; use imbl_value::InternedString;
use rpc_toolkit::{Context, Empty, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, Empty, HandlerExt, ParentHandler, UnknownTS};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use tokio::process::Command; use tokio::process::Command;
use tokio::sync::broadcast::Receiver; use tokio::sync::broadcast::Receiver;
@@ -21,12 +21,12 @@ use crate::logs::{LogSource, LogsParams, SYSTEM_UNIT};
use crate::prelude::*; use crate::prelude::*;
use crate::rpc_continuations::{Guid, RpcContinuation, RpcContinuations}; use crate::rpc_continuations::{Guid, RpcContinuation, RpcContinuations};
use crate::shutdown::Shutdown; use crate::shutdown::Shutdown;
use crate::util::Invoke; use crate::util::cpupower::{get_available_governors, set_governor, Governor};
use crate::util::cpupower::{Governor, get_available_governors, set_governor};
use crate::util::io::open_file; use crate::util::io::open_file;
use crate::util::net::WebSocketExt; use crate::util::net::WebSocketExt;
use crate::util::serde::{HandlerExtSerde, WithIoFormat, display_serializable}; use crate::util::serde::{display_serializable, HandlerExtSerde, WithIoFormat};
use crate::util::sync::Watch; use crate::util::sync::Watch;
use crate::util::Invoke;
use crate::{MAIN_DATA, PACKAGE_DATA}; use crate::{MAIN_DATA, PACKAGE_DATA};
pub fn experimental<C: Context>() -> ParentHandler<C> { pub fn experimental<C: Context>() -> ParentHandler<C> {
@@ -116,7 +116,7 @@ pub async fn zram(ctx: RpcContext, ZramParams { enable }: ZramParams) -> Result<
Ok(()) Ok(())
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, TS)]
pub struct GovernorInfo { pub struct GovernorInfo {
current: Option<Governor>, current: Option<Governor>,
available: BTreeSet<Governor>, available: BTreeSet<Governor>,
@@ -186,7 +186,7 @@ pub async fn governor(
Ok(GovernorInfo { current, available }) Ok(GovernorInfo { current, available })
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, TS)]
pub struct TimeInfo { pub struct TimeInfo {
now: String, now: String,
uptime: u64, uptime: u64,
@@ -242,11 +242,12 @@ pub async fn time(ctx: RpcContext, _: Empty) -> Result<TimeInfo, Error> {
}) })
} }
pub fn logs<C: Context + AsRef<RpcContinuations>>() -> ParentHandler<C, LogsParams> { pub fn logs<C: Context + AsRef<RpcContinuations>>() -> UnknownTS<ParentHandler<C, LogsParams>> {
crate::logs::logs(|_: &C, _| async { Ok(LogSource::Unit(SYSTEM_UNIT)) }) crate::logs::logs(|_: &C, _| async { Ok(LogSource::Unit(SYSTEM_UNIT)) })
} }
pub fn kernel_logs<C: Context + AsRef<RpcContinuations>>() -> ParentHandler<C, LogsParams> { pub fn kernel_logs<C: Context + AsRef<RpcContinuations>>() -> UnknownTS<ParentHandler<C, LogsParams>>
{
crate::logs::logs(|_: &C, _| async { Ok(LogSource::Kernel) }) crate::logs::logs(|_: &C, _| async { Ok(LogSource::Kernel) })
} }
@@ -319,8 +320,8 @@ pub fn kiosk<C: Context>() -> ParentHandler<C> {
) )
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, TS)]
pub struct MetricLeaf<T> { pub struct MetricLeaf<T: TS> {
value: T, value: T,
unit: Option<String>, unit: Option<String>,
} }
@@ -470,7 +471,6 @@ pub struct MetricsDisk {
#[derive(Deserialize, Serialize, Clone, Debug, TS)] #[derive(Deserialize, Serialize, Clone, Debug, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Metrics { pub struct Metrics {
general: MetricsGeneral, general: MetricsGeneral,
memory: MetricsMemory, memory: MetricsMemory,
@@ -961,7 +961,6 @@ async fn get_disk_info() -> Result<MetricsDisk, Error> {
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SmtpValue { pub struct SmtpValue {
#[arg(long)] #[arg(long)]
@@ -1007,7 +1006,6 @@ pub async fn clear_system_smtp(ctx: RpcContext) -> Result<(), Error> {
Ok(()) Ok(())
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Parser, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct TestSmtpParams { pub struct TestSmtpParams {
#[arg(long)] #[arg(long)]

View File

@@ -3,14 +3,31 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
use clap::Parser; use clap::Parser;
use imbl_value::InternedString; use imbl_value::InternedString;
use ipnet::Ipv4Net; use ipnet::Ipv4Net;
use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, Empty, HandlerArgs, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::context::CliContext; use crate::context::CliContext;
use crate::prelude::*; use crate::prelude::*;
use crate::tunnel::context::TunnelContext; use crate::tunnel::context::TunnelContext;
use crate::tunnel::wg::{WgConfig, WgSubnetClients, WgSubnetConfig}; use crate::tunnel::wg::{WgConfig, WgSubnetClients, WgSubnetConfig};
use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::serde::{display_serializable, HandlerExtSerde};
#[test]
fn export_bindings_tunnel_api() {
use rpc_toolkit::HandlerTS;
std::fs::create_dir_all("./bindings").unwrap();
std::fs::write(
"./bindings/tunnel-api.ts",
format!(
"export type TunnelApi = {}",
tunnel_api::<TunnelContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
}
pub fn tunnel_api<C: Context>() -> ParentHandler<C> { pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new() ParentHandler::new()
@@ -54,9 +71,10 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
) )
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SubnetParams { pub struct SubnetParams {
#[ts(type = "string")]
subnet: Ipv4Net, subnet: Ipv4Net,
} }
@@ -132,7 +150,7 @@ pub fn device_api<C: Context>() -> ParentHandler<C> {
) )
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AddSubnetParams { pub struct AddSubnetParams {
name: InternedString, name: InternedString,
@@ -186,9 +204,10 @@ pub async fn remove_subnet(
server.sync().await server.sync().await
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AddDeviceParams { pub struct AddDeviceParams {
#[ts(type = "string")]
subnet: Ipv4Net, subnet: Ipv4Net,
name: InternedString, name: InternedString,
ip: Option<Ipv4Addr>, ip: Option<Ipv4Addr>,
@@ -247,9 +266,10 @@ pub async fn add_device(
server.sync().await server.sync().await
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RemoveDeviceParams { pub struct RemoveDeviceParams {
#[ts(type = "string")]
subnet: Ipv4Net, subnet: Ipv4Net,
ip: Ipv4Addr, ip: Ipv4Addr,
} }
@@ -275,9 +295,10 @@ pub async fn remove_device(
server.sync().await server.sync().await
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ListDevicesParams { pub struct ListDevicesParams {
#[ts(type = "string")]
subnet: Ipv4Net, subnet: Ipv4Net,
} }
@@ -295,13 +316,15 @@ pub async fn list_devices(
.de() .de()
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ShowConfigParams { pub struct ShowConfigParams {
#[ts(type = "string")]
subnet: Ipv4Net, subnet: Ipv4Net,
ip: Ipv4Addr, ip: Ipv4Addr,
wan_addr: Option<IpAddr>, wan_addr: Option<IpAddr>,
#[serde(rename = "__ConnectInfo_local_addr")] #[serde(rename = "__ConnectInfo_local_addr")]
#[ts(skip)]
#[arg(skip)] #[arg(skip)]
local_addr: Option<SocketAddr>, local_addr: Option<SocketAddr>,
} }
@@ -359,7 +382,7 @@ pub async fn show_config(
.to_string()) .to_string())
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AddPortForwardParams { pub struct AddPortForwardParams {
source: SocketAddrV4, source: SocketAddrV4,
@@ -383,7 +406,7 @@ pub async fn add_forward(
Ok(()) Ok(())
} }
#[derive(Deserialize, Serialize, Parser)] #[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RemovePortForwardParams { pub struct RemovePortForwardParams {
source: SocketAddrV4, source: SocketAddrV4,

View File

@@ -3,11 +3,11 @@ use imbl::HashMap;
use imbl_value::InternedString; use imbl_value::InternedString;
use itertools::Itertools; use itertools::Itertools;
use patch_db::HasModel; use patch_db::HasModel;
use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, Empty, HandlerArgs, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS; use ts_rs::TS;
use crate::auth::{Sessions, check_password}; use crate::auth::{check_password, Sessions};
use crate::context::CliContext; use crate::context::CliContext;
use crate::middleware::auth::AuthContext; use crate::middleware::auth::AuthContext;
use crate::middleware::signature::SignatureAuthContext; use crate::middleware::signature::SignatureAuthContext;
@@ -16,7 +16,7 @@ use crate::rpc_continuations::OpenAuthedContinuations;
use crate::sign::AnyVerifyingKey; use crate::sign::AnyVerifyingKey;
use crate::tunnel::context::TunnelContext; use crate::tunnel::context::TunnelContext;
use crate::tunnel::db::TunnelDatabase; use crate::tunnel::db::TunnelDatabase;
use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::serde::{display_serializable, HandlerExtSerde};
use crate::util::sync::SyncMutex; use crate::util::sync::SyncMutex;
impl SignatureAuthContext for TunnelContext { impl SignatureAuthContext for TunnelContext {
@@ -113,27 +113,12 @@ impl AuthContext for TunnelContext {
#[derive(Clone, Debug, Deserialize, Serialize, HasModel, TS, Parser)] #[derive(Clone, Debug, Deserialize, Serialize, HasModel, TS, Parser)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[model = "Model<Self>"] #[model = "Model<Self>"]
#[ts(export)]
pub struct SignerInfo { pub struct SignerInfo {
pub name: InternedString, pub name: InternedString,
} }
pub fn auth_api<C: Context>() -> ParentHandler<C> { pub fn auth_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new() crate::auth::auth::<C, TunnelContext>()
.subcommand(
"login",
from_fn_async(crate::auth::login_impl::<TunnelContext>)
.with_metadata("login", Value::Bool(true))
.no_cli(),
)
.subcommand(
"logout",
from_fn_async(crate::auth::logout::<TunnelContext>)
.with_metadata("get_session", Value::Bool(true))
.no_display()
.with_about("Log out of current auth session")
.with_call_remote::<CliContext>(),
)
.subcommand("set-password", from_fn_async(set_password_rpc).no_cli()) .subcommand("set-password", from_fn_async(set_password_rpc).no_cli())
.subcommand( .subcommand(
"set-password", "set-password",
@@ -170,22 +155,22 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
"list", "list",
from_fn_async(list_keys) from_fn_async(list_keys)
.with_metadata("sync_db", Value::Bool(true)) .with_metadata("sync_db", Value::Bool(true))
.custom_ts(
Empty::inline_flattened(),
std::collections::HashMap::<AnyVerifyingKey, SignerInfo>::inline_flattened(),
)
.with_display_serializable() .with_display_serializable()
.with_custom_display_fn(|HandlerArgs { params, .. }, res| { .with_custom_display_fn(|HandlerArgs { params, .. }, res| {
use prettytable::*; use prettytable::*;
if let Some(format) = params.format { if let Some(format) = params.format {
return display_serializable(format, res); return display_serializable(format, res);
} }
let mut table = Table::new(); let mut table = Table::new();
table.add_row(row![bc => "NAME", "KEY"]); table.add_row(row![bc => "NAME", "KEY"]);
for (key, info) in res { for (key, info) in res {
table.add_row(row![info.name, key]); table.add_row(row![info.name, key]);
} }
table.print_tty(false)?; table.print_tty(false)?;
Ok(()) Ok(())
}) })
.with_about("List authorized keys") .with_about("List authorized keys")
@@ -194,7 +179,7 @@ pub fn auth_api<C: Context>() -> ParentHandler<C> {
) )
} }
#[derive(Debug, Deserialize, Serialize, Parser)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AddKeyParams { pub struct AddKeyParams {
pub name: InternedString, pub name: InternedString,
@@ -216,7 +201,7 @@ pub async fn add_key(
.result .result
} }
#[derive(Debug, Deserialize, Serialize, Parser)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RemoveKeyParams { pub struct RemoveKeyParams {
pub key: AnyVerifyingKey, pub key: AnyVerifyingKey,
@@ -240,7 +225,7 @@ pub async fn list_keys(ctx: TunnelContext) -> Result<HashMap<AnyVerifyingKey, Si
ctx.db.peek().await.into_auth_pubkeys().de() ctx.db.peek().await.into_auth_pubkeys().de()
} }
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
pub struct SetPasswordParams { pub struct SetPasswordParams {
pub password: String, pub password: String,
} }

View File

@@ -9,7 +9,6 @@ use cookie::{Cookie, Expiration, SameSite};
use http::HeaderMap; use http::HeaderMap;
use imbl::OrdMap; use imbl::OrdMap;
use imbl_value::InternedString; use imbl_value::InternedString;
use include_dir::Dir;
use models::GatewayId; use models::GatewayId;
use patch_db::PatchDb; use patch_db::PatchDb;
use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::yajrc::RpcError;
@@ -34,7 +33,7 @@ use crate::rpc_continuations::{OpenAuthedContinuations, RpcContinuations};
use crate::tunnel::TUNNEL_DEFAULT_LISTEN; use crate::tunnel::TUNNEL_DEFAULT_LISTEN;
use crate::tunnel::api::tunnel_api; use crate::tunnel::api::tunnel_api;
use crate::tunnel::db::TunnelDatabase; use crate::tunnel::db::TunnelDatabase;
use crate::tunnel::wg::WIREGUARD_INTERFACE_NAME; use crate::tunnel::wg::{WIREGUARD_INTERFACE_NAME, WgSubnetConfig};
use crate::util::Invoke; use crate::util::Invoke;
use crate::util::collections::OrdMapIterMut; use crate::util::collections::OrdMapIterMut;
use crate::util::io::read_file_to_string; use crate::util::io::read_file_to_string;
@@ -101,7 +100,17 @@ impl TunnelContext {
let db_path = datadir.join("tunnel.db"); let db_path = datadir.join("tunnel.db");
let db = TypedPatchDb::<TunnelDatabase>::load_or_init( let db = TypedPatchDb::<TunnelDatabase>::load_or_init(
PatchDb::open(&db_path).await?, PatchDb::open(&db_path).await?,
|| async { Ok(Default::default()) }, || async {
let mut db = TunnelDatabase::default();
db.wg.subnets.0.insert(
"10.59.0.1/24".parse()?,
WgSubnetConfig {
name: "Default Subnet".into(),
..Default::default()
},
);
Ok(db)
},
) )
.await?; .await?;
let listen = config.tunnel_listen.unwrap_or(TUNNEL_DEFAULT_LISTEN); let listen = config.tunnel_listen.unwrap_or(TUNNEL_DEFAULT_LISTEN);

View File

@@ -9,10 +9,10 @@ use imbl::{HashMap, OrdMap};
use imbl_value::InternedString; use imbl_value::InternedString;
use itertools::Itertools; use itertools::Itertools;
use models::GatewayId; use models::GatewayId;
use patch_db::Dump;
use patch_db::json_ptr::{JsonPointer, ROOT}; use patch_db::json_ptr::{JsonPointer, ROOT};
use patch_db::Dump;
use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, HandlerArgs, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tracing::instrument; use tracing::instrument;
use ts_rs::TS; use ts_rs::TS;
@@ -28,7 +28,7 @@ use crate::tunnel::context::TunnelContext;
use crate::tunnel::web::WebserverInfo; use crate::tunnel::web::WebserverInfo;
use crate::tunnel::wg::WgServer; use crate::tunnel::wg::WgServer;
use crate::util::net::WebSocketExt; use crate::util::net::WebSocketExt;
use crate::util::serde::{HandlerExtSerde, apply_expr}; use crate::util::serde::{apply_expr, HandlerExtSerde};
#[derive(Default, Deserialize, Serialize, HasModel, TS)] #[derive(Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@@ -47,7 +47,7 @@ pub struct TunnelDatabase {
#[test] #[test]
fn export_bindings_tunnel_db() { fn export_bindings_tunnel_db() {
TunnelDatabase::export_all_to("bindings/tunnel").unwrap(); TunnelDatabase::export_all_to("bindings/database/tunnel").unwrap();
} }
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)] #[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
@@ -69,13 +69,18 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
"dump", "dump",
from_fn_async(cli_dump) from_fn_async(cli_dump)
.with_display_serializable() .with_display_serializable()
.no_ts()
.with_about("Filter/query db to display tables and records"), .with_about("Filter/query db to display tables and records"),
) )
.subcommand( .subcommand(
"dump", "dump",
from_fn_async(dump) from_fn_async(dump)
.with_metadata("admin", Value::Bool(true)) .with_metadata("admin", Value::Bool(true))
.no_cli(), .no_cli()
.custom_ts(
DumpParams::inline_flattened(),
format!("{{ id: number; value: unknown }}"),
),
) )
.subcommand( .subcommand(
"subscribe", "subscribe",
@@ -87,6 +92,7 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
"apply", "apply",
from_fn_async(cli_apply) from_fn_async(cli_apply)
.no_display() .no_display()
.no_ts()
.with_about("Update a db record"), .with_about("Update a db record"),
) )
.subcommand( .subcommand(

View File

@@ -1,33 +1,32 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use std::net::{IpAddr, Ipv6Addr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
use std::sync::Arc; use std::sync::Arc;
use clap::Parser; use clap::Parser;
use hickory_client::proto::rr::rdata::cert; use imbl_value::{json, InternedString};
use imbl_value::{InternedString, json};
use itertools::Itertools; use itertools::Itertools;
use openssl::pkey::{PKey, Private}; use openssl::pkey::{PKey, Private};
use openssl::x509::X509; use openssl::x509::X509;
use rpc_toolkit::{ use rpc_toolkit::{
Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async, from_fn_async_local, from_fn_async, from_fn_async_local, Context, Empty, HandlerArgs, HandlerExt, ParentHandler,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::rustls::crypto::CryptoProvider; use tokio_rustls::rustls::crypto::CryptoProvider;
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
use tokio_rustls::rustls::server::ClientHello; use tokio_rustls::rustls::server::ClientHello;
use tokio_rustls::rustls::ServerConfig;
use ts_rs::TS; use ts_rs::TS;
use crate::context::CliContext; use crate::context::CliContext;
use crate::net::ssl::SANInfo; use crate::hostname::Hostname;
use crate::net::ssl::{root_ca_start_time, SANInfo};
use crate::net::tls::TlsHandler; use crate::net::tls::TlsHandler;
use crate::net::web_server::Accept; use crate::net::web_server::Accept;
use crate::prelude::*; use crate::prelude::*;
use crate::tunnel::auth::SetPasswordParams; use crate::tunnel::auth::SetPasswordParams;
use crate::tunnel::context::TunnelContext; use crate::tunnel::context::TunnelContext;
use crate::tunnel::db::TunnelDatabase; use crate::tunnel::db::TunnelDatabase;
use crate::util::serde::{HandlerExtSerde, Pem, display_serializable}; use crate::util::serde::{display_serializable, HandlerExtSerde, Pem};
use crate::util::tui::{choose, choose_custom_display, parse_as, prompt, prompt_multiline}; use crate::util::tui::{choose, choose_custom_display, parse_as, prompt, prompt_multiline};
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
@@ -134,7 +133,7 @@ pub fn web_api<C: Context>() -> ParentHandler<C> {
.subcommand( .subcommand(
"generate-certificate", "generate-certificate",
from_fn_async(generate_certificate) from_fn_async(generate_certificate)
.with_about("Generate a self signed certificaet to use for the webserver") .with_about("Generate a certificate to use for the webserver")
.with_call_remote::<CliContext>(), .with_call_remote::<CliContext>(),
) )
.subcommand( .subcommand(
@@ -256,7 +255,11 @@ pub async fn import_certificate_cli(
chain.push(cert.0); chain.push(cert.0);
if is_root { Ok(Some(())) } else { Ok(None) } if is_root {
Ok(Some(()))
} else {
Ok(None)
}
} else { } else {
Ok(None) Ok(None)
} }
@@ -277,7 +280,7 @@ pub async fn import_certificate_cli(
Ok(()) Ok(())
} }
#[derive(Debug, Deserialize, Serialize, Parser)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
pub struct GenerateCertParams { pub struct GenerateCertParams {
#[arg(help = "Subject Alternative Name(s)")] #[arg(help = "Subject Alternative Name(s)")]
pub subject: Vec<InternedString>, pub subject: Vec<InternedString>,
@@ -286,11 +289,21 @@ pub struct GenerateCertParams {
pub async fn generate_certificate( pub async fn generate_certificate(
ctx: TunnelContext, ctx: TunnelContext,
GenerateCertParams { subject }: GenerateCertParams, GenerateCertParams { subject }: GenerateCertParams,
) -> Result<Pem<X509>, Error> { ) -> Result<Pem<Vec<X509>>, Error> {
let saninfo = SANInfo::new(&subject.into_iter().collect()); let saninfo = SANInfo::new(&subject.into_iter().collect());
let root_key = crate::net::ssl::generate_key()?;
let root_cert = crate::net::ssl::make_root_cert(
&root_key,
&Hostname("start-tunnel".into()),
root_ca_start_time().await,
)?;
let int_key = crate::net::ssl::generate_key()?;
let int_cert = crate::net::ssl::make_int_cert((&root_key, &root_cert), &int_key)?;
let key = crate::net::ssl::generate_key()?; let key = crate::net::ssl::generate_key()?;
let cert = crate::net::ssl::make_self_signed((&key, &saninfo))?; let cert = crate::net::ssl::make_leaf_cert((&int_key, &int_cert), (&key, &saninfo))?;
let chain = Pem(vec![cert, int_cert, root_cert]);
ctx.db ctx.db
.mutate(|db| { .mutate(|db| {
@@ -298,13 +311,13 @@ pub async fn generate_certificate(
.as_certificate_mut() .as_certificate_mut()
.ser(&Some(TunnelCertData { .ser(&Some(TunnelCertData {
key: Pem(key), key: Pem(key),
cert: Pem(vec![cert.clone()]), cert: chain.clone(),
})) }))
}) })
.await .await
.result?; .result?;
Ok(Pem(cert)) Ok(chain)
} }
pub async fn get_certificate(ctx: TunnelContext) -> Result<Option<Pem<Vec<X509>>>, Error> { pub async fn get_certificate(ctx: TunnelContext) -> Result<Option<Pem<Vec<X509>>>, Error> {
@@ -318,7 +331,7 @@ pub async fn get_certificate(ctx: TunnelContext) -> Result<Option<Pem<Vec<X509>>
.transpose() .transpose()
} }
#[derive(Debug, Deserialize, Serialize, Parser)] #[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SetListenParams { pub struct SetListenParams {
pub listen: SocketAddr, pub listen: SocketAddr,
@@ -501,8 +514,12 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> {
let cert = from_value::<Pem<Vec<X509>>>( let cert = from_value::<Pem<Vec<X509>>>(
ctx.call_remote::<TunnelContext>("web.get-certificate", json!({})) ctx.call_remote::<TunnelContext>("web.get-certificate", json!({}))
.await?, .await?,
)?; )?
println!("📝 SSL Certificate:"); .0
.pop()
.map(Pem)
.or_not_found("certificate in chain")?;
println!("📝 Root SSL Certificate:");
print!("{cert}"); print!("{cert}");
println!(concat!( println!(concat!(
@@ -594,7 +611,7 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> {
impl std::fmt::Display for Choice { impl std::fmt::Display for Choice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::Generate => write!(f, "Generate a Self Signed Certificate"), Self::Generate => write!(f, "Generate an SSL certificate"),
Self::Provide => write!(f, "Provide your own certificate and key"), Self::Provide => write!(f, "Provide your own certificate and key"),
} }
} }
@@ -602,7 +619,7 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> {
let options = vec![Choice::Generate, Choice::Provide]; let options = vec![Choice::Generate, Choice::Provide];
let choice = choose( let choice = choose(
concat!( concat!(
"Select whether to autogenerate a self-signed SSL certificate ", "Select whether to generate an SSL certificate ",
"or provide your own certificate and key:" "or provide your own certificate and key:"
), ),
&options, &options,

View File

@@ -209,7 +209,7 @@ where
}) })
} }
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize, TS)]
pub struct ClientConfig { pub struct ClientConfig {
client_config: WgConfig, client_config: WgConfig,
client_addr: Ipv4Addr, client_addr: Ipv4Addr,

View File

@@ -217,7 +217,7 @@ pub async fn cli_update_system(
} }
/// What is the status of the updates? /// What is the status of the updates?
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] #[derive(serde::Serialize, serde::Deserialize, Clone, Debug, TS)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub enum UpdateResult { pub enum UpdateResult {
NoUpdates, NoUpdates,

View File

@@ -3,8 +3,9 @@ use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ts_rs::TS;
#[derive(Clone, Serialize)] #[derive(Clone, Serialize, TS)]
pub struct EqSet<T: Eq>(Vec<T>); pub struct EqSet<T: Eq>(Vec<T>);
impl<T: Eq> Default for EqSet<T> { impl<T: Eq> Default for EqSet<T> {
fn default() -> Self { fn default() -> Self {

View File

@@ -17,7 +17,6 @@ pub const GOVERNOR_HEIRARCHY: &[Governor] = &[
#[derive( #[derive(
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, TS, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, TS,
)] )]
#[ts(export, type = "string")]
pub struct Governor(Cow<'static, str>); pub struct Governor(Cow<'static, str>);
impl std::str::FromStr for Governor { impl std::str::FromStr for Governor {
type Err = std::convert::Infallible; type Err = std::convert::Infallible;

View File

@@ -57,7 +57,6 @@ pub fn decrypt_slice(input: impl AsRef<[u8]>, password: impl AsRef<[u8]>) -> Vec
} }
#[derive(Debug, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct EncryptedWire { pub struct EncryptedWire {
#[ts(type = "any")] #[ts(type = "any")]
encrypted: Value, encrypted: Value,

Some files were not shown because too many files have changed in this diff Show More