Get or search repositories. If query is provided, searches repositories across the git provider. If query is not provided, returns a paginated list of the authenticated user's repositories.
(
provider: ProviderType,
query: Annotated[
str | None,
Query(
title='Search query for finding repositories. If not provided, returns user repositories.'
),
] = None,
installation_id: Annotated[
str | None,
Query(title='Filter by installation/app ID'),
] = None,
page_id: Annotated[
str | None,
Query(title='Optional next_page_id from the previously returned page'),
] = None,
limit: Annotated[
int,
Query(title='The max number of results in the page', gt=0, le=100),
] = 100,
sort_order: Annotated[
SortOrder | None,
Query(title='Sort order for search results (e.g., stars-desc, forks-asc)'),
] = None,
user_context: UserContext = user_context_dependency,
)
| 101 | |
| 102 | @router.get('/repositories/search') |
| 103 | async def search_repositories( |
| 104 | provider: ProviderType, |
| 105 | query: Annotated[ |
| 106 | str | None, |
| 107 | Query( |
| 108 | title='Search query for finding repositories. If not provided, returns user repositories.' |
| 109 | ), |
| 110 | ] = None, |
| 111 | installation_id: Annotated[ |
| 112 | str | None, |
| 113 | Query(title='Filter by installation/app ID'), |
| 114 | ] = None, |
| 115 | page_id: Annotated[ |
| 116 | str | None, |
| 117 | Query(title='Optional next_page_id from the previously returned page'), |
| 118 | ] = None, |
| 119 | limit: Annotated[ |
| 120 | int, |
| 121 | Query(title='The max number of results in the page', gt=0, le=100), |
| 122 | ] = 100, |
| 123 | sort_order: Annotated[ |
| 124 | SortOrder | None, |
| 125 | Query(title='Sort order for search results (e.g., stars-desc, forks-asc)'), |
| 126 | ] = None, |
| 127 | user_context: UserContext = user_context_dependency, |
| 128 | ) -> RepositoryPage: |
| 129 | """Get or search repositories. |
| 130 | |
| 131 | If query is provided, searches repositories across the git provider. |
| 132 | If query is not provided, returns a paginated list of the authenticated user's repositories. |
| 133 | """ |
| 134 | # Get provider tokens from user context |
| 135 | provider_tokens = await user_context.get_provider_tokens() |
| 136 | if not provider_tokens: |
| 137 | raise HTTPException( |
| 138 | status_code=status.HTTP_403_FORBIDDEN, # 403 not 401 to avoid frontend logout |
| 139 | detail='Git provider token required (such as GitHub).', |
| 140 | ) |
| 141 | |
| 142 | user_id = await user_context.get_user_id() |
| 143 | # Cast to the expected type since we validated provider_tokens exists |
| 144 | typed_provider_tokens: PROVIDER_TOKEN_TYPE = provider_tokens # type: ignore[assignment] |
| 145 | client = ProviderHandler( |
| 146 | provider_tokens=MappingProxyType(typed_provider_tokens), |
| 147 | external_auth_id=user_id, |
| 148 | ) |
| 149 | |
| 150 | page = 1 |
| 151 | decoded_page_id = decode_page_id(page_id) |
| 152 | if decoded_page_id is not None: |
| 153 | page = decoded_page_id |
| 154 | |
| 155 | # If query is provided, use search; otherwise get user's repositories |
| 156 | if query: |
| 157 | # Parse sort_order into sort and order components (if provided) |
| 158 | if sort_order: |
| 159 | search_sort, order = sort_order.value.rsplit('-', 1) |
| 160 | else: |