[package]
name = "bestool"
version = "1.38.0"
edition = "2024"
default-run = "bestool"

authors = ["Félix Saparelli <felix@passcod.name>", "BES Developers <contact@bes.au>"]
license = "GPL-3.0-or-later"
description = "BES Deployment tooling"
keywords = ["bes", "tamanu", "tupaia"]
categories = ["command-line-utilities"]
repository = "https://github.com/beyondessential/bestool"
readme = "../../README.md"
exclude.workspace = true

[lints]
workspace = true

[dependencies]
algae-cli = { version = "1.1.6", path = "../algae-cli", optional = true }
axum = { version = "0.8.9", optional = true }
bestool-alertd = { version = "16.0.0", path = "../alertd", default-features = false, optional = true }
bestool-canopy = { version = "0.6.0", path = "../canopy", optional = true }
bestool-kopia = { version = "0.3.4", path = "../kopia", optional = true }
bestool-postgres = { version = "1.1.0", path = "../postgres", optional = true }
bestool-psql = { version = "1.7.5", path = "../psql", default-features = false, optional = true }
bestool-tamanu = { version = "0.14.6", path = "../tamanu", default-features = false, optional = true }
binstalk-downloader = { version = "0.13.38", optional = true, features = ["hickory-dns"] }
blake3 = { version = "1.8.5", optional = true }
boxcar = "0.2.14"
bytes = "1.10.0"
base64 = { version = "0.22.1", optional = true }
clap = { workspace = true, features = ["env", "unicode", "string"] }
clap_complete = { version = "4.6.3", optional = true }
clap-markdown = "0.1.5"
comfy-table = { version = "7.2.0", optional = true }
crossterm = { version = "0.29.0", optional = true }
ctrlc = { version = "3.5.0", optional = true }
detect-targets = { version = "0.1.84", optional = true }
dirs = { version = "6.0.0", optional = true }
duct = { version = "1.1.0", optional = true }
embedded-graphics = { version = "0.8.1", optional = true }
fs4 = { version = "1.1.0", features = ["tokio"], optional = true }
futures = { workspace = true }
glob = { version = "0.3.3", optional = true }
hickory-resolver = { version = "0.26.1", optional = true }
improv-wifi = { version = "0.1.2", path = "../improv-wifi", features = ["networkmanager"], optional = true }
indicatif = { workspace = true, optional = true }
itertools = { workspace = true, optional = true }
jiff = { version = "0.2.28", features = ["serde"] }
json5 = { version = "1.3.0", optional = true }
leon = { version = "3.0.1", optional = true }
leon-macros = { version = "1.0.2", optional = true }
lloggs = "1.1.0"
merkle_hash = { version = "3.8.0", optional = true }
miette = { workspace = true, features = ["fancy"] }
mimalloc = "0.1.50"
minisign-verify = { version = "0.2.5", optional = true }
node-semver = { version = "2.2.0", optional = true }
notify = { version = "8.2.0", optional = true }
owo-colors = { version = "4.2.3", optional = true }
p256 = { version = "0.13.2", features = ["pkcs8", "pem"], optional = true }
percent-encoding = { version = "2.3.1", optional = true }
privilege = { version = "0.3.0", optional = true }
quick-xml = { version = "0.41.0", features = ["serialize"], optional = true }
regex = { version = "1.11.2", optional = true }
reqwest = { workspace = true }
rpi-st7789v2-driver = { version = "0.3.14", path = "../rpi-st7789v2-driver", features = ["miette"], optional = true }
rppal = { version = "0.22.1", optional = true }
self-replace = { version = "1.5.0", optional = true }
semver = { version = "1.0.28", optional = true }
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.143"
ssh-key = { version = "0.6.6", optional = true }
sysinfo = { workspace = true }
target-tuples = { version = "0.16.1", optional = true }
tempfile = "3.21.0"
tera = { version = "2.0.0", optional = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tokio-postgres = { version = "0.7.17", features = ["with-jiff-0_2", "with-uuid-1"], optional = true }
tokio-util = { workspace = true, optional = true }
toml = { version = "1", optional = true }
tracing = { workspace = true }
uuid = { version = "1.23.2", features = ["v4"] }
walkdir = { version = "2.5.0", optional = true }
zip = { version = "8.6.0", optional = true, default-features = false, features = ["time"] }
zmq = { version = "0.10.0", optional = true }

[target.'cfg(windows)'.dependencies]
tauri-winrt-notification = { version = "0.7.2", optional = true }
windows-acl = { version = "0.3.0", optional = true }
windows-env = { version = "0.2.0", optional = true }
windows-service = { version = "0.8.0", optional = true }

[build-dependencies]
windows_exe_info = { version = "0.5.2", features = ["manifest"] }

[features]
default = ["alertd", "caddy", "canopy", "completions", "crypto", "kopia", "rdp", "self-update", "ssh", "tamanu"]

## Common dep groups (not meant to be used directly)
download = ["dep:binstalk-downloader", "dep:detect-targets", "dep:hickory-resolver"]

## Subcommands
# The daemon always reads the canopy registration (device key + server id), so
# bestool-canopy is core, not Tamanu-gated. `alertd-tamanu` adds reading config
# and the device key from Tamanu's DB, plus the Tamanu-specific checks.
alertd = ["dep:bestool-alertd", "dep:bestool-canopy"]
caddy = ["download", "dep:tera"]
completions = ["dep:clap_complete", "clap_complete/unstable-dynamic"]
crypto = ["dep:algae-cli", "dep:blake3", "dep:merkle_hash"]
file = ["dep:blake3", "dep:indicatif", "dep:tokio-util"]
kopia = ["dep:bestool-kopia", "bestool-kopia/cli", "dep:comfy-table"]
rdp = ["dep:duct", "dep:privilege", "dep:quick-xml", "dep:tauri-winrt-notification", "dep:windows-service"]
self-update = ["download", "dep:minisign-verify", "dep:self-replace", "dep:semver", "dep:windows-env"]
ssh = ["dep:dirs", "dep:duct", "dep:fs4", "dep:ssh-key", "dep:privilege", "dep:windows-acl"]

## Tamanu subcommands
tamanu = [ # enable all tamanu subcommands
	"alertd-tamanu",
	"tamanu-artifacts",
	"tamanu-backup",
	"tamanu-backup-configs",
	"tamanu-config",
	"tamanu-url",
	"tamanu-doctor",
	"tamanu-download",
	"tamanu-find",
	"tamanu-lifecycle",
	"tamanu-logs",
	"tamanu-psql",
	"tamanu-sync",
	"tamanu-tags",
]
# Wire the alertd daemon to read Tamanu's config/DB (database URL + device key
# migration). The conjunction of `alertd` and Tamanu support; enabled by the
# `tamanu` umbrella so default builds get it, while a Tamanu-less build can
# still enable `alertd` alone.
alertd-tamanu = ["alertd", "tamanu-config", "dep:bestool-postgres", "bestool-tamanu/canopy-registration"]
tamanu-artifacts = ["__tamanu", "dep:comfy-table", "dep:detect-targets", "dep:target-tuples"]
tamanu-backup = ["__tamanu", "file", "tamanu-config", "dep:bestool-psql", "dep:algae-cli", "dep:duct"]
tamanu-backup-configs = ["__tamanu", "tamanu-backup", "dep:walkdir", "dep:zip"]
tamanu-config = ["__tamanu"]
tamanu-doctor = [
	"__tamanu",
	"tamanu-config",
	"dep:bestool-alertd",
	"bestool-tamanu/canopy-registration",
	"dep:bestool-canopy",
	"dep:bestool-postgres",
	"dep:bestool-psql",
	"dep:crossterm",
	"dep:owo-colors",
	"dep:p256",
	"dep:tokio-postgres",
]
tamanu-url = ["__tamanu", "tamanu-config", "dep:percent-encoding"]
tamanu-download = ["__tamanu", "download"]
tamanu-find = ["__tamanu"]
tamanu-lifecycle = ["__tamanu", "tamanu-config", "dep:bestool-postgres", "dep:comfy-table", "dep:owo-colors", "dep:privilege"]
tamanu-logs = ["__tamanu", "tamanu-config", "dep:bestool-postgres", "dep:owo-colors"]
tamanu-psql = ["__tamanu", "tamanu-config", "dep:bestool-canopy", "bestool-tamanu/canopy-registration", "dep:bestool-psql"]
tamanu-sync = ["__tamanu", "tamanu-config"]
# Deprecated alias for `canopy-tags`; keeps `bestool tamanu tags` working.
tamanu-tags = ["canopy-tags"]
__tamanu = [ # internal feature to enable the tamanu subcommand common code
	"dep:bestool-tamanu",
	"dep:dirs",
	"dep:itertools",
	"dep:node-semver",
	"dep:regex",
]

## Canopy subcommands
canopy = [ # enable all canopy subcommands
	"canopy-register",
	"canopy-export",
	"canopy-import",
	"canopy-tags",
	"canopy-backup",
	"canopy-restore",
]
canopy-register = ["__canopy", "dep:algae-cli", "dep:base64", "dep:bestool-tamanu", "bestool-tamanu/device-key", "bestool-tamanu/canopy-registration", "dep:p256"]
canopy-export = ["__canopy", "dep:algae-cli", "dep:base64"]
canopy-import = ["__canopy", "dep:algae-cli", "dep:base64"]
canopy-tags = ["__canopy", "tamanu-config", "bestool-tamanu/canopy-registration", "dep:comfy-table", "dep:owo-colors"]
# Config-driven backups: registers capabilities with canopy, runs pre/method/post
# per a backups/*.toml def, drives kopia, reports the outcome. The `postgresql`
# method needs bestool-postgres (CHECKPOINT/verify) but not Tamanu config.
canopy-backup = ["__canopy", "bestool-tamanu/canopy-registration", "dep:bestool-kopia", "bestool-kopia/proxy", "dep:bestool-postgres", "dep:axum", "dep:toml", "dep:notify", "dep:fs4"]
canopy-restore = ["canopy-backup"]
__canopy = ["dep:bestool-canopy"] # internal feature to enable the canopy subcommand common code

## Iti subcommands
iti = [ # enable all iti subcommands
	"iti-battery",
	"iti-improv-wifi",
	"iti-lcd",
	"iti-temperature",
]
iti-battery = ["__iti", "dep:rppal"]
iti-improv-wifi = ["__iti", "dep:improv-wifi", "dep:rppal"]
iti-lcd = ["__iti", "dep:ctrlc", "dep:embedded-graphics", "dep:rpi-st7789v2-driver"]
iti-temperature = ["__iti", "dep:duct"]
__iti = ["dep:zmq"] # internal feature to enable the iti subcommand common code

## Legacy noop features to avoid breaking builds
tamanu-upgrade = []
walg = []
notify = ["dep:notify"]

[dev-dependencies]
age = { version = "0.11.3", features = ["async"] }
jsonschema = { version = "0.46.5", default-features = false }
minisign = "0.9.1"
trycmd = "1.2.0"

[package.metadata.binstall]
pkg-url = "https://tools.ops.tamanu.io/bestool/{ version }/{ target }/{ name }{ binary-ext }.tar.zst"
pkg-fmt = "tzstd"
bin-dir = "{ bin }{ binary-ext }"

[package.metadata.binstall.signing]
algorithm = "minisign"
pubkey = "RWT+oj++Y0app3N4K+PLSYTKhtXimltIHxhoFgyWjxR/ZElCG0lDBDl5"
file = "{ url }.minisig"
