( query: string, source: Source, minStars: number, )
| 172 | } |
| 173 | |
| 174 | async function githubCodeSearch( |
| 175 | query: string, |
| 176 | source: Source, |
| 177 | minStars: number, |
| 178 | ): Promise<Candidate[]> { |
| 179 | // Code Search doesn't support `stars:>=N` directly, but it does support |
| 180 | // a `repo:owner/name` filter. We can't pre-filter by stars in Code Search, |
| 181 | // so we filter post-hoc via fetchGitHubRepoMeta. Instead, we keep the query |
| 182 | // clean and rely on the meta-filter step to apply --min-stars. |
| 183 | void minStars; |
| 184 | |
| 185 | const out: Candidate[] = []; |
| 186 | const PER_PAGE = 100; |
| 187 | const MAX_PAGES = 10; |
| 188 | |
| 189 | for (let page = 1; page <= MAX_PAGES; page++) { |
| 190 | const data = await githubSearch<{ repository?: { full_name?: string } }>( |
| 191 | "code", |
| 192 | query, |
| 193 | page, |
| 194 | PER_PAGE, |
| 195 | `code "${query}"`, |
| 196 | ); |
| 197 | if (!data) break; |
| 198 | |
| 199 | if (page === 1) { |
| 200 | console.log( |
| 201 | ` query "${query}": total_count=${data.total_count}, fetching up to ${MAX_PAGES * PER_PAGE}`, |
| 202 | ); |
| 203 | } |
| 204 | |
| 205 | for (const item of data.items) { |
| 206 | const fullName = item.repository?.full_name; |
| 207 | if (!fullName) continue; |
| 208 | const [owner, repo] = fullName.split("/"); |
| 209 | if (!owner || !repo) continue; |
| 210 | out.push({ owner, repo, source, matchedQuery: query }); |
| 211 | } |
| 212 | |
| 213 | if (data.items.length < PER_PAGE) break; |
| 214 | } |
| 215 | |
| 216 | return out; |
| 217 | } |
| 218 | |
| 219 | async function githubTopicSearch( |
| 220 | topic: string, |
no outgoing calls
no test coverage detected