import { VssueAPI } from 'vssue' ; import axios , { AxiosInstance , AxiosRequestConfig } from 'axios' ; import { buildQuery , buildURL , concatURL , getCleanURL , parseQuery , } from '@vssue/utils' ; import { normalizeUser , normalizeIssue , normalizeComment , normalizeReactions , mapReactionName , } from './utils' ; import { ResponseUser , ResponseIssue , ResponseComment , ResponseReaction , ResponseMarkdown , } from './types' ; see https see https export default class GitlabV4 implements VssueAPI . Instance { baseURL : string ; owner : string ; repo : string ; labels : Array < string > ; clientId : string ; state : string ; $http : AxiosInstance ; private _encodedRepo : string ; constructor ( { baseURL = 'https://gitlab.com' , owner , repo , labels , clientId , state , } ) { this . baseURL = baseURL ; this . owner = owner ; this . repo = repo ; this . labels = labels ; this . clientId = clientId ; this . state = state ; this . _encodedRepo = encodeURIComponent ( `${ this . owner }/${ this . repo }` ) ; this . $http = axios . create ( { baseURL : concatURL ( baseURL , 'api/v4' ) , headers : { Accept : 'application/json' , } , } ) ; } /**
     * The platform api info
     */ get platform ( ) : VssueAPI . Platform { return { name : 'GitLab' , link : this . baseURL , version : 'v4' , meta : { reactable : true , sortable : true , } , } ; } see https redirectAuth ( ) { window . location . href = buildURL ( concatURL ( this . baseURL , 'oauth/authorize' ) , { client_id : this . clientId , redirect_uri : window . location . href , response_type : 'token' , state : this . state , } ) ; } see https remarks async handleAuth ( ) { const hash = parseQuery ( window . location . hash . slice ( 1 ) ) ; if ( ! hash . access_token || hash . state !== this . state ) { return null ; } const accessToken = hash . access_token ; delete hash . access_token ; delete hash . token_type ; delete hash . expires_in ; delete hash . state ; const hashString = buildQuery ( hash ) ; const newHash = hashString ? `#${ hashString }` : '' ; const replaceURL = `${ getCleanURL ( window . location . href ) }${ window . location . search }${ newHash }` ; window . history . replaceState ( null , '' , replaceURL ) ; return accessToken ; } /**
     * Get the logged-in user with access token.
     */ async getUser ( { accessToken , } ) { const { data } = await this . $http . get < ResponseUser > ( 'user' , { headers : { Authorization : `Bearer ${ accessToken }` } , } ) ; return normalizeUser ( data ) ; } see https see https see https async getIssue ( { accessToken , issueId , issueTitle , } ) { const options = { } ; if ( accessToken ) { options . headers = { Authorization : `Bearer ${ accessToken }` , } ; } if ( issueId ) { try { const { data } = await this . $http . get < ResponseIssue > ( `projects/${ this . _encodedRepo }/issues/${ issueId }` , options ) ; return normalizeIssue ( data ) ; } catch ( e ) { if ( e . response && e . response . status === 404 ) { return null ; } else { throw e ; } } } else { options . params = { labels : this . labels . join ( ',' ) , order_by : 'created_at' , sort : 'asc' , search : issueTitle , } ; const { data } = await this . $http . get < ResponseIssue [ ] > ( `projects/${ this . _encodedRepo }/issues` , options ) ; const issue = data . map ( normalizeIssue ) . find ( item => item . title === issueTitle ) ; return issue || null ; } } see https async postIssue ( { accessToken , title , content , } ) { const { data } = await this . $http . post < ResponseIssue > ( `projects/${ this . _encodedRepo }/issues` , { title , description : content , labels : this . labels . join ( ',' ) , } , { headers : { Authorization : `Bearer ${ accessToken }` } , } ) ; return normalizeIssue ( data ) ; } see https see https remarks async getComments ( { accessToken , issueId , query : { page = 1 , perPage = 10 , sort = 'desc' } = { } , } ) { const options = { params : { page : page , per_page : perPage , order_by : 'created_at' , sort : sort , } , } ; if ( accessToken ) { options . headers = { Authorization : `Bearer ${ accessToken }` , } ; } const response = await this . $http . get < ResponseComment [ ] > ( `projects/${ this . _encodedRepo }/issues/${ issueId }/notes` , options ) ; const commentsRaw = response . data ; const getCommentsMeta = [ ] ; for ( const comment of commentsRaw ) { getCommentsMeta . push ( ( async ( ) : Promise < void > => { comment . body_html = await this . getMarkdownContent ( { accessToken : accessToken , contentRaw : comment . body , } ) ; } ) ( ) ) ; getCommentsMeta . push ( ( async ( ) : Promise < void > => { comment . reactions = await this . getCommentReactions ( { accessToken : accessToken , issueId : issueId , commentId : comment . id , } ) ; } ) ( ) ) ; } await Promise . all ( getCommentsMeta ) ; return { count : Number ( response . headers [ 'x-total' ] ) , page : Number ( response . headers [ 'x-page' ] ) , perPage : Number ( response . headers [ 'x-per-page' ] ) , data : commentsRaw . map ( normalizeComment ) , } ; } see https async postComment ( { accessToken , issueId , content , } ) { const { data } = await this . $http . post < ResponseComment > ( `projects/${ this . _encodedRepo }/issues/${ issueId }/notes` , { body : content , } , { headers : { Authorization : `Bearer ${ accessToken }` } , } ) ; return normalizeComment ( data ) ; } see https async putComment ( { accessToken , issueId , commentId , content , } ) { const { data } = await this . $http . put < ResponseComment > ( `projects/${ this . _encodedRepo }/issues/${ issueId }/notes/${ commentId }` , { body : content , } , { headers : { Authorization : `Bearer ${ accessToken }` } , } ) ; const [ contentHTML , reactions ] = await Promise . all ( [ this . getMarkdownContent ( { accessToken : accessToken , contentRaw : data . body , } ) , this . getCommentReactions ( { accessToken : accessToken , issueId : issueId , commentId : data . id , } ) , ] ) ; data . body_html = contentHTML ; data . reactions = reactions ; return normalizeComment ( data ) ; } see https async deleteComment ( { accessToken , issueId , commentId , } ) { const { status } = await this . $http . delete ( `projects/${ this . _encodedRepo }/issues/${ issueId }/notes/${ commentId }` , { headers : { Authorization : `Bearer ${ accessToken }` } , } ) ; return status === 204 ; } see https async getCommentReactions ( { accessToken , issueId , commentId , } ) { const { data } = await this . $http . get < ResponseReaction [ ] > ( `projects/${ this . _encodedRepo }/issues/${ issueId }/notes/${ commentId }/award_emoji` , { headers : { Authorization : `Bearer ${ accessToken }` } , } ) ; return normalizeReactions ( data ) ; } see https async postCommentReaction ( { issueId , commentId , reaction , accessToken , } ) { try { const response = await this . $http . post ( `projects/${ this . _encodedRepo }/issues/${ issueId }/notes/${ commentId }/award_emoji` , { name : mapReactionName ( reaction ) , } , { headers : { Authorization : `Bearer ${ accessToken }` , } , } ) ; return response . status === 201 ; } catch ( e ) { if ( e . response && e . response . status === 404 ) { return false ; } else { throw e ; } } } see https async getMarkdownContent ( { accessToken , contentRaw , } ) { const options = { } ; if ( accessToken ) { options . headers = { Authorization : `Bearer ${ accessToken }` , } ; } const { data } = await this . $http . post < ResponseMarkdown > ( `markdown` , { text : contentRaw , gfm : true , } , options ) ; return data . html ; } }