2021-02-08 12:58:32 +08:00
import { getUserAgent } from "universal-user-agent" ;
import { Collection } from "before-after-hook" ;
import { request } from "@octokit/request" ;
import { withCustomRequest } from "@octokit/graphql" ;
import { createTokenAuth } from "@octokit/auth-token" ;
import { VERSION } from "./version" ;
export class Octokit {
constructor ( options = { } ) {
const hook = new Collection ( ) ;
const requestDefaults = {
baseUrl : request . endpoint . DEFAULTS . baseUrl ,
headers : { } ,
request : Object . assign ( { } , options . request , {
2021-06-04 22:19:14 +08:00
// @ts-ignore internal usage only, no need to type
2021-02-08 12:58:32 +08:00
hook : hook . bind ( null , "request" ) ,
} ) ,
mediaType : {
previews : [ ] ,
format : "" ,
} ,
} ;
// prepend default user agent with `options.userAgent` if set
requestDefaults . headers [ "user-agent" ] = [
options . userAgent ,
` octokit-core.js/ ${ VERSION } ${ getUserAgent ( ) } ` ,
]
. filter ( Boolean )
. join ( " " ) ;
if ( options . baseUrl ) {
requestDefaults . baseUrl = options . baseUrl ;
}
if ( options . previews ) {
requestDefaults . mediaType . previews = options . previews ;
}
if ( options . timeZone ) {
requestDefaults . headers [ "time-zone" ] = options . timeZone ;
}
this . request = request . defaults ( requestDefaults ) ;
2021-06-04 22:19:14 +08:00
this . graphql = withCustomRequest ( this . request ) . defaults ( requestDefaults ) ;
2021-02-08 12:58:32 +08:00
this . log = Object . assign ( {
debug : ( ) => { } ,
info : ( ) => { } ,
warn : console . warn . bind ( console ) ,
error : console . error . bind ( console ) ,
} , options . log ) ;
this . hook = hook ;
// (1) If neither `options.authStrategy` nor `options.auth` are set, the `octokit` instance
2021-06-04 22:19:14 +08:00
// is unauthenticated. The `this.auth()` method is a no-op and no request hook is registered.
2021-02-08 12:58:32 +08:00
// (2) If only `options.auth` is set, use the default token authentication strategy.
// (3) If `options.authStrategy` is set then use it and pass in `options.auth`. Always pass own request as many strategies accept a custom request instance.
// TODO: type `options.auth` based on `options.authStrategy`.
if ( ! options . authStrategy ) {
if ( ! options . auth ) {
// (1)
this . auth = async ( ) => ( {
type : "unauthenticated" ,
} ) ;
}
else {
// (2)
const auth = createTokenAuth ( options . auth ) ;
// @ts-ignore ¯\_(ツ)_/¯
hook . wrap ( "request" , auth . hook ) ;
this . auth = auth ;
}
}
else {
2021-06-04 22:19:14 +08:00
const { authStrategy , ... otherOptions } = options ;
const auth = authStrategy ( Object . assign ( {
2021-02-08 12:58:32 +08:00
request : this . request ,
2021-06-04 22:19:14 +08:00
log : this . log ,
// we pass the current octokit instance as well as its constructor options
// to allow for authentication strategies that return a new octokit instance
// that shares the same internal state as the current one. The original
// requirement for this was the "event-octokit" authentication strategy
// of https://github.com/probot/octokit-auth-probot.
octokit : this ,
octokitOptions : otherOptions ,
2021-02-08 12:58:32 +08:00
} , options . auth ) ) ;
// @ts-ignore ¯\_(ツ)_/¯
hook . wrap ( "request" , auth . hook ) ;
this . auth = auth ;
}
// apply plugins
// https://stackoverflow.com/a/16345172
const classConstructor = this . constructor ;
classConstructor . plugins . forEach ( ( plugin ) => {
Object . assign ( this , plugin ( this , options ) ) ;
} ) ;
}
static defaults ( defaults ) {
const OctokitWithDefaults = class extends this {
constructor ( ... args ) {
const options = args [ 0 ] || { } ;
if ( typeof defaults === "function" ) {
super ( defaults ( options ) ) ;
return ;
}
super ( Object . assign ( { } , defaults , options , options . userAgent && defaults . userAgent
? {
userAgent : ` ${ options . userAgent } ${ defaults . userAgent } ` ,
}
: null ) ) ;
}
} ;
return OctokitWithDefaults ;
}
/ * *
* Attach a plugin ( or many ) to your Octokit instance .
*
* @ example
* const API = Octokit . plugin ( plugin1 , plugin2 , plugin3 , ... )
* /
static plugin ( ... newPlugins ) {
var _a ;
const currentPlugins = this . plugins ;
const NewOctokit = ( _a = class extends this {
} ,
_a . plugins = currentPlugins . concat ( newPlugins . filter ( ( plugin ) => ! currentPlugins . includes ( plugin ) ) ) ,
_a ) ;
return NewOctokit ;
}
}
Octokit . VERSION = VERSION ;
Octokit . plugins = [ ] ;