fix(tsconnect): avoid nil services slice in netmap JSON

userServicesFromView returned a nil slice when a node advertised no
services, which (combined with the omitempty tag) caused the
services field to be dropped or serialize as null instead of [].
TypeScript declares services as a non-optional array, so JS callers
calling .find()/.some() on it would throw intermittently depending on
which netmap snapshot they observed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit was merged in pull request #9.
This commit is contained in:
2026-06-16 08:08:32 +00:00
parent 3a9f6f463a
commit 78c4511a3d
+2 -2
View File
@@ -1393,7 +1393,7 @@ func (i *jsIPN) setServices(jsServices js.Value) js.Value {
// userServicesFromView converts a hostinfo services slice to jsService entries,
// filtering out internal peerapi protocol entries (already reflected in peerAPIURL).
func userServicesFromView(svcs views.Slice[tailcfg.Service]) []jsService {
var out []jsService
out := make([]jsService, 0, svcs.Len())
for _, s := range svcs.All() {
switch s.Proto {
case tailcfg.PeerAPI4, tailcfg.PeerAPI6, tailcfg.PeerAPIDNS:
@@ -1652,7 +1652,7 @@ type jsNetMapNode struct {
MachineKey string `json:"machineKey"`
NodeKey string `json:"nodeKey"`
PeerAPIURL string `json:"peerAPIURL,omitempty"`
Services []jsService `json:"services,omitempty"`
Services []jsService `json:"services"`
}
type jsNetMapSelfNode struct {