22
33import logging
44from typing import List , Optional , Type
5- from urllib .parse import urlparse
5+ from urllib .parse import urlencode , urlparse
66
77import attr
88from fastapi import APIRouter , FastAPI , HTTPException , Query , Request
99from fastapi .responses import JSONResponse
1010from starlette .responses import Response
11+ from typing_extensions import TypedDict
1112
1213from stac_fastapi .core .models import Catalog
1314from stac_fastapi .types import stac as stac_types
1718logger = logging .getLogger (__name__ )
1819
1920
21+ class Catalogs (TypedDict , total = False ):
22+ """Catalogs endpoint response.
23+
24+ Similar to Collections but for catalogs.
25+ """
26+
27+ catalogs : List [Catalog ]
28+ links : List [dict ]
29+ numberMatched : Optional [int ]
30+ numberReturned : Optional [int ]
31+
32+
2033@attr .s
2134class CatalogsExtension (ApiExtension ):
2235 """Catalogs Extension.
2336
24- The Catalogs extension adds a /catalogs endpoint that returns the root catalog
25- containing child links to all catalogs in the database .
37+ The Catalogs extension adds a /catalogs endpoint that returns a list of all catalogs
38+ in the database, similar to how /collections returns a list of collections .
2639 """
2740
2841 client : BaseCoreClient = attr .ib (default = None )
@@ -44,10 +57,10 @@ def register(self, app: FastAPI, settings=None) -> None:
4457 path = "/catalogs" ,
4558 endpoint = self .catalogs ,
4659 methods = ["GET" ],
47- response_model = Catalog ,
60+ response_model = Catalogs ,
4861 response_class = self .response_class ,
49- summary = "Get Root Catalog " ,
50- description = "Returns the root catalog containing links to all catalogs ." ,
62+ summary = "Get All Catalogs " ,
63+ description = "Returns a list of all catalogs in the database ." ,
5164 tags = ["Catalogs" ],
5265 )
5366
@@ -140,73 +153,57 @@ async def catalogs(
140153 None ,
141154 description = "Pagination token for the next page of results" ,
142155 ),
143- ) -> Catalog :
144- """Get root catalog with links to all catalogs .
156+ ) -> Catalogs :
157+ """Get all catalogs with pagination support .
145158
146159 Args:
147160 request: Request object.
148161 limit: The maximum number of catalogs to return (page size). Defaults to 10.
149162 token: Pagination token for the next page of results.
150163
151164 Returns:
152- Root catalog containing child links to all catalogs in the database .
165+ Catalogs object containing catalogs and pagination links .
153166 """
154167 base_url = str (request .base_url )
155168
156169 # Get all catalogs from database with pagination
157- catalogs , _ , _ = await self .client .database .get_all_catalogs (
170+ catalogs , next_token , _ = await self .client .database .get_all_catalogs (
158171 token = token ,
159172 limit = limit ,
160173 request = request ,
161174 sort = [{"field" : "id" , "direction" : "asc" }],
162175 )
163176
164- # Create child links to each catalog
165- child_links = []
177+ # Convert database catalogs to STAC format
178+ catalog_stac_objects = []
166179 for catalog in catalogs :
167- catalog_id = catalog .get ("id" ) if isinstance (catalog , dict ) else catalog .id
168- catalog_title = (
169- catalog .get ("title" ) or catalog_id
170- if isinstance (catalog , dict )
171- else catalog .title or catalog .id
172- )
173- child_links .append (
174- {
175- "rel" : "child" ,
176- "href" : f"{ base_url } catalogs/{ catalog_id } " ,
177- "type" : "application/json" ,
178- "title" : catalog_title ,
179- }
180- )
181-
182- # Create root catalog
183- root_catalog = {
184- "type" : "Catalog" ,
185- "stac_version" : "1.0.0" ,
186- "id" : "root" ,
187- "title" : "Root Catalog" ,
188- "description" : "Root catalog containing all available catalogs" ,
189- "links" : [
190- {
191- "rel" : "self" ,
192- "href" : f"{ base_url } catalogs" ,
193- "type" : "application/json" ,
194- },
195- {
196- "rel" : "root" ,
197- "href" : f"{ base_url } catalogs" ,
198- "type" : "application/json" ,
199- },
200- {
201- "rel" : "parent" ,
202- "href" : base_url .rstrip ("/" ),
203- "type" : "application/json" ,
204- },
205- ]
206- + child_links ,
207- }
208-
209- return Catalog (** root_catalog )
180+ catalog_stac = self .client .catalog_serializer .db_to_stac (catalog , request )
181+ catalog_stac_objects .append (catalog_stac )
182+
183+ # Create pagination links
184+ links = [
185+ {"rel" : "root" , "type" : "application/json" , "href" : base_url },
186+ {"rel" : "parent" , "type" : "application/json" , "href" : base_url },
187+ {"rel" : "self" , "type" : "application/json" , "href" : str (request .url )},
188+ ]
189+
190+ # Add next link if there are more pages
191+ if next_token :
192+ query_params = {"limit" : limit , "token" : next_token }
193+ next_link = {
194+ "rel" : "next" ,
195+ "href" : f"{ base_url } catalogs?{ urlencode (query_params )} " ,
196+ "type" : "application/json" ,
197+ "title" : "Next page of catalogs" ,
198+ }
199+ links .append (next_link )
200+
201+ # Return Catalogs object with catalogs
202+ return Catalogs (
203+ catalogs = catalog_stac_objects ,
204+ links = links ,
205+ numberReturned = len (catalog_stac_objects ),
206+ )
210207
211208 async def create_catalog (self , catalog : Catalog , request : Request ) -> Catalog :
212209 """Create a new catalog.
0 commit comments