refactor(plugins): reorganize and sort type definitions for consistency

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2025-12-30 12:16:13 -05:00
parent 25b5acad8a
commit 723b19c8de
7 changed files with 205 additions and 199 deletions

View File

@ -5,9 +5,11 @@ import (
"go/ast" "go/ast"
"go/parser" "go/parser"
"go/token" "go/token"
"maps"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"slices"
"strings" "strings"
) )
@ -180,15 +182,18 @@ func parseCapabilityFile(fset *token.FileSet, path string) ([]Capability, error)
// Recursively collect all struct dependencies // Recursively collect all struct dependencies
collectAllStructDependencies(referencedTypes, structMap) collectAllStructDependencies(referencedTypes, structMap)
// Sort type names for stable output order
sortedTypeNames := slices.Sorted(maps.Keys(referencedTypes))
// Attach referenced structs to the capability // Attach referenced structs to the capability
for typeName := range referencedTypes { for _, typeName := range sortedTypeNames {
if s, exists := structMap[typeName]; exists { if s, exists := structMap[typeName]; exists {
capability.Structs = append(capability.Structs, s) capability.Structs = append(capability.Structs, s)
} }
} }
// Attach referenced type aliases // Attach referenced type aliases
for typeName := range referencedTypes { for _, typeName := range sortedTypeNames {
if a, exists := aliasMap[typeName]; exists { if a, exists := aliasMap[typeName]; exists {
capability.TypeAliases = append(capability.TypeAliases, a) capability.TypeAliases = append(capability.TypeAliases, a)
} }
@ -197,7 +202,8 @@ func parseCapabilityFile(fset *token.FileSet, path string) ([]Capability, error)
// Also attach type aliases prefixed with interface name (e.g., ScrobblerError for Scrobbler interface) // Also attach type aliases prefixed with interface name (e.g., ScrobblerError for Scrobbler interface)
// This supports error types that are not directly referenced in method signatures // This supports error types that are not directly referenced in method signatures
interfaceName := typeSpec.Name.Name interfaceName := typeSpec.Name.Name
for typeName, a := range aliasMap { for _, typeName := range slices.Sorted(maps.Keys(aliasMap)) {
a := aliasMap[typeName]
if strings.HasPrefix(typeName, interfaceName) && !referencedTypes[typeName] { if strings.HasPrefix(typeName, interfaceName) && !referencedTypes[typeName] {
capability.TypeAliases = append(capability.TypeAliases, a) capability.TypeAliases = append(capability.TypeAliases, a)
referencedTypes[typeName] = true // Mark as referenced for const lookup referencedTypes[typeName] = true // Mark as referenced for const lookup
@ -368,8 +374,8 @@ func parseFile(fset *token.FileSet, path string) ([]Service, error) {
} }
} }
// Attach referenced structs to the service // Attach referenced structs to the service (sorted for stable output)
for typeName := range referencedTypes { for _, typeName := range slices.Sorted(maps.Keys(referencedTypes)) {
if s, exists := structMap[typeName]; exists { if s, exists := structMap[typeName]; exists {
service.Structs = append(service.Structs, s) service.Structs = append(service.Structs, s)
} }

View File

@ -11,35 +11,9 @@ import (
pdk "github.com/extism/go-pdk" pdk "github.com/extism/go-pdk"
) )
// ArtistBiographyResponse is the response for GetArtistBiography. // AlbumImagesResponse is the response for GetAlbumImages.
type ArtistBiographyResponse struct { type AlbumImagesResponse struct {
// Biography is the artist biography text. // Images is the list of album images.
Biography string `json:"biography"`
}
// SimilarArtistsResponse is the response for GetSimilarArtists.
type SimilarArtistsResponse struct {
// Artists is the list of similar artists.
Artists []ArtistRef `json:"artists"`
}
// TopSongsResponse is the response for GetArtistTopSongs.
type TopSongsResponse struct {
// Songs is the list of top songs.
Songs []SongRef `json:"songs"`
}
// ArtistRef is a reference to an artist with name and optional MBID.
type ArtistRef struct {
// Name is the artist name.
Name string `json:"name"`
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid,omitempty"`
}
// ArtistImagesResponse is the response for GetArtistImages.
type ArtistImagesResponse struct {
// Images is the list of artist images.
Images []ImageInfo `json:"images"` Images []ImageInfo `json:"images"`
} }
@ -55,34 +29,28 @@ type AlbumInfoResponse struct {
URL string `json:"url"` URL string `json:"url"`
} }
// ImageInfo represents an image with URL and size. // AlbumRequest is the common request for album-related functions.
type ImageInfo struct { type AlbumRequest struct {
// URL is the URL of the image. // Name is the album name.
URL string `json:"url"`
// Size is the size of the image in pixels (width or height).
Size int32 `json:"size"`
}
// ArtistMBIDResponse is the response for GetArtistMBID.
type ArtistMBIDResponse struct {
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid"`
}
// ArtistURLResponse is the response for GetArtistURL.
type ArtistURLResponse struct {
// URL is the external URL for the artist.
URL string `json:"url"`
}
// SongRef is a reference to a song with name and optional MBID.
type SongRef struct {
// Name is the song name.
Name string `json:"name"` Name string `json:"name"`
// MBID is the MusicBrainz ID for the song. // Artist is the album artist name.
Artist string `json:"artist"`
// MBID is the MusicBrainz ID for the album (if known).
MBID string `json:"mbid,omitempty"` MBID string `json:"mbid,omitempty"`
} }
// ArtistBiographyResponse is the response for GetArtistBiography.
type ArtistBiographyResponse struct {
// Biography is the artist biography text.
Biography string `json:"biography"`
}
// ArtistImagesResponse is the response for GetArtistImages.
type ArtistImagesResponse struct {
// Images is the list of artist images.
Images []ImageInfo `json:"images"`
}
// ArtistMBIDRequest is the request for GetArtistMBID. // ArtistMBIDRequest is the request for GetArtistMBID.
type ArtistMBIDRequest struct { type ArtistMBIDRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -91,6 +59,20 @@ type ArtistMBIDRequest struct {
Name string `json:"name"` Name string `json:"name"`
} }
// ArtistMBIDResponse is the response for GetArtistMBID.
type ArtistMBIDResponse struct {
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid"`
}
// ArtistRef is a reference to an artist with name and optional MBID.
type ArtistRef struct {
// Name is the artist name.
Name string `json:"name"`
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid,omitempty"`
}
// ArtistRequest is the common request for artist-related functions. // ArtistRequest is the common request for artist-related functions.
type ArtistRequest struct { type ArtistRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -101,6 +83,20 @@ type ArtistRequest struct {
MBID string `json:"mbid,omitempty"` MBID string `json:"mbid,omitempty"`
} }
// ArtistURLResponse is the response for GetArtistURL.
type ArtistURLResponse struct {
// URL is the external URL for the artist.
URL string `json:"url"`
}
// ImageInfo represents an image with URL and size.
type ImageInfo struct {
// URL is the URL of the image.
URL string `json:"url"`
// Size is the size of the image in pixels (width or height).
Size int32 `json:"size"`
}
// SimilarArtistsRequest is the request for GetSimilarArtists. // SimilarArtistsRequest is the request for GetSimilarArtists.
type SimilarArtistsRequest struct { type SimilarArtistsRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -113,6 +109,20 @@ type SimilarArtistsRequest struct {
Limit int32 `json:"limit"` Limit int32 `json:"limit"`
} }
// SimilarArtistsResponse is the response for GetSimilarArtists.
type SimilarArtistsResponse struct {
// Artists is the list of similar artists.
Artists []ArtistRef `json:"artists"`
}
// SongRef is a reference to a song with name and optional MBID.
type SongRef struct {
// Name is the song name.
Name string `json:"name"`
// MBID is the MusicBrainz ID for the song.
MBID string `json:"mbid,omitempty"`
}
// TopSongsRequest is the request for GetArtistTopSongs. // TopSongsRequest is the request for GetArtistTopSongs.
type TopSongsRequest struct { type TopSongsRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -125,20 +135,10 @@ type TopSongsRequest struct {
Count int32 `json:"count"` Count int32 `json:"count"`
} }
// AlbumRequest is the common request for album-related functions. // TopSongsResponse is the response for GetArtistTopSongs.
type AlbumRequest struct { type TopSongsResponse struct {
// Name is the album name. // Songs is the list of top songs.
Name string `json:"name"` Songs []SongRef `json:"songs"`
// Artist is the album artist name.
Artist string `json:"artist"`
// MBID is the MusicBrainz ID for the album (if known).
MBID string `json:"mbid,omitempty"`
}
// AlbumImagesResponse is the response for GetAlbumImages.
type AlbumImagesResponse struct {
// Images is the list of album images.
Images []ImageInfo `json:"images"`
} }
// Metadata is the marker interface for metadata plugins. // Metadata is the marker interface for metadata plugins.

View File

@ -8,35 +8,9 @@
package metadata package metadata
// ArtistBiographyResponse is the response for GetArtistBiography. // AlbumImagesResponse is the response for GetAlbumImages.
type ArtistBiographyResponse struct { type AlbumImagesResponse struct {
// Biography is the artist biography text. // Images is the list of album images.
Biography string `json:"biography"`
}
// SimilarArtistsResponse is the response for GetSimilarArtists.
type SimilarArtistsResponse struct {
// Artists is the list of similar artists.
Artists []ArtistRef `json:"artists"`
}
// TopSongsResponse is the response for GetArtistTopSongs.
type TopSongsResponse struct {
// Songs is the list of top songs.
Songs []SongRef `json:"songs"`
}
// ArtistRef is a reference to an artist with name and optional MBID.
type ArtistRef struct {
// Name is the artist name.
Name string `json:"name"`
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid,omitempty"`
}
// ArtistImagesResponse is the response for GetArtistImages.
type ArtistImagesResponse struct {
// Images is the list of artist images.
Images []ImageInfo `json:"images"` Images []ImageInfo `json:"images"`
} }
@ -52,34 +26,28 @@ type AlbumInfoResponse struct {
URL string `json:"url"` URL string `json:"url"`
} }
// ImageInfo represents an image with URL and size. // AlbumRequest is the common request for album-related functions.
type ImageInfo struct { type AlbumRequest struct {
// URL is the URL of the image. // Name is the album name.
URL string `json:"url"`
// Size is the size of the image in pixels (width or height).
Size int32 `json:"size"`
}
// ArtistMBIDResponse is the response for GetArtistMBID.
type ArtistMBIDResponse struct {
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid"`
}
// ArtistURLResponse is the response for GetArtistURL.
type ArtistURLResponse struct {
// URL is the external URL for the artist.
URL string `json:"url"`
}
// SongRef is a reference to a song with name and optional MBID.
type SongRef struct {
// Name is the song name.
Name string `json:"name"` Name string `json:"name"`
// MBID is the MusicBrainz ID for the song. // Artist is the album artist name.
Artist string `json:"artist"`
// MBID is the MusicBrainz ID for the album (if known).
MBID string `json:"mbid,omitempty"` MBID string `json:"mbid,omitempty"`
} }
// ArtistBiographyResponse is the response for GetArtistBiography.
type ArtistBiographyResponse struct {
// Biography is the artist biography text.
Biography string `json:"biography"`
}
// ArtistImagesResponse is the response for GetArtistImages.
type ArtistImagesResponse struct {
// Images is the list of artist images.
Images []ImageInfo `json:"images"`
}
// ArtistMBIDRequest is the request for GetArtistMBID. // ArtistMBIDRequest is the request for GetArtistMBID.
type ArtistMBIDRequest struct { type ArtistMBIDRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -88,6 +56,20 @@ type ArtistMBIDRequest struct {
Name string `json:"name"` Name string `json:"name"`
} }
// ArtistMBIDResponse is the response for GetArtistMBID.
type ArtistMBIDResponse struct {
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid"`
}
// ArtistRef is a reference to an artist with name and optional MBID.
type ArtistRef struct {
// Name is the artist name.
Name string `json:"name"`
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid,omitempty"`
}
// ArtistRequest is the common request for artist-related functions. // ArtistRequest is the common request for artist-related functions.
type ArtistRequest struct { type ArtistRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -98,6 +80,20 @@ type ArtistRequest struct {
MBID string `json:"mbid,omitempty"` MBID string `json:"mbid,omitempty"`
} }
// ArtistURLResponse is the response for GetArtistURL.
type ArtistURLResponse struct {
// URL is the external URL for the artist.
URL string `json:"url"`
}
// ImageInfo represents an image with URL and size.
type ImageInfo struct {
// URL is the URL of the image.
URL string `json:"url"`
// Size is the size of the image in pixels (width or height).
Size int32 `json:"size"`
}
// SimilarArtistsRequest is the request for GetSimilarArtists. // SimilarArtistsRequest is the request for GetSimilarArtists.
type SimilarArtistsRequest struct { type SimilarArtistsRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -110,6 +106,20 @@ type SimilarArtistsRequest struct {
Limit int32 `json:"limit"` Limit int32 `json:"limit"`
} }
// SimilarArtistsResponse is the response for GetSimilarArtists.
type SimilarArtistsResponse struct {
// Artists is the list of similar artists.
Artists []ArtistRef `json:"artists"`
}
// SongRef is a reference to a song with name and optional MBID.
type SongRef struct {
// Name is the song name.
Name string `json:"name"`
// MBID is the MusicBrainz ID for the song.
MBID string `json:"mbid,omitempty"`
}
// TopSongsRequest is the request for GetArtistTopSongs. // TopSongsRequest is the request for GetArtistTopSongs.
type TopSongsRequest struct { type TopSongsRequest struct {
// ID is the internal Navidrome artist ID. // ID is the internal Navidrome artist ID.
@ -122,20 +132,10 @@ type TopSongsRequest struct {
Count int32 `json:"count"` Count int32 `json:"count"`
} }
// AlbumRequest is the common request for album-related functions. // TopSongsResponse is the response for GetArtistTopSongs.
type AlbumRequest struct { type TopSongsResponse struct {
// Name is the album name. // Songs is the list of top songs.
Name string `json:"name"` Songs []SongRef `json:"songs"`
// Artist is the album artist name.
Artist string `json:"artist"`
// MBID is the MusicBrainz ID for the album (if known).
MBID string `json:"mbid,omitempty"`
}
// AlbumImagesResponse is the response for GetAlbumImages.
type AlbumImagesResponse struct {
// Images is the list of album images.
Images []ImageInfo `json:"images"`
} }
// Metadata is the marker interface for metadata plugins. // Metadata is the marker interface for metadata plugins.

View File

@ -26,6 +26,20 @@ const (
// Error implements the error interface for ScrobblerError. // Error implements the error interface for ScrobblerError.
func (e ScrobblerError) Error() string { return string(e) } func (e ScrobblerError) Error() string { return string(e) }
// IsAuthorizedRequest is the request for authorization check.
type IsAuthorizedRequest struct {
// UserID is the internal Navidrome user ID.
UserID string `json:"userId"`
// Username is the username of the user.
Username string `json:"username"`
}
// IsAuthorizedResponse is the response for authorization check.
type IsAuthorizedResponse struct {
// Authorized indicates whether the user is authorized to scrobble.
Authorized bool `json:"authorized"`
}
// NowPlayingRequest is the request for now playing notification. // NowPlayingRequest is the request for now playing notification.
type NowPlayingRequest struct { type NowPlayingRequest struct {
// UserID is the internal Navidrome user ID. // UserID is the internal Navidrome user ID.
@ -82,20 +96,6 @@ type TrackInfo struct {
MBZReleaseTrackID string `json:"mbzReleaseTrackId,omitempty"` MBZReleaseTrackID string `json:"mbzReleaseTrackId,omitempty"`
} }
// IsAuthorizedRequest is the request for authorization check.
type IsAuthorizedRequest struct {
// UserID is the internal Navidrome user ID.
UserID string `json:"userId"`
// Username is the username of the user.
Username string `json:"username"`
}
// IsAuthorizedResponse is the response for authorization check.
type IsAuthorizedResponse struct {
// Authorized indicates whether the user is authorized to scrobble.
Authorized bool `json:"authorized"`
}
// Scrobbler requires all methods to be implemented. // Scrobbler requires all methods to be implemented.
// Scrobbler provides scrobbling functionality to external services. // Scrobbler provides scrobbling functionality to external services.
// This capability allows plugins to submit listening history to services like Last.fm, // This capability allows plugins to submit listening history to services like Last.fm,

View File

@ -23,6 +23,20 @@ const (
// Error implements the error interface for ScrobblerError. // Error implements the error interface for ScrobblerError.
func (e ScrobblerError) Error() string { return string(e) } func (e ScrobblerError) Error() string { return string(e) }
// IsAuthorizedRequest is the request for authorization check.
type IsAuthorizedRequest struct {
// UserID is the internal Navidrome user ID.
UserID string `json:"userId"`
// Username is the username of the user.
Username string `json:"username"`
}
// IsAuthorizedResponse is the response for authorization check.
type IsAuthorizedResponse struct {
// Authorized indicates whether the user is authorized to scrobble.
Authorized bool `json:"authorized"`
}
// NowPlayingRequest is the request for now playing notification. // NowPlayingRequest is the request for now playing notification.
type NowPlayingRequest struct { type NowPlayingRequest struct {
// UserID is the internal Navidrome user ID. // UserID is the internal Navidrome user ID.
@ -79,20 +93,6 @@ type TrackInfo struct {
MBZReleaseTrackID string `json:"mbzReleaseTrackId,omitempty"` MBZReleaseTrackID string `json:"mbzReleaseTrackId,omitempty"`
} }
// IsAuthorizedRequest is the request for authorization check.
type IsAuthorizedRequest struct {
// UserID is the internal Navidrome user ID.
UserID string `json:"userId"`
// Username is the username of the user.
Username string `json:"username"`
}
// IsAuthorizedResponse is the response for authorization check.
type IsAuthorizedResponse struct {
// Authorized indicates whether the user is authorized to scrobble.
Authorized bool `json:"authorized"`
}
// Scrobbler requires all methods to be implemented. // Scrobbler requires all methods to be implemented.
// Scrobbler provides scrobbling functionality to external services. // Scrobbler provides scrobbling functionality to external services.
// This capability allows plugins to submit listening history to services like Last.fm, // This capability allows plugins to submit listening history to services like Last.fm,

View File

@ -11,14 +11,6 @@ import (
pdk "github.com/extism/go-pdk" pdk "github.com/extism/go-pdk"
) )
// OnTextMessageRequest is the request provided when a text message is received.
type OnTextMessageRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that received the message.
ConnectionID string `json:"connectionId"`
// Message is the text message content received from the WebSocket.
Message string `json:"message"`
}
// OnBinaryMessageRequest is the request provided when a binary message is received. // OnBinaryMessageRequest is the request provided when a binary message is received.
type OnBinaryMessageRequest struct { type OnBinaryMessageRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that received the message. // ConnectionID is the unique identifier for the WebSocket connection that received the message.
@ -27,14 +19,6 @@ type OnBinaryMessageRequest struct {
Data string `json:"data"` Data string `json:"data"`
} }
// OnErrorRequest is the request provided when an error occurs on a WebSocket connection.
type OnErrorRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection where the error occurred.
ConnectionID string `json:"connectionId"`
// Error is the error message describing what went wrong.
Error string `json:"error"`
}
// OnCloseRequest is the request provided when a WebSocket connection is closed. // OnCloseRequest is the request provided when a WebSocket connection is closed.
type OnCloseRequest struct { type OnCloseRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that was closed. // ConnectionID is the unique identifier for the WebSocket connection that was closed.
@ -46,6 +30,22 @@ type OnCloseRequest struct {
Reason string `json:"reason"` Reason string `json:"reason"`
} }
// OnErrorRequest is the request provided when an error occurs on a WebSocket connection.
type OnErrorRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection where the error occurred.
ConnectionID string `json:"connectionId"`
// Error is the error message describing what went wrong.
Error string `json:"error"`
}
// OnTextMessageRequest is the request provided when a text message is received.
type OnTextMessageRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that received the message.
ConnectionID string `json:"connectionId"`
// Message is the text message content received from the WebSocket.
Message string `json:"message"`
}
// WebSocket is the marker interface for websocket plugins. // WebSocket is the marker interface for websocket plugins.
// Implement one or more of the provider interfaces below. // Implement one or more of the provider interfaces below.
// WebSocketCallback provides WebSocket message handling. // WebSocketCallback provides WebSocket message handling.

View File

@ -8,14 +8,6 @@
package websocket package websocket
// OnTextMessageRequest is the request provided when a text message is received.
type OnTextMessageRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that received the message.
ConnectionID string `json:"connectionId"`
// Message is the text message content received from the WebSocket.
Message string `json:"message"`
}
// OnBinaryMessageRequest is the request provided when a binary message is received. // OnBinaryMessageRequest is the request provided when a binary message is received.
type OnBinaryMessageRequest struct { type OnBinaryMessageRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that received the message. // ConnectionID is the unique identifier for the WebSocket connection that received the message.
@ -24,14 +16,6 @@ type OnBinaryMessageRequest struct {
Data string `json:"data"` Data string `json:"data"`
} }
// OnErrorRequest is the request provided when an error occurs on a WebSocket connection.
type OnErrorRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection where the error occurred.
ConnectionID string `json:"connectionId"`
// Error is the error message describing what went wrong.
Error string `json:"error"`
}
// OnCloseRequest is the request provided when a WebSocket connection is closed. // OnCloseRequest is the request provided when a WebSocket connection is closed.
type OnCloseRequest struct { type OnCloseRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that was closed. // ConnectionID is the unique identifier for the WebSocket connection that was closed.
@ -43,6 +27,22 @@ type OnCloseRequest struct {
Reason string `json:"reason"` Reason string `json:"reason"`
} }
// OnErrorRequest is the request provided when an error occurs on a WebSocket connection.
type OnErrorRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection where the error occurred.
ConnectionID string `json:"connectionId"`
// Error is the error message describing what went wrong.
Error string `json:"error"`
}
// OnTextMessageRequest is the request provided when a text message is received.
type OnTextMessageRequest struct {
// ConnectionID is the unique identifier for the WebSocket connection that received the message.
ConnectionID string `json:"connectionId"`
// Message is the text message content received from the WebSocket.
Message string `json:"message"`
}
// WebSocket is the marker interface for websocket plugins. // WebSocket is the marker interface for websocket plugins.
// Implement one or more of the provider interfaces below. // Implement one or more of the provider interfaces below.
// WebSocketCallback provides WebSocket message handling. // WebSocketCallback provides WebSocket message handling.