@@ -269,6 +269,134 @@ export const gitlabSearch = async (pat: string, searchString: string) => {
269269 return searchGitlabRepos ( pat , search ) ;
270270} ;
271271
272+ // Bitbucket functions
273+
274+ type BitbucketRepo = {
275+ uuid : string ;
276+ name : string ;
277+ full_name : string ;
278+ description ?: string ;
279+ language ?: string ;
280+ mainbranch ?: {
281+ name : string ;
282+ } ;
283+ links : {
284+ html : {
285+ href : string ;
286+ } ;
287+ } ;
288+ owner : {
289+ username : string ;
290+ } ;
291+ } ;
292+
293+ type BitbucketResponse = {
294+ values : BitbucketRepo [ ] ;
295+ next ?: string ;
296+ } ;
297+
298+ const BITBUCKET_API_URL = 'https://api.bitbucket.org/2.0' ;
299+
300+ export const searchBitbucketRepos = async (
301+ credentials : string ,
302+ searchString : string
303+ ) : Promise < BaseRepo [ ] > => {
304+ let urlString = convertUrlToQuery ( searchString ) ;
305+ if ( urlString !== searchString && urlString . includes ( '/' ) ) {
306+ try {
307+ return await searchBitbucketRepoWithURL ( credentials , urlString ) ;
308+ } catch ( e ) {
309+ return await searchBitbucketReposWithNames ( credentials , urlString ) ;
310+ }
311+ }
312+ return await searchBitbucketReposWithNames ( credentials , urlString ) ;
313+ } ;
314+
315+ const searchBitbucketRepoWithURL = async (
316+ credentials : string ,
317+ searchString : string
318+ ) : Promise < BaseRepo [ ] > => {
319+ const apiUrl = `${ BITBUCKET_API_URL } /repositories/${ searchString } ` ;
320+
321+ const response = await fetch ( apiUrl , {
322+ method : 'GET' ,
323+ headers : {
324+ Authorization : `Basic ${ credentials } ` ,
325+ 'Content-Type' : 'application/json'
326+ }
327+ } ) ;
328+
329+ if ( ! response . ok ) {
330+ throw new Error ( `Bitbucket API error: ${ response . statusText } ` ) ;
331+ }
332+
333+ const repo = ( await response . json ( ) ) as BitbucketRepo ;
334+
335+ return [
336+ {
337+ id : repo . uuid . replace ( / [ { } ] / g, '' ) ,
338+ name : repo . name ,
339+ desc : repo . description ,
340+ slug : repo . name ,
341+ parent : repo . owner . username ,
342+ web_url : repo . links . html . href ,
343+ branch : repo . mainbranch ?. name ,
344+ language : repo . language ,
345+ provider : Integration . BITBUCKET
346+ }
347+ ] as BaseRepo [ ] ;
348+ } ;
349+
350+ const searchBitbucketReposWithNames = async (
351+ credentials : string ,
352+ searchString : string
353+ ) : Promise < BaseRepo [ ] > => {
354+ const apiUrl = `${ BITBUCKET_API_URL } /repositories` ;
355+ const params = new URLSearchParams ( {
356+ q : `name~"${ searchString } "` ,
357+ role : 'member' ,
358+ pagelen : '50'
359+ } ) ;
360+
361+ const response = await fetch ( `${ apiUrl } ?${ params } ` , {
362+ method : 'GET' ,
363+ headers : {
364+ Authorization : `Basic ${ credentials } ` ,
365+ 'Content-Type' : 'application/json'
366+ }
367+ } ) ;
368+
369+ if ( ! response . ok ) {
370+ throw new Error ( `Bitbucket API error: ${ response . statusText } ` ) ;
371+ }
372+
373+ const responseBody = ( await response . json ( ) ) as BitbucketResponse ;
374+ const repositories = responseBody . values || [ ] ;
375+
376+ return repositories . map (
377+ ( repo ) =>
378+ ( {
379+ id : repo . uuid . replace ( / [ { } ] / g, '' ) ,
380+ name : repo . name ,
381+ desc : repo . description ,
382+ slug : repo . name ,
383+ parent : repo . owner . username ,
384+ web_url : repo . links . html . href ,
385+ branch : repo . mainbranch ?. name ,
386+ language : repo . language || null ,
387+ provider : Integration . BITBUCKET
388+ } ) as BaseRepo
389+ ) ;
390+ } ;
391+
392+ export const bitbucketSearch = async (
393+ credentials : string ,
394+ searchString : string
395+ ) : Promise < BaseRepo [ ] > => {
396+ let search = convertUrlToQuery ( searchString ) ;
397+ return searchBitbucketRepos ( credentials , search ) ;
398+ } ;
399+
272400const convertUrlToQuery = ( url : string ) => {
273401 let query = url ;
274402 try {
@@ -280,6 +408,7 @@ const convertUrlToQuery = (url: string) => {
280408 query = query . replace ( 'http://' , '' ) ;
281409 query = query . replace ( 'github.com/' , '' ) ;
282410 query = query . replace ( 'gitlab.com/' , '' ) ;
411+ query = query . replace ( 'bitbucket.org/' , '' ) ;
283412 query = query . startsWith ( 'www.' ) ? query . slice ( 4 ) : query ;
284413 query = query . endsWith ( '/' ) ? query . slice ( 0 , - 1 ) : query ;
285414 }
@@ -303,4 +432,4 @@ const replaceURL = async (url: string): Promise<string> => {
303432 }
304433
305434 return url ;
306- } ;
435+ } ;
0 commit comments