Search Source

A SearchSource is the plugin component that provides the search algorithm for the local library. Only one search source is active at a time; the user selects it from Settings → System → Search.

Registration

ctx.registerSearchSource({
	id: "my-search",
	enable(apiCtx) {},
	getName() {
		return "My Search";
	},
	getCapabilities(entities) {
		return { sortMethods: [], filterableAttributes: [] };
	},
	async search(query) {
		return { tracks: [], artists: [], albums: [] };
	},
});

Interface

enable(apiCtx)

Called once on registration. The SearchSourceApiContext is currently empty - use it for any future setup.

getName()

Display name shown in the search source selector.

getCapabilities(entities)

Called with a map of which entity types the current request involves. Returns a SearchSourceCapabilities object describing what the source supports:

getCapabilities(entities) {
    return {
        sortMethods: [
            { key: "title", ascending: true, descending: true },
            { key: "duration", ascending: true, descending: false },
        ],
        filterableAttributes: [
            {
                entityType: "track",
                attributeKey: "title",
                attributeType: "string",
                supportsFuzzy: true,
            },
            {
                entityType: "track",
                attributeKey: "duration",
                attributeType: "integer",
            },
        ],
    };
}

The frontend uses this to populate the sort and filter UI in the search page. Only advertise capabilities your search implementation actually honours.

search(query)

The core search method. Receives a SearchQuery and returns ordered lists of UUIDs:

async search(query) {
    const trackUuids = await myIndex.search(query.query, {
        limit: query.entities.tracks?.limit ?? 0,
        filters: query.filters,
        sort: query.sort,
    });

    return {
        tracks: trackUuids,
        trackTotal: myIndex.count(),
    };
}

SearchQuery fields:

Field Type Description
query string | undefined The search string (may be absent for filter-only queries)
entities.tracks { limit, page? } How many track UUIDs to return
entities.artists { limit, page? } How many artist UUIDs to return
entities.albums { limit, page? } How many album UUIDs to return
sort { key, direction } Optional sort - key matches one declared in getCapabilities
filters SearchFilter[] Attribute filters to apply

Return: SearchSourceResults - tracks, artists, albums arrays of UUID strings, plus optional trackTotal, artistTotal, albumTotal counts.

Filter types

The filters array contains typed filter objects. Each has entityType, attributeKey, and attributeType. The value fields depend on the type:

attributeType Value fields
string value?, partial?, fuzzy?, exists?, inverse?
integer / decimal value?, min?, max?, exists?, inverse?
boolean value?, exists?, inverse?
buffer exists?, inverse?

You are responsible for applying these filters within your search implementation. The server does not pre-filter before calling search.

Keeping the index up to date

The server does not automatically notify a search source when tracks are added or removed. A typical pattern is to implement a plugin development/Plugin-Development that rebuilds the index from the data client and register it so users can trigger it from Settings → Tasks (or via a users/Workflows).