The previous init flow took whatever the user typed for --server and
called GET <url>/api/v1/info on it. If the user typed
"vikunja.example.com" (no scheme), or pasted the URL with /api/v1 in
it (double-suffix), or pointed at a localhost install on the default
:3456 port without typing the port, we'd hand back a raw HTTP error.
New `client.DiscoverServer` ports the frontend's
helpers/checkAndSetApiUrl.ts discovery: probe a small ordered set of
plausible bases for /api/v1/info, return the first one that returns
parseable Info. Candidate order:
1. scheme://host[:port]/path (as the user typed it)
2. scheme://host:3456/path (default API port)
3. opposite scheme of (1)
4. opposite scheme of (2)
Heuristics:
- Missing scheme → https for public hosts, http for localhost /
127.0.0.1 / [::1] (matches most CLIs' behaviour)
- Trailing /api/v1 from a pasted URL is stripped before probing, so
we don't double up to /api/v1/api/v1/info
- Trailing slashes normalized
Errors now list everything we tried + the last underlying network
error, so the user can see why a URL failed instead of just
"GET /info: connection refused":
veans: VALIDATION_ERROR: couldn't find a Vikunja instance reachable
from "vikunja.example.com" — tried:
- https://vikunja.example.com/api/v1/info
- https://vikunja.example.com:3456/api/v1/info
- http://vikunja.example.com/api/v1/info
- http://vikunja.example.com:3456/api/v1/info
last error: dial tcp: lookup vikunja.example.com: no such host
bootstrap.Init now defers URL canonicalisation to DiscoverServer and
caches the matched info from the probe (no second /info round-trip).
Unit tests cover the candidate-builder across the common shapes:
bare hostname, localhost, /api/v1-suffixed paste, explicit port,
subpath install, 127.0.0.1:3456, trailing slash. e2e green.