Detailed changes
@@ -7,32 +7,12 @@ matrix:
- language: go
go: 1.13.x
- language: node_js
- node_js: 8
+ node_js: node
before_install:
- cd webui
after_success: []
- language: node_js
- node_js: 9
- before_install:
- - cd webui
- after_success: []
- - language: node_js
- node_js: 10
- before_install:
- - cd webui
- after_success: []
- - language: node_js
- node_js: 11
- before_install:
- - cd webui
- after_success: []
- - language: node_js
- node_js: 12
- before_install:
- - cd webui
- after_success: []
- - language: node_js
- node_js: 13
+ node_js: lts/*
before_install:
- cd webui
after_success: []
@@ -44,13 +44,13 @@ That's all !
</details>
-<details><summary>go get (unstable)</summary>
+<details><summary>go install (unstable)</summary>
```shell
-go get -u github.com/MichaelMure/git-bug
+go install github.com/MichaelMure/git-bug
```
-If it's not done already, add golang binary directory in your PATH:
+If it's not done already, add the golang binary directory in your PATH:
```bash
export PATH=$PATH:$(go env GOROOT)/bin:$(go env GOPATH)/bin
@@ -1,6 +1,8 @@
package auth
import (
+ "crypto/rand"
+ "encoding/base64"
"errors"
"fmt"
"regexp"
@@ -16,15 +18,18 @@ const (
configKeyKind = "kind"
configKeyTarget = "target"
configKeyCreateTime = "createtime"
+ configKeySalt = "salt"
configKeyPrefixMeta = "meta."
- MetaKeyLogin = "login"
+ MetaKeyLogin = "login"
+ MetaKeyBaseURL = "base-url"
)
type CredentialKind string
const (
KindToken CredentialKind = "token"
+ KindLogin CredentialKind = "login"
KindLoginPassword CredentialKind = "login-password"
)
@@ -36,9 +41,10 @@ func NewErrMultipleMatchCredential(matching []entity.Id) *entity.ErrMultipleMatc
type Credential interface {
ID() entity.Id
- Target() string
Kind() CredentialKind
+ Target() string
CreateTime() time.Time
+ Salt() []byte
Validate() error
Metadata() map[string]string
@@ -46,7 +52,7 @@ type Credential interface {
SetMetadata(key string, value string)
// Return all the specific properties of the credential that need to be saved into the configuration.
- // This does not include Target, Kind, CreateTime and Metadata.
+ // This does not include Target, Kind, CreateTime, Metadata or Salt.
toConfig() map[string]string
}
@@ -107,15 +113,23 @@ func loadFromConfig(rawConfigs map[string]string, id entity.Id) (Credential, err
}
var cred Credential
+ var err error
switch CredentialKind(configs[configKeyKind]) {
case KindToken:
- cred = NewTokenFromConfig(configs)
+ cred, err = NewTokenFromConfig(configs)
+ case KindLogin:
+ cred, err = NewLoginFromConfig(configs)
case KindLoginPassword:
+ cred, err = NewLoginPasswordFromConfig(configs)
default:
return nil, fmt.Errorf("unknown credential type %s", configs[configKeyKind])
}
+ if err != nil {
+ return nil, fmt.Errorf("loading credential: %v", err)
+ }
+
return cred, nil
}
@@ -133,6 +147,23 @@ func metaFromConfig(configs map[string]string) map[string]string {
return result
}
+func makeSalt() []byte {
+ result := make([]byte, 16)
+ _, err := rand.Read(result)
+ if err != nil {
+ panic(err)
+ }
+ return result
+}
+
+func saltFromConfig(configs map[string]string) ([]byte, error) {
+ val, ok := configs[configKeySalt]
+ if !ok {
+ return nil, fmt.Errorf("no credential salt found")
+ }
+ return base64.StdEncoding.DecodeString(val)
+}
+
// List load all existing credentials
func List(repo repository.RepoConfig, opts ...Option) ([]Credential, error) {
rawConfigs, err := repo.GlobalConfig().ReadAll(configKeyPrefix + ".")
@@ -210,6 +241,16 @@ func Store(repo repository.RepoConfig, cred Credential) error {
return err
}
+ // Salt
+ if len(cred.Salt()) != 16 {
+ panic("credentials need to be salted")
+ }
+ encoded := base64.StdEncoding.EncodeToString(cred.Salt())
+ err = repo.GlobalConfig().StoreString(prefix+configKeySalt, encoded)
+ if err != nil {
+ return err
+ }
+
// Metadata
for key, val := range cred.Metadata() {
err := repo.GlobalConfig().StoreString(prefix+configKeyPrefixMeta+key, val)
@@ -0,0 +1,90 @@
+package auth
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/MichaelMure/git-bug/bridge/core"
+ "github.com/MichaelMure/git-bug/repository"
+)
+
+type credentialBase struct {
+ target string
+ createTime time.Time
+ salt []byte
+ meta map[string]string
+}
+
+func newCredentialBase(target string) *credentialBase {
+ return &credentialBase{
+ target: target,
+ createTime: time.Now(),
+ salt: makeSalt(),
+ }
+}
+
+func newCredentialBaseFromConfig(conf map[string]string) (*credentialBase, error) {
+ base := &credentialBase{
+ target: conf[configKeyTarget],
+ meta: metaFromConfig(conf),
+ }
+
+ if createTime, ok := conf[configKeyCreateTime]; ok {
+ t, err := repository.ParseTimestamp(createTime)
+ if err != nil {
+ return nil, err
+ }
+ base.createTime = t
+ } else {
+ return nil, fmt.Errorf("missing create time")
+ }
+
+ salt, err := saltFromConfig(conf)
+ if err != nil {
+ return nil, err
+ }
+ base.salt = salt
+
+ return base, nil
+}
+
+func (cb *credentialBase) Target() string {
+ return cb.target
+}
+
+func (cb *credentialBase) CreateTime() time.Time {
+ return cb.createTime
+}
+
+func (cb *credentialBase) Salt() []byte {
+ return cb.salt
+}
+
+func (cb *credentialBase) validate() error {
+ if cb.target == "" {
+ return fmt.Errorf("missing target")
+ }
+ if cb.createTime.IsZero() || cb.createTime.Equal(time.Time{}) {
+ return fmt.Errorf("missing creation time")
+ }
+ if !core.TargetExist(cb.target) {
+ return fmt.Errorf("unknown target")
+ }
+ return nil
+}
+
+func (cb *credentialBase) Metadata() map[string]string {
+ return cb.meta
+}
+
+func (cb *credentialBase) GetMetadata(key string) (string, bool) {
+ val, ok := cb.meta[key]
+ return val, ok
+}
+
+func (cb *credentialBase) SetMetadata(key string, value string) {
+ if cb.meta == nil {
+ cb.meta = make(map[string]string)
+ }
+ cb.meta[key] = value
+}
@@ -14,7 +14,7 @@ func TestCredential(t *testing.T) {
repo := repository.NewMockRepoForTest()
storeToken := func(val string, target string) *Token {
- token := NewToken(val, target)
+ token := NewToken(target, val)
err := Store(repo, token)
require.NoError(t, err)
return token
@@ -100,3 +100,25 @@ func sameIds(t *testing.T, a []Credential, b []Credential) {
assert.ElementsMatch(t, ids(a), ids(b))
}
+
+func testCredentialSerial(t *testing.T, original Credential) Credential {
+ repo := repository.NewMockRepoForTest()
+
+ original.SetMetadata("test", "value")
+
+ assert.NotEmpty(t, original.ID().String())
+ assert.NotEmpty(t, original.Salt())
+ assert.NoError(t, Store(repo, original))
+
+ loaded, err := LoadWithId(repo, original.ID())
+ assert.NoError(t, err)
+
+ assert.Equal(t, original.ID(), loaded.ID())
+ assert.Equal(t, original.Kind(), loaded.Kind())
+ assert.Equal(t, original.Target(), loaded.Target())
+ assert.Equal(t, original.CreateTime().Unix(), loaded.CreateTime().Unix())
+ assert.Equal(t, original.Salt(), loaded.Salt())
+ assert.Equal(t, original.Metadata(), loaded.Metadata())
+
+ return loaded
+}
@@ -0,0 +1,67 @@
+package auth
+
+import (
+ "crypto/sha256"
+ "fmt"
+
+ "github.com/MichaelMure/git-bug/entity"
+)
+
+const (
+ configKeyLoginLogin = "login"
+)
+
+var _ Credential = &Login{}
+
+type Login struct {
+ *credentialBase
+ Login string
+}
+
+func NewLogin(target, login string) *Login {
+ return &Login{
+ credentialBase: newCredentialBase(target),
+ Login: login,
+ }
+}
+
+func NewLoginFromConfig(conf map[string]string) (*Login, error) {
+ base, err := newCredentialBaseFromConfig(conf)
+ if err != nil {
+ return nil, err
+ }
+
+ return &Login{
+ credentialBase: base,
+ Login: conf[configKeyLoginLogin],
+ }, nil
+}
+
+func (lp *Login) ID() entity.Id {
+ h := sha256.New()
+ _, _ = h.Write(lp.salt)
+ _, _ = h.Write([]byte(lp.target))
+ _, _ = h.Write([]byte(lp.Login))
+ return entity.Id(fmt.Sprintf("%x", h.Sum(nil)))
+}
+
+func (lp *Login) Kind() CredentialKind {
+ return KindLogin
+}
+
+func (lp *Login) Validate() error {
+ err := lp.credentialBase.validate()
+ if err != nil {
+ return err
+ }
+ if lp.Login == "" {
+ return fmt.Errorf("missing login")
+ }
+ return nil
+}
+
+func (lp *Login) toConfig() map[string]string {
+ return map[string]string{
+ configKeyLoginLogin: lp.Login,
+ }
+}
@@ -0,0 +1,76 @@
+package auth
+
+import (
+ "crypto/sha256"
+ "fmt"
+
+ "github.com/MichaelMure/git-bug/entity"
+)
+
+const (
+ configKeyLoginPasswordLogin = "login"
+ configKeyLoginPasswordPassword = "password"
+)
+
+var _ Credential = &LoginPassword{}
+
+type LoginPassword struct {
+ *credentialBase
+ Login string
+ Password string
+}
+
+func NewLoginPassword(target, login, password string) *LoginPassword {
+ return &LoginPassword{
+ credentialBase: newCredentialBase(target),
+ Login: login,
+ Password: password,
+ }
+}
+
+func NewLoginPasswordFromConfig(conf map[string]string) (*LoginPassword, error) {
+ base, err := newCredentialBaseFromConfig(conf)
+ if err != nil {
+ return nil, err
+ }
+
+ return &LoginPassword{
+ credentialBase: base,
+ Login: conf[configKeyLoginPasswordLogin],
+ Password: conf[configKeyLoginPasswordPassword],
+ }, nil
+}
+
+func (lp *LoginPassword) ID() entity.Id {
+ h := sha256.New()
+ _, _ = h.Write(lp.salt)
+ _, _ = h.Write([]byte(lp.target))
+ _, _ = h.Write([]byte(lp.Login))
+ _, _ = h.Write([]byte(lp.Password))
+ return entity.Id(fmt.Sprintf("%x", h.Sum(nil)))
+}
+
+func (lp *LoginPassword) Kind() CredentialKind {
+ return KindLoginPassword
+}
+
+func (lp *LoginPassword) Validate() error {
+ err := lp.credentialBase.validate()
+ if err != nil {
+ return err
+ }
+ if lp.Login == "" {
+ return fmt.Errorf("missing login")
+ }
+ if lp.Password == "" {
+ return fmt.Errorf("missing password")
+ }
+ return nil
+}
+
+func (lp *LoginPassword) toConfig() map[string]string {
+ return map[string]string{
+ configKeyLoginPasswordLogin: lp.Login,
+ configKeyLoginPasswordPassword: lp.Password,
+ }
+}
@@ -0,0 +1,14 @@
+package auth
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestLoginPasswordSerial(t *testing.T) {
+ original := NewLoginPassword("github", "jean", "jacques")
+ loaded := testCredentialSerial(t, original)
+ assert.Equal(t, original.Login, loaded.(*LoginPassword).Login)
+ assert.Equal(t, original.Password, loaded.(*LoginPassword).Password)
+}
@@ -0,0 +1,13 @@
+package auth
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestLoginSerial(t *testing.T) {
+ original := NewLogin("github", "jean")
+ loaded := testCredentialSerial(t, original)
+ assert.Equal(t, original.Login, loaded.(*Login).Login)
+}
@@ -3,104 +3,68 @@ package auth
import (
"crypto/sha256"
"fmt"
- "time"
- "github.com/MichaelMure/git-bug/bridge/core"
"github.com/MichaelMure/git-bug/entity"
- "github.com/MichaelMure/git-bug/repository"
)
const (
- tokenValueKey = "value"
+ configKeyTokenValue = "value"
)
var _ Credential = &Token{}
// Token holds an API access token data
type Token struct {
- target string
- createTime time.Time
- Value string
- meta map[string]string
+ *credentialBase
+ Value string
}
// NewToken instantiate a new token
-func NewToken(value, target string) *Token {
+func NewToken(target, value string) *Token {
return &Token{
- target: target,
- createTime: time.Now(),
- Value: value,
+ credentialBase: newCredentialBase(target),
+ Value: value,
}
}
-func NewTokenFromConfig(conf map[string]string) *Token {
- token := &Token{}
-
- token.target = conf[configKeyTarget]
- if createTime, ok := conf[configKeyCreateTime]; ok {
- if t, err := repository.ParseTimestamp(createTime); err == nil {
- token.createTime = t
- }
+func NewTokenFromConfig(conf map[string]string) (*Token, error) {
+ base, err := newCredentialBaseFromConfig(conf)
+ if err != nil {
+ return nil, err
}
- token.Value = conf[tokenValueKey]
- token.meta = metaFromConfig(conf)
-
- return token
+ return &Token{
+ credentialBase: base,
+ Value: conf[configKeyTokenValue],
+ }, nil
}
func (t *Token) ID() entity.Id {
- sum := sha256.Sum256([]byte(t.target + t.Value))
- return entity.Id(fmt.Sprintf("%x", sum))
-}
-
-func (t *Token) Target() string {
- return t.target
+ h := sha256.New()
+ _, _ = h.Write(t.salt)
+ _, _ = h.Write([]byte(t.target))
+ _, _ = h.Write([]byte(t.Value))
+ return entity.Id(fmt.Sprintf("%x", h.Sum(nil)))
}
func (t *Token) Kind() CredentialKind {
return KindToken
}
-func (t *Token) CreateTime() time.Time {
- return t.createTime
-}
-
// Validate ensure token important fields are valid
func (t *Token) Validate() error {
+ err := t.credentialBase.validate()
+ if err != nil {
+ return err
+ }
if t.Value == "" {
return fmt.Errorf("missing value")
}
- if t.target == "" {
- return fmt.Errorf("missing target")
- }
- if t.createTime.IsZero() || t.createTime.Equal(time.Time{}) {
- return fmt.Errorf("missing creation time")
- }
- if !core.TargetExist(t.target) {
- return fmt.Errorf("unknown target")
- }
return nil
}
-func (t *Token) Metadata() map[string]string {
- return t.meta
-}
-
-func (t *Token) GetMetadata(key string) (string, bool) {
- val, ok := t.meta[key]
- return val, ok
-}
-
-func (t *Token) SetMetadata(key string, value string) {
- if t.meta == nil {
- t.meta = make(map[string]string)
- }
- t.meta[key] = value
-}
-
func (t *Token) toConfig() map[string]string {
return map[string]string{
- tokenValueKey: t.Value,
+ configKeyTokenValue: t.Value,
}
}
@@ -0,0 +1,13 @@
+package auth
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestTokenSerial(t *testing.T) {
+ original := NewToken("github", "value")
+ loaded := testCredentialSerial(t, original)
+ assert.Equal(t, original.Value, loaded.(*Token).Value)
+}
@@ -3,6 +3,7 @@ package github
import (
"bufio"
"bytes"
+ "context"
"encoding/json"
"fmt"
"io"
@@ -70,25 +71,7 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
return nil, fmt.Errorf("invalid parameter owner: %v", owner)
}
- login := params.Login
- if login == "" {
- validator := func(name string, value string) (string, error) {
- ok, err := validateUsername(value)
- if err != nil {
- return "", err
- }
- if !ok {
- return "invalid login", nil
- }
- return "", nil
- }
-
- login, err = input.Prompt("Github login", "login", input.Required, validator)
- if err != nil {
- return nil, err
- }
- }
-
+ var login string
var cred auth.Credential
switch {
@@ -97,10 +80,27 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
if err != nil {
return nil, err
}
+ l, ok := cred.GetMetadata(auth.MetaKeyLogin)
+ if !ok {
+ return nil, fmt.Errorf("credential doesn't have a login")
+ }
+ login = l
case params.TokenRaw != "":
- cred = auth.NewToken(params.TokenRaw, target)
- cred.SetMetadata(auth.MetaKeyLogin, login)
+ token := auth.NewToken(target, params.TokenRaw)
+ login, err = getLoginFromToken(token)
+ if err != nil {
+ return nil, err
+ }
+ token.SetMetadata(auth.MetaKeyLogin, login)
+ cred = token
default:
+ login = params.Login
+ if login == "" {
+ login, err = input.Prompt("Github login", "login", input.Required, usernameValidator)
+ if err != nil {
+ return nil, err
+ }
+ }
cred, err = promptTokenOptions(repo, login, owner, project)
if err != nil {
return nil, err
@@ -159,6 +159,17 @@ func (*Github) ValidateConfig(conf core.Configuration) error {
return nil
}
+func usernameValidator(name string, value string) (string, error) {
+ ok, err := validateUsername(value)
+ if err != nil {
+ return "", err
+ }
+ if !ok {
+ return "invalid login", nil
+ }
+ return "", nil
+}
+
func requestToken(note, login, password string, scope string) (*http.Response, error) {
return requestTokenWith2FA(note, login, password, "", scope)
}
@@ -231,7 +242,11 @@ func randomFingerprint() string {
func promptTokenOptions(repo repository.RepoConfig, login, owner, project string) (auth.Credential, error) {
for {
- creds, err := auth.List(repo, auth.WithTarget(target), auth.WithMeta(auth.MetaKeyLogin, login))
+ creds, err := auth.List(repo,
+ auth.WithTarget(target),
+ auth.WithKind(auth.KindToken),
+ auth.WithMeta(auth.MetaKeyLogin, login),
+ )
if err != nil {
return nil, err
}
@@ -275,19 +290,13 @@ func promptTokenOptions(repo repository.RepoConfig, login, owner, project string
switch index {
case 1:
- value, err := promptToken()
- if err != nil {
- return nil, err
- }
- token := auth.NewToken(value, target)
- token.SetMetadata(auth.MetaKeyLogin, login)
- return token, nil
+ return promptToken()
case 2:
value, err := loginAndRequestToken(login, owner, project)
if err != nil {
return nil, err
}
- token := auth.NewToken(value, target)
+ token := auth.NewToken(target, value)
token.SetMetadata(auth.MetaKeyLogin, login)
return token, nil
default:
@@ -296,7 +305,7 @@ func promptTokenOptions(repo repository.RepoConfig, login, owner, project string
}
}
-func promptToken() (string, error) {
+func promptToken() (*auth.Token, error) {
fmt.Println("You can generate a new token by visiting https://github.com/settings/tokens.")
fmt.Println("Choose 'Generate new token' and set the necessary access scope for your repository.")
fmt.Println()
@@ -312,14 +321,28 @@ func promptToken() (string, error) {
panic("regexp compile:" + err.Error())
}
+ var login string
+
validator := func(name string, value string) (complaint string, err error) {
- if re.MatchString(value) {
- return "", nil
+ if !re.MatchString(value) {
+ return "token has incorrect format", nil
+ }
+ login, err = getLoginFromToken(auth.NewToken(target, value))
+ if err != nil {
+ return fmt.Sprintf("token is invalid: %v", err), nil
}
- return "token has incorrect format", nil
+ return "", nil
+ }
+
+ rawToken, err := input.Prompt("Enter token", "token", input.Required, validator)
+ if err != nil {
+ return nil, err
}
- return input.Prompt("Enter token", "token", input.Required, validator)
+ token := auth.NewToken(target, rawToken)
+ token.SetMetadata(auth.MetaKeyLogin, login)
+
+ return token, nil
}
func loginAndRequestToken(login, owner, project string) (string, error) {
@@ -543,3 +566,22 @@ func validateProject(owner, project string, token *auth.Token) (bool, error) {
return resp.StatusCode == http.StatusOK, nil
}
+
+func getLoginFromToken(token *auth.Token) (string, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
+ defer cancel()
+
+ client := buildClient(token)
+
+ var q loginQuery
+
+ err := client.Query(ctx, &q, nil)
+ if err != nil {
+ return "", err
+ }
+ if q.Viewer.Login == "" {
+ return "", fmt.Errorf("github say username is empty")
+ }
+
+ return q.Viewer.Login, nil
+}
@@ -154,8 +154,8 @@ func TestValidateProject(t *testing.T) {
t.Skip("Env var GITHUB_TOKEN_PUBLIC missing")
}
- tokenPrivate := auth.NewToken(envPrivate, target)
- tokenPublic := auth.NewToken(envPublic, target)
+ tokenPrivate := auth.NewToken(target, envPrivate)
+ tokenPublic := auth.NewToken(target, envPublic)
type args struct {
owner string
@@ -157,7 +157,7 @@ func TestPushPull(t *testing.T) {
defer backend.Close()
interrupt.RegisterCleaner(backend.Close)
- token := auth.NewToken(envToken, target)
+ token := auth.NewToken(target, envToken)
token.SetMetadata(auth.MetaKeyLogin, login)
err = auth.Store(repo, token)
require.NoError(t, err)
@@ -168,14 +168,6 @@ type ghostQuery struct {
} `graphql:"user(login: $login)"`
}
-type labelQuery struct {
- Repository struct {
- Label struct {
- ID string `graphql:"id"`
- } `graphql:"label(name: $label)"`
- } `graphql:"repository(owner: $owner, name: $name)"`
-}
-
type labelsQuery struct {
Repository struct {
Labels struct {
@@ -189,3 +181,9 @@ type labelsQuery struct {
} `graphql:"labels(first: $first, after: $after)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}
+
+type loginQuery struct {
+ Viewer struct {
+ Login string `graphql:"login"`
+ } `graphql:"viewer"`
+}
@@ -144,7 +144,7 @@ func Test_Importer(t *testing.T) {
login := "test-identity"
author.SetMetadata(metaKeyGithubLogin, login)
- token := auth.NewToken(envToken, target)
+ token := auth.NewToken(target, envToken)
token.SetMetadata(auth.MetaKeyLogin, login)
err = auth.Store(repo, token)
require.NoError(t, err)
@@ -35,9 +35,6 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
if params.Owner != "" {
fmt.Println("warning: --owner is ineffective for a gitlab bridge")
}
- if params.Login != "" {
- fmt.Println("warning: --login is ineffective for a gitlab bridge")
- }
conf := make(core.Configuration)
var err error
@@ -53,24 +50,25 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
}
}
- var url string
+ var projectURL string
// get project url
switch {
case params.URL != "":
- url = params.URL
+ projectURL = params.URL
default:
// terminal prompt
- url, err = promptURL(repo, baseUrl)
+ projectURL, err = promptProjectURL(repo, baseUrl)
if err != nil {
return nil, errors.Wrap(err, "url prompt")
}
}
- if !strings.HasPrefix(url, params.BaseURL) {
- return nil, fmt.Errorf("base URL (%s) doesn't match the project URL (%s)", params.BaseURL, url)
+ if !strings.HasPrefix(projectURL, params.BaseURL) {
+ return nil, fmt.Errorf("base URL (%s) doesn't match the project URL (%s)", params.BaseURL, projectURL)
}
+ var login string
var cred auth.Credential
switch {
@@ -79,16 +77,30 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
if err != nil {
return nil, err
}
+ l, ok := cred.GetMetadata(auth.MetaKeyLogin)
+ if !ok {
+ return nil, fmt.Errorf("credential doesn't have a login")
+ }
+ login = l
case params.TokenRaw != "":
- token := auth.NewToken(params.TokenRaw, target)
- login, err := getLoginFromToken(baseUrl, token)
+ token := auth.NewToken(target, params.TokenRaw)
+ login, err = getLoginFromToken(baseUrl, token)
if err != nil {
return nil, err
}
token.SetMetadata(auth.MetaKeyLogin, login)
+ token.SetMetadata(auth.MetaKeyBaseURL, baseUrl)
cred = token
default:
- cred, err = promptTokenOptions(repo, baseUrl)
+ login := params.Login
+ if login == "" {
+ // TODO: validate username
+ login, err = input.Prompt("Gitlab login", "login", input.Required)
+ if err != nil {
+ return nil, err
+ }
+ }
+ cred, err = promptTokenOptions(repo, login, baseUrl)
if err != nil {
return nil, err
}
@@ -100,7 +112,7 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
}
// validate project url and get its ID
- id, err := validateProjectURL(baseUrl, url, token)
+ id, err := validateProjectURL(baseUrl, projectURL, token)
if err != nil {
return nil, errors.Wrap(err, "project validation")
}
@@ -122,7 +134,7 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
}
}
- return conf, nil
+ return conf, core.FinishConfig(repo, metaKeyGitlabLogin, login)
}
func (g *Gitlab) ValidateConfig(conf core.Configuration) error {
@@ -176,9 +188,14 @@ func promptBaseUrl() (string, error) {
return input.Prompt("Base url", "url", input.Required, validator)
}
-func promptTokenOptions(repo repository.RepoConfig, baseUrl string) (auth.Credential, error) {
+func promptTokenOptions(repo repository.RepoConfig, login, baseUrl string) (auth.Credential, error) {
for {
- creds, err := auth.List(repo, auth.WithTarget(target), auth.WithKind(auth.KindToken))
+ creds, err := auth.List(repo,
+ auth.WithTarget(target),
+ auth.WithKind(auth.KindToken),
+ auth.WithMeta(auth.MetaKeyLogin, login),
+ auth.WithMeta(auth.MetaKeyBaseURL, baseUrl),
+ )
if err != nil {
return nil, err
}
@@ -248,7 +265,7 @@ func promptToken(baseUrl string) (*auth.Token, error) {
if !re.MatchString(value) {
return "token has incorrect format", nil
}
- login, err = getLoginFromToken(baseUrl, auth.NewToken(value, target))
+ login, err = getLoginFromToken(baseUrl, auth.NewToken(target, value))
if err != nil {
return fmt.Sprintf("token is invalid: %v", err), nil
}
@@ -260,13 +277,14 @@ func promptToken(baseUrl string) (*auth.Token, error) {
return nil, err
}
- token := auth.NewToken(rawToken, target)
+ token := auth.NewToken(target, rawToken)
token.SetMetadata(auth.MetaKeyLogin, login)
+ token.SetMetadata(auth.MetaKeyBaseURL, baseUrl)
return token, nil
}
-func promptURL(repo repository.RepoCommon, baseUrl string) (string, error) {
+func promptProjectURL(repo repository.RepoCommon, baseUrl string) (string, error) {
// remote suggestions
remotes, err := repo.GetRemotes()
if err != nil {
@@ -317,13 +335,13 @@ func promptURL(repo repository.RepoCommon, baseUrl string) (string, error) {
return "", err
}
- url := strings.TrimSpace(line)
- if url == "" {
+ projectURL := strings.TrimSpace(line)
+ if projectURL == "" {
fmt.Println("URL is empty")
continue
}
- return url, nil
+ return projectURL, nil
}
}
@@ -47,7 +47,7 @@ func (ge *gitlabExporter) Init(repo *cache.RepoCache, conf core.Configuration) e
ge.repositoryID = ge.conf[keyProjectID]
// preload all clients
- err := ge.cacheAllClient(repo)
+ err := ge.cacheAllClient(repo, ge.conf[keyGitlabBaseUrl])
if err != nil {
return err
}
@@ -55,8 +55,12 @@ func (ge *gitlabExporter) Init(repo *cache.RepoCache, conf core.Configuration) e
return nil
}
-func (ge *gitlabExporter) cacheAllClient(repo *cache.RepoCache) error {
- creds, err := auth.List(repo, auth.WithTarget(target), auth.WithKind(auth.KindToken))
+func (ge *gitlabExporter) cacheAllClient(repo *cache.RepoCache, baseURL string) error {
+ creds, err := auth.List(repo,
+ auth.WithTarget(target),
+ auth.WithKind(auth.KindToken),
+ auth.WithMeta(auth.MetaKeyBaseURL, baseURL),
+ )
if err != nil {
return err
}
@@ -162,8 +162,9 @@ func TestPushPull(t *testing.T) {
defer backend.Close()
interrupt.RegisterCleaner(backend.Close)
- token := auth.NewToken(envToken, target)
+ token := auth.NewToken(target, envToken)
token.SetMetadata(auth.MetaKeyLogin, login)
+ token.SetMetadata(auth.MetaKeyBaseURL, defaultBaseURL)
err = auth.Store(repo, token)
require.NoError(t, err)
@@ -194,7 +195,7 @@ func TestPushPull(t *testing.T) {
exporter := &gitlabExporter{}
err = exporter.Init(backend, core.Configuration{
keyProjectID: strconv.Itoa(projectID),
- keyGitlabBaseUrl: "https://gitlab.com/",
+ keyGitlabBaseUrl: defaultBaseURL,
})
require.NoError(t, err)
@@ -222,7 +223,7 @@ func TestPushPull(t *testing.T) {
importer := &gitlabImporter{}
err = importer.Init(backend, core.Configuration{
keyProjectID: strconv.Itoa(projectID),
- keyGitlabBaseUrl: "https://gitlab.com/",
+ keyGitlabBaseUrl: defaultBaseURL,
})
require.NoError(t, err)
@@ -287,7 +288,7 @@ func generateRepoName() string {
// create repository need a token with scope 'repo'
func createRepository(ctx context.Context, name string, token *auth.Token) (int, error) {
- client, err := buildClient("https://gitlab.com/", token)
+ client, err := buildClient(defaultBaseURL, token)
if err != nil {
return 0, err
}
@@ -307,7 +308,7 @@ func createRepository(ctx context.Context, name string, token *auth.Token) (int,
// delete repository need a token with scope 'delete_repo'
func deleteRepository(ctx context.Context, project int, token *auth.Token) error {
- client, err := buildClient("https://gitlab.com/", token)
+ client, err := buildClient(defaultBaseURL, token)
if err != nil {
return err
}
@@ -33,7 +33,11 @@ type gitlabImporter struct {
func (gi *gitlabImporter) Init(repo *cache.RepoCache, conf core.Configuration) error {
gi.conf = conf
- creds, err := auth.List(repo, auth.WithTarget(target), auth.WithKind(auth.KindToken))
+ creds, err := auth.List(repo,
+ auth.WithTarget(target),
+ auth.WithKind(auth.KindToken),
+ auth.WithMeta(auth.MetaKeyBaseURL, conf[keyGitlabBaseUrl]),
+ )
if err != nil {
return err
}
@@ -98,15 +98,16 @@ func TestImport(t *testing.T) {
login := "test-identity"
author.SetMetadata(metaKeyGitlabLogin, login)
- token := auth.NewToken(envToken, target)
- token.SetMetadata(metaKeyGitlabLogin, login)
+ token := auth.NewToken(target, envToken)
+ token.SetMetadata(auth.MetaKeyLogin, login)
+ token.SetMetadata(auth.MetaKeyBaseURL, defaultBaseURL)
err = auth.Store(repo, token)
require.NoError(t, err)
importer := &gitlabImporter{}
err = importer.Init(backend, core.Configuration{
keyProjectID: projectID,
- keyGitlabBaseUrl: "https://gitlab.com",
+ keyGitlabBaseUrl: defaultBaseURL,
})
require.NoError(t, err)
@@ -58,6 +58,9 @@ type RepoCache struct {
// the underlying repo
repo repository.ClockedRepo
+ // the name of the repository, as defined in the MultiRepoCache
+ name string
+
muBug sync.RWMutex
// excerpt of bugs data for all bugs
bugExcerpts map[entity.Id]*BugExcerpt
@@ -75,8 +78,13 @@ type RepoCache struct {
}
func NewRepoCache(r repository.ClockedRepo) (*RepoCache, error) {
+ return NewNamedRepoCache(r, "")
+}
+
+func NewNamedRepoCache(r repository.ClockedRepo, name string) (*RepoCache, error) {
c := &RepoCache{
repo: r,
+ name: name,
bugs: make(map[entity.Id]*BugCache),
identities: make(map[entity.Id]*IdentityCache),
}
@@ -102,6 +110,10 @@ func NewRepoCache(r repository.ClockedRepo) (*RepoCache, error) {
return c, c.write()
}
+func (c *RepoCache) Name() string {
+ return c.name
+}
+
// LocalConfig give access to the repository scoped configuration
func (c *RepoCache) LocalConfig() repository.Config {
return c.repo.LocalConfig()
@@ -86,7 +86,7 @@ func runBridgeTokenAdd(cmd *cobra.Command, args []string) error {
}
}
- token := auth.NewToken(value, bridgeAuthAddTokenTarget)
+ token := auth.NewToken(bridgeAuthAddTokenTarget, value)
token.SetMetadata(auth.MetaKeyLogin, bridgeAuthAddTokenLogin)
if err := token.Validate(); err != nil {
@@ -13,7 +13,7 @@ require (
github.com/dustin/go-humanize v1.0.0
github.com/fatih/color v1.9.0
github.com/go-errors/errors v1.0.1
- github.com/gorilla/mux v1.7.3
+ github.com/gorilla/mux v1.7.4
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428
github.com/mattn/go-isatty v0.0.12
@@ -26,7 +26,7 @@ require (
github.com/stretchr/testify v1.4.0
github.com/theckman/goconstraint v1.11.0
github.com/vektah/gqlparser v1.3.1
- github.com/xanzy/go-gitlab v0.24.0
+ github.com/xanzy/go-gitlab v0.25.0
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288
golang.org/x/sync v0.0.0-20190423024810-112230192c58
@@ -51,6 +51,8 @@ github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
+github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
@@ -138,6 +140,8 @@ github.com/xanzy/go-gitlab v0.22.1 h1:TVxgHmoa35jQL+9FCkG0nwPDxU9dQZXknBTDtGaSFn
github.com/xanzy/go-gitlab v0.22.1/go.mod h1:t4Bmvnxj7k37S4Y17lfLx+nLqkf/oQwT2HagfWKv5Og=
github.com/xanzy/go-gitlab v0.24.0 h1:zP1zC4K76Gha0coN5GhygOLhsHTCvUjrnqGL3kHXkVU=
github.com/xanzy/go-gitlab v0.24.0/go.mod h1:t4Bmvnxj7k37S4Y17lfLx+nLqkf/oQwT2HagfWKv5Og=
+github.com/xanzy/go-gitlab v0.25.0 h1:G5aTZeqZd66Q6qMVieBfmHBsPpF0jY92zCLAMpULe3I=
+github.com/xanzy/go-gitlab v0.25.0/go.mod h1:t4Bmvnxj7k37S4Y17lfLx+nLqkf/oQwT2HagfWKv5Og=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
@@ -163,16 +163,6 @@ type ComplexityRoot struct {
Message func(childComplexity int) int
}
- CommitAsNeededPayload struct {
- Bug func(childComplexity int) int
- ClientMutationID func(childComplexity int) int
- }
-
- CommitPayload struct {
- Bug func(childComplexity int) int
- ClientMutationID func(childComplexity int) int
- }
-
CreateOperation struct {
Author func(childComplexity int) int
Date func(childComplexity int) int
@@ -264,14 +254,12 @@ type ComplexityRoot struct {
}
Mutation struct {
- AddComment func(childComplexity int, input models.AddCommentInput) int
- ChangeLabels func(childComplexity int, input *models.ChangeLabelInput) int
- CloseBug func(childComplexity int, input models.CloseBugInput) int
- Commit func(childComplexity int, input models.CommitInput) int
- CommitAsNeeded func(childComplexity int, input models.CommitAsNeededInput) int
- NewBug func(childComplexity int, input models.NewBugInput) int
- OpenBug func(childComplexity int, input models.OpenBugInput) int
- SetTitle func(childComplexity int, input models.SetTitleInput) int
+ AddComment func(childComplexity int, input models.AddCommentInput) int
+ ChangeLabels func(childComplexity int, input *models.ChangeLabelInput) int
+ CloseBug func(childComplexity int, input models.CloseBugInput) int
+ NewBug func(childComplexity int, input models.NewBugInput) int
+ OpenBug func(childComplexity int, input models.OpenBugInput) int
+ SetTitle func(childComplexity int, input models.SetTitleInput) int
}
NewBugPayload struct {
@@ -306,8 +294,7 @@ type ComplexityRoot struct {
}
Query struct {
- DefaultRepository func(childComplexity int) int
- Repository func(childComplexity int, ref string) int
+ Repository func(childComplexity int, ref *string) int
}
Repository struct {
@@ -315,6 +302,7 @@ type ComplexityRoot struct {
AllIdentities func(childComplexity int, after *string, before *string, first *int, last *int) int
Bug func(childComplexity int, prefix string) int
Identity func(childComplexity int, prefix string) int
+ Name func(childComplexity int) int
UserIdentity func(childComplexity int) int
ValidLabels func(childComplexity int, after *string, before *string, first *int, last *int) int
}
@@ -448,14 +436,12 @@ type MutationResolver interface {
OpenBug(ctx context.Context, input models.OpenBugInput) (*models.OpenBugPayload, error)
CloseBug(ctx context.Context, input models.CloseBugInput) (*models.CloseBugPayload, error)
SetTitle(ctx context.Context, input models.SetTitleInput) (*models.SetTitlePayload, error)
- Commit(ctx context.Context, input models.CommitInput) (*models.CommitPayload, error)
- CommitAsNeeded(ctx context.Context, input models.CommitAsNeededInput) (*models.CommitAsNeededPayload, error)
}
type QueryResolver interface {
- DefaultRepository(ctx context.Context) (*models.Repository, error)
- Repository(ctx context.Context, ref string) (*models.Repository, error)
+ Repository(ctx context.Context, ref *string) (*models.Repository, error)
}
type RepositoryResolver interface {
+ Name(ctx context.Context, obj *models.Repository) (*string, error)
AllBugs(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, query *string) (*models.BugConnection, error)
Bug(ctx context.Context, obj *models.Repository, prefix string) (models.BugWrapper, error)
AllIdentities(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error)
@@ -925,34 +911,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.CommentHistoryStep.Message(childComplexity), true
- case "CommitAsNeededPayload.bug":
- if e.complexity.CommitAsNeededPayload.Bug == nil {
- break
- }
-
- return e.complexity.CommitAsNeededPayload.Bug(childComplexity), true
-
- case "CommitAsNeededPayload.clientMutationId":
- if e.complexity.CommitAsNeededPayload.ClientMutationID == nil {
- break
- }
-
- return e.complexity.CommitAsNeededPayload.ClientMutationID(childComplexity), true
-
- case "CommitPayload.bug":
- if e.complexity.CommitPayload.Bug == nil {
- break
- }
-
- return e.complexity.CommitPayload.Bug(childComplexity), true
-
- case "CommitPayload.clientMutationId":
- if e.complexity.CommitPayload.ClientMutationID == nil {
- break
- }
-
- return e.complexity.CommitPayload.ClientMutationID(childComplexity), true
-
case "CreateOperation.author":
if e.complexity.CreateOperation.Author == nil {
break
@@ -1367,30 +1325,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.CloseBug(childComplexity, args["input"].(models.CloseBugInput)), true
- case "Mutation.commit":
- if e.complexity.Mutation.Commit == nil {
- break
- }
-
- args, err := ec.field_Mutation_commit_args(context.TODO(), rawArgs)
- if err != nil {
- return 0, false
- }
-
- return e.complexity.Mutation.Commit(childComplexity, args["input"].(models.CommitInput)), true
-
- case "Mutation.commitAsNeeded":
- if e.complexity.Mutation.CommitAsNeeded == nil {
- break
- }
-
- args, err := ec.field_Mutation_commitAsNeeded_args(context.TODO(), rawArgs)
- if err != nil {
- return 0, false
- }
-
- return e.complexity.Mutation.CommitAsNeeded(childComplexity, args["input"].(models.CommitAsNeededInput)), true
-
case "Mutation.newBug":
if e.complexity.Mutation.NewBug == nil {
break
@@ -1539,13 +1473,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.PageInfo.StartCursor(childComplexity), true
- case "Query.defaultRepository":
- if e.complexity.Query.DefaultRepository == nil {
- break
- }
-
- return e.complexity.Query.DefaultRepository(childComplexity), true
-
case "Query.repository":
if e.complexity.Query.Repository == nil {
break
@@ -1556,7 +1483,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return 0, false
}
- return e.complexity.Query.Repository(childComplexity, args["ref"].(string)), true
+ return e.complexity.Query.Repository(childComplexity, args["ref"].(*string)), true
case "Repository.allBugs":
if e.complexity.Repository.AllBugs == nil {
@@ -1606,6 +1533,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Repository.Identity(childComplexity, args["prefix"].(string)), true
+ case "Repository.name":
+ if e.complexity.Repository.Name == nil {
+ break
+ }
+
+ return e.complexity.Repository.Name(childComplexity), true
+
case "Repository.userIdentity":
if e.complexity.Repository.UserIdentity == nil {
break
@@ -2184,38 +2118,6 @@ type SetTitlePayload {
"""The resulting operation"""
operation: SetTitleOperation!
}
-
-input CommitInput {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """"The name of the repository. If not set, the default repository is used."""
- repoRef: String
- """The bug ID's prefix."""
- prefix: String!
-}
-
-type CommitPayload {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """The affected bug."""
- bug: Bug!
-}
-
-input CommitAsNeededInput {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """"The name of the repository. If not set, the default repository is used."""
- repoRef: String
- """The bug ID's prefix."""
- prefix: String!
-}
-
-type CommitAsNeededPayload {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """The affected bug."""
- bug: Bug!
-}
`, BuiltIn: false},
&ast.Source{Name: "schema/operations.graphql", Input: `"""An operation applied to a bug."""
interface Operation {
@@ -2320,6 +2222,9 @@ type LabelChangeOperation implements Operation & Authored {
`, BuiltIn: false},
&ast.Source{Name: "schema/repository.graphql", Input: `
type Repository {
+ """The name of the repository"""
+ name: String
+
"""All the bugs"""
allBugs(
"""Returns the elements in the list that come after the specified cursor."""
@@ -2330,7 +2235,7 @@ type Repository {
first: Int
"""Returns the last _n_ elements from the list."""
last: Int
- """A query to select and order bugs"""
+ """A query to select and order bugs."""
query: String
): BugConnection!
@@ -2366,12 +2271,8 @@ type Repository {
): LabelConnection!
}`, BuiltIn: false},
&ast.Source{Name: "schema/root.graphql", Input: `type Query {
- """The default unnamend repository."""
- defaultRepository: Repository
- """Access a repository by reference/name."""
- repository(ref: String!): Repository
-
- #TODO: connection for all repositories
+ """Access a repository by reference/name. If no ref is given, the default repository is returned if any."""
+ repository(ref: String): Repository
}
type Mutation {
@@ -2387,10 +2288,6 @@ type Mutation {
closeBug(input: CloseBugInput!): CloseBugPayload!
"""Change a bug's title"""
setTitle(input: SetTitleInput!): SetTitlePayload!
- """Commit write the pending operations into storage. This mutation fail if nothing is pending"""
- commit(input: CommitInput!): CommitPayload!
- """Commit write the pending operations into storage. This mutation succed if nothing is pending"""
- commitAsNeeded(input: CommitAsNeededInput!): CommitAsNeededPayload!
}
`, BuiltIn: false},
&ast.Source{Name: "schema/timeline.graphql", Input: `"""An item in the timeline of events"""
@@ -2750,34 +2647,6 @@ func (ec *executionContext) field_Mutation_closeBug_args(ctx context.Context, ra
return args, nil
}
-func (ec *executionContext) field_Mutation_commitAsNeeded_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
- var err error
- args := map[string]interface{}{}
- var arg0 models.CommitAsNeededInput
- if tmp, ok := rawArgs["input"]; ok {
- arg0, err = ec.unmarshalNCommitAsNeededInput2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitAsNeededInput(ctx, tmp)
- if err != nil {
- return nil, err
- }
- }
- args["input"] = arg0
- return args, nil
-}
-
-func (ec *executionContext) field_Mutation_commit_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
- var err error
- args := map[string]interface{}{}
- var arg0 models.CommitInput
- if tmp, ok := rawArgs["input"]; ok {
- arg0, err = ec.unmarshalNCommitInput2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitInput(ctx, tmp)
- if err != nil {
- return nil, err
- }
- }
- args["input"] = arg0
- return args, nil
-}
-
func (ec *executionContext) field_Mutation_newBug_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
@@ -2837,9 +2706,9 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs
func (ec *executionContext) field_Query_repository_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
- var arg0 string
+ var arg0 *string
if tmp, ok := rawArgs["ref"]; ok {
- arg0, err = ec.unmarshalNString2string(ctx, tmp)
+ arg0, err = ec.unmarshalOString2ᚖstring(ctx, tmp)
if err != nil {
return nil, err
}
@@ -4998,136 +4867,6 @@ func (ec *executionContext) _CommentHistoryStep_date(ctx context.Context, field
return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res)
}
-func (ec *executionContext) _CommitAsNeededPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.CommitAsNeededPayload) (ret graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- ret = graphql.Null
- }
- }()
- fc := &graphql.FieldContext{
- Object: "CommitAsNeededPayload",
- Field: field,
- Args: nil,
- IsMethod: false,
- }
-
- ctx = graphql.WithFieldContext(ctx, fc)
- resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return obj.ClientMutationID, nil
- })
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- if resTmp == nil {
- return graphql.Null
- }
- res := resTmp.(*string)
- fc.Result = res
- return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) _CommitAsNeededPayload_bug(ctx context.Context, field graphql.CollectedField, obj *models.CommitAsNeededPayload) (ret graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- ret = graphql.Null
- }
- }()
- fc := &graphql.FieldContext{
- Object: "CommitAsNeededPayload",
- Field: field,
- Args: nil,
- IsMethod: false,
- }
-
- ctx = graphql.WithFieldContext(ctx, fc)
- resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return obj.Bug, nil
- })
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- if resTmp == nil {
- if !graphql.HasFieldError(ctx, fc) {
- ec.Errorf(ctx, "must not be null")
- }
- return graphql.Null
- }
- res := resTmp.(models.BugWrapper)
- fc.Result = res
- return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) _CommitPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.CommitPayload) (ret graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- ret = graphql.Null
- }
- }()
- fc := &graphql.FieldContext{
- Object: "CommitPayload",
- Field: field,
- Args: nil,
- IsMethod: false,
- }
-
- ctx = graphql.WithFieldContext(ctx, fc)
- resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return obj.ClientMutationID, nil
- })
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- if resTmp == nil {
- return graphql.Null
- }
- res := resTmp.(*string)
- fc.Result = res
- return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) _CommitPayload_bug(ctx context.Context, field graphql.CollectedField, obj *models.CommitPayload) (ret graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- ret = graphql.Null
- }
- }()
- fc := &graphql.FieldContext{
- Object: "CommitPayload",
- Field: field,
- Args: nil,
- IsMethod: false,
- }
-
- ctx = graphql.WithFieldContext(ctx, fc)
- resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return obj.Bug, nil
- })
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- if resTmp == nil {
- if !graphql.HasFieldError(ctx, fc) {
- ec.Errorf(ctx, "must not be null")
- }
- return graphql.Null
- }
- res := resTmp.(models.BugWrapper)
- fc.Result = res
- return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res)
-}
-
func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@@ -7201,88 +6940,6 @@ func (ec *executionContext) _Mutation_setTitle(ctx context.Context, field graphq
return ec.marshalNSetTitlePayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐSetTitlePayload(ctx, field.Selections, res)
}
-func (ec *executionContext) _Mutation_commit(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- ret = graphql.Null
- }
- }()
- fc := &graphql.FieldContext{
- Object: "Mutation",
- Field: field,
- Args: nil,
- IsMethod: true,
- }
-
- ctx = graphql.WithFieldContext(ctx, fc)
- rawArgs := field.ArgumentMap(ec.Variables)
- args, err := ec.field_Mutation_commit_args(ctx, rawArgs)
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- fc.Args = args
- resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().Commit(rctx, args["input"].(models.CommitInput))
- })
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- if resTmp == nil {
- if !graphql.HasFieldError(ctx, fc) {
- ec.Errorf(ctx, "must not be null")
- }
- return graphql.Null
- }
- res := resTmp.(*models.CommitPayload)
- fc.Result = res
- return ec.marshalNCommitPayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitPayload(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) _Mutation_commitAsNeeded(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- ret = graphql.Null
- }
- }()
- fc := &graphql.FieldContext{
- Object: "Mutation",
- Field: field,
- Args: nil,
- IsMethod: true,
- }
-
- ctx = graphql.WithFieldContext(ctx, fc)
- rawArgs := field.ArgumentMap(ec.Variables)
- args, err := ec.field_Mutation_commitAsNeeded_args(ctx, rawArgs)
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- fc.Args = args
- resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().CommitAsNeeded(rctx, args["input"].(models.CommitAsNeededInput))
- })
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- if resTmp == nil {
- if !graphql.HasFieldError(ctx, fc) {
- ec.Errorf(ctx, "must not be null")
- }
- return graphql.Null
- }
- res := resTmp.(*models.CommitAsNeededPayload)
- fc.Result = res
- return ec.marshalNCommitAsNeededPayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitAsNeededPayload(ctx, field.Selections, res)
-}
-
func (ec *executionContext) _NewBugPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.NewBugPayload) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@@ -7821,7 +7478,7 @@ func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graph
return ec.marshalNString2string(ctx, field.Selections, res)
}
-func (ec *executionContext) _Query_defaultRepository(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+func (ec *executionContext) _Query_repository(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
@@ -7836,9 +7493,16 @@ func (ec *executionContext) _Query_defaultRepository(ctx context.Context, field
}
ctx = graphql.WithFieldContext(ctx, fc)
+ rawArgs := field.ArgumentMap(ec.Variables)
+ args, err := ec.field_Query_repository_args(ctx, rawArgs)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ fc.Args = args
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Query().DefaultRepository(rctx)
+ return ec.resolvers.Query().Repository(rctx, args["ref"].(*string))
})
if err != nil {
ec.Error(ctx, err)
@@ -7852,7 +7516,7 @@ func (ec *executionContext) _Query_defaultRepository(ctx context.Context, field
return ec.marshalORepository2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐRepository(ctx, field.Selections, res)
}
-func (ec *executionContext) _Query_repository(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
@@ -7868,7 +7532,7 @@ func (ec *executionContext) _Query_repository(ctx context.Context, field graphql
ctx = graphql.WithFieldContext(ctx, fc)
rawArgs := field.ArgumentMap(ec.Variables)
- args, err := ec.field_Query_repository_args(ctx, rawArgs)
+ args, err := ec.field_Query___type_args(ctx, rawArgs)
if err != nil {
ec.Error(ctx, err)
return graphql.Null
@@ -7876,7 +7540,7 @@ func (ec *executionContext) _Query_repository(ctx context.Context, field graphql
fc.Args = args
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Query().Repository(rctx, args["ref"].(string))
+ return ec.introspectType(args["name"].(string))
})
if err != nil {
ec.Error(ctx, err)
@@ -7885,12 +7549,12 @@ func (ec *executionContext) _Query_repository(ctx context.Context, field graphql
if resTmp == nil {
return graphql.Null
}
- res := resTmp.(*models.Repository)
+ res := resTmp.(*introspection.Type)
fc.Result = res
- return ec.marshalORepository2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐRepository(ctx, field.Selections, res)
+ return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)
}
-func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
@@ -7905,16 +7569,9 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col
}
ctx = graphql.WithFieldContext(ctx, fc)
- rawArgs := field.ArgumentMap(ec.Variables)
- args, err := ec.field_Query___type_args(ctx, rawArgs)
- if err != nil {
- ec.Error(ctx, err)
- return graphql.Null
- }
- fc.Args = args
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.introspectType(args["name"].(string))
+ return ec.introspectSchema()
})
if err != nil {
ec.Error(ctx, err)
@@ -7923,12 +7580,12 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col
if resTmp == nil {
return graphql.Null
}
- res := resTmp.(*introspection.Type)
+ res := resTmp.(*introspection.Schema)
fc.Result = res
- return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res)
+ return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)
}
-func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+func (ec *executionContext) _Repository_name(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
@@ -7936,7 +7593,7 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C
}
}()
fc := &graphql.FieldContext{
- Object: "Query",
+ Object: "Repository",
Field: field,
Args: nil,
IsMethod: true,
@@ -7945,7 +7602,7 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.introspectSchema()
+ return ec.resolvers.Repository().Name(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
@@ -7954,9 +7611,9 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C
if resTmp == nil {
return graphql.Null
}
- res := resTmp.(*introspection.Schema)
+ res := resTmp.(*string)
fc.Result = res
- return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res)
+ return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _Repository_allBugs(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
@@ -10273,66 +9930,6 @@ func (ec *executionContext) unmarshalInputCloseBugInput(ctx context.Context, obj
return it, nil
}
-func (ec *executionContext) unmarshalInputCommitAsNeededInput(ctx context.Context, obj interface{}) (models.CommitAsNeededInput, error) {
- var it models.CommitAsNeededInput
- var asMap = obj.(map[string]interface{})
-
- for k, v := range asMap {
- switch k {
- case "clientMutationId":
- var err error
- it.ClientMutationID, err = ec.unmarshalOString2ᚖstring(ctx, v)
- if err != nil {
- return it, err
- }
- case "repoRef":
- var err error
- it.RepoRef, err = ec.unmarshalOString2ᚖstring(ctx, v)
- if err != nil {
- return it, err
- }
- case "prefix":
- var err error
- it.Prefix, err = ec.unmarshalNString2string(ctx, v)
- if err != nil {
- return it, err
- }
- }
- }
-
- return it, nil
-}
-
-func (ec *executionContext) unmarshalInputCommitInput(ctx context.Context, obj interface{}) (models.CommitInput, error) {
- var it models.CommitInput
- var asMap = obj.(map[string]interface{})
-
- for k, v := range asMap {
- switch k {
- case "clientMutationId":
- var err error
- it.ClientMutationID, err = ec.unmarshalOString2ᚖstring(ctx, v)
- if err != nil {
- return it, err
- }
- case "repoRef":
- var err error
- it.RepoRef, err = ec.unmarshalOString2ᚖstring(ctx, v)
- if err != nil {
- return it, err
- }
- case "prefix":
- var err error
- it.Prefix, err = ec.unmarshalNString2string(ctx, v)
- if err != nil {
- return it, err
- }
- }
- }
-
- return it, nil
-}
-
func (ec *executionContext) unmarshalInputNewBugInput(ctx context.Context, obj interface{}) (models.NewBugInput, error) {
var it models.NewBugInput
var asMap = obj.(map[string]interface{})
@@ -11346,64 +10943,6 @@ func (ec *executionContext) _CommentHistoryStep(ctx context.Context, sel ast.Sel
return out
}
-var commitAsNeededPayloadImplementors = []string{"CommitAsNeededPayload"}
-
-func (ec *executionContext) _CommitAsNeededPayload(ctx context.Context, sel ast.SelectionSet, obj *models.CommitAsNeededPayload) graphql.Marshaler {
- fields := graphql.CollectFields(ec.OperationContext, sel, commitAsNeededPayloadImplementors)
-
- out := graphql.NewFieldSet(fields)
- var invalids uint32
- for i, field := range fields {
- switch field.Name {
- case "__typename":
- out.Values[i] = graphql.MarshalString("CommitAsNeededPayload")
- case "clientMutationId":
- out.Values[i] = ec._CommitAsNeededPayload_clientMutationId(ctx, field, obj)
- case "bug":
- out.Values[i] = ec._CommitAsNeededPayload_bug(ctx, field, obj)
- if out.Values[i] == graphql.Null {
- invalids++
- }
- default:
- panic("unknown field " + strconv.Quote(field.Name))
- }
- }
- out.Dispatch()
- if invalids > 0 {
- return graphql.Null
- }
- return out
-}
-
-var commitPayloadImplementors = []string{"CommitPayload"}
-
-func (ec *executionContext) _CommitPayload(ctx context.Context, sel ast.SelectionSet, obj *models.CommitPayload) graphql.Marshaler {
- fields := graphql.CollectFields(ec.OperationContext, sel, commitPayloadImplementors)
-
- out := graphql.NewFieldSet(fields)
- var invalids uint32
- for i, field := range fields {
- switch field.Name {
- case "__typename":
- out.Values[i] = graphql.MarshalString("CommitPayload")
- case "clientMutationId":
- out.Values[i] = ec._CommitPayload_clientMutationId(ctx, field, obj)
- case "bug":
- out.Values[i] = ec._CommitPayload_bug(ctx, field, obj)
- if out.Values[i] == graphql.Null {
- invalids++
- }
- default:
- panic("unknown field " + strconv.Quote(field.Name))
- }
- }
- out.Dispatch()
- if invalids > 0 {
- return graphql.Null
- }
- return out
-}
-
var createOperationImplementors = []string{"CreateOperation", "Operation", "Authored"}
func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.CreateOperation) graphql.Marshaler {
@@ -12172,16 +11711,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
invalids++
}
- case "commit":
- out.Values[i] = ec._Mutation_commit(ctx, field)
- if out.Values[i] == graphql.Null {
- invalids++
- }
- case "commitAsNeeded":
- out.Values[i] = ec._Mutation_commitAsNeeded(ctx, field)
- if out.Values[i] == graphql.Null {
- invalids++
- }
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@@ -12392,17 +11921,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("Query")
- case "defaultRepository":
- field := field
- out.Concurrently(i, func() (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._Query_defaultRepository(ctx, field)
- return res
- })
case "repository":
field := field
out.Concurrently(i, func() (res graphql.Marshaler) {
@@ -12440,6 +11958,17 @@ func (ec *executionContext) _Repository(ctx context.Context, sel ast.SelectionSe
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("Repository")
+ case "name":
+ field := field
+ out.Concurrently(i, func() (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._Repository_name(ctx, field, obj)
+ return res
+ })
case "allBugs":
field := field
out.Concurrently(i, func() (res graphql.Marshaler) {
@@ -13544,42 +13073,6 @@ func (ec *executionContext) marshalNCommentHistoryStep2ᚕgithubᚗcomᚋMichael
return ret
}
-func (ec *executionContext) unmarshalNCommitAsNeededInput2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitAsNeededInput(ctx context.Context, v interface{}) (models.CommitAsNeededInput, error) {
- return ec.unmarshalInputCommitAsNeededInput(ctx, v)
-}
-
-func (ec *executionContext) marshalNCommitAsNeededPayload2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitAsNeededPayload(ctx context.Context, sel ast.SelectionSet, v models.CommitAsNeededPayload) graphql.Marshaler {
- return ec._CommitAsNeededPayload(ctx, sel, &v)
-}
-
-func (ec *executionContext) marshalNCommitAsNeededPayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitAsNeededPayload(ctx context.Context, sel ast.SelectionSet, v *models.CommitAsNeededPayload) graphql.Marshaler {
- if v == nil {
- if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
- ec.Errorf(ctx, "must not be null")
- }
- return graphql.Null
- }
- return ec._CommitAsNeededPayload(ctx, sel, v)
-}
-
-func (ec *executionContext) unmarshalNCommitInput2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitInput(ctx context.Context, v interface{}) (models.CommitInput, error) {
- return ec.unmarshalInputCommitInput(ctx, v)
-}
-
-func (ec *executionContext) marshalNCommitPayload2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitPayload(ctx context.Context, sel ast.SelectionSet, v models.CommitPayload) graphql.Marshaler {
- return ec._CommitPayload(ctx, sel, &v)
-}
-
-func (ec *executionContext) marshalNCommitPayload2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋgraphqlᚋmodelsᚐCommitPayload(ctx context.Context, sel ast.SelectionSet, v *models.CommitPayload) graphql.Marshaler {
- if v == nil {
- if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
- ec.Errorf(ctx, "must not be null")
- }
- return graphql.Null
- }
- return ec._CommitPayload(ctx, sel, v)
-}
-
func (ec *executionContext) marshalNCreateOperation2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCreateOperation(ctx context.Context, sel ast.SelectionSet, v bug.CreateOperation) graphql.Marshaler {
return ec._CreateOperation(ctx, sel, &v)
}
@@ -25,7 +25,7 @@ func TestQueries(t *testing.T) {
query := `
query {
- defaultRepository {
+ repository {
allBugs(first: 2) {
pageInfo {
endCursor
@@ -162,7 +162,7 @@ func TestQueries(t *testing.T) {
}
var resp struct {
- DefaultRepository struct {
+ Repository struct {
AllBugs struct {
PageInfo models.PageInfo
Nodes []struct {
@@ -111,38 +111,6 @@ type CommentEdge struct {
Node *bug.Comment `json:"node"`
}
-type CommitAsNeededInput struct {
- // A unique identifier for the client performing the mutation.
- ClientMutationID *string `json:"clientMutationId"`
- // "The name of the repository. If not set, the default repository is used.
- RepoRef *string `json:"repoRef"`
- // The bug ID's prefix.
- Prefix string `json:"prefix"`
-}
-
-type CommitAsNeededPayload struct {
- // A unique identifier for the client performing the mutation.
- ClientMutationID *string `json:"clientMutationId"`
- // The affected bug.
- Bug BugWrapper `json:"bug"`
-}
-
-type CommitInput struct {
- // A unique identifier for the client performing the mutation.
- ClientMutationID *string `json:"clientMutationId"`
- // "The name of the repository. If not set, the default repository is used.
- RepoRef *string `json:"repoRef"`
- // The bug ID's prefix.
- Prefix string `json:"prefix"`
-}
-
-type CommitPayload struct {
- // A unique identifier for the client performing the mutation.
- ClientMutationID *string `json:"clientMutationId"`
- // The affected bug.
- Bug BugWrapper `json:"bug"`
-}
-
type IdentityConnection struct {
Edges []*IdentityEdge `json:"edges"`
Nodes []IdentityWrapper `json:"nodes"`
@@ -23,6 +23,15 @@ func (r mutationResolver) getRepo(ref *string) (*cache.RepoCache, error) {
return r.cache.DefaultRepo()
}
+func (r mutationResolver) getBug(repoRef *string, bugPrefix string) (*cache.BugCache, error) {
+ repo, err := r.getRepo(repoRef)
+ if err != nil {
+ return nil, err
+ }
+
+ return repo.ResolveBugPrefix(bugPrefix)
+}
+
func (r mutationResolver) NewBug(_ context.Context, input models.NewBugInput) (*models.NewBugPayload, error) {
repo, err := r.getRepo(input.RepoRef)
if err != nil {
@@ -42,17 +51,17 @@ func (r mutationResolver) NewBug(_ context.Context, input models.NewBugInput) (*
}
func (r mutationResolver) AddComment(_ context.Context, input models.AddCommentInput) (*models.AddCommentPayload, error) {
- repo, err := r.getRepo(input.RepoRef)
+ b, err := r.getBug(input.RepoRef, input.Prefix)
if err != nil {
return nil, err
}
- b, err := repo.ResolveBugPrefix(input.Prefix)
+ op, err := b.AddCommentWithFiles(input.Message, input.Files)
if err != nil {
return nil, err
}
- op, err := b.AddCommentWithFiles(input.Message, input.Files)
+ err = b.Commit()
if err != nil {
return nil, err
}
@@ -65,17 +74,17 @@ func (r mutationResolver) AddComment(_ context.Context, input models.AddCommentI
}
func (r mutationResolver) ChangeLabels(_ context.Context, input *models.ChangeLabelInput) (*models.ChangeLabelPayload, error) {
- repo, err := r.getRepo(input.RepoRef)
+ b, err := r.getBug(input.RepoRef, input.Prefix)
if err != nil {
return nil, err
}
- b, err := repo.ResolveBugPrefix(input.Prefix)
+ results, op, err := b.ChangeLabels(input.Added, input.Removed)
if err != nil {
return nil, err
}
- results, op, err := b.ChangeLabels(input.Added, input.Removed)
+ err = b.Commit()
if err != nil {
return nil, err
}
@@ -94,17 +103,17 @@ func (r mutationResolver) ChangeLabels(_ context.Context, input *models.ChangeLa
}
func (r mutationResolver) OpenBug(_ context.Context, input models.OpenBugInput) (*models.OpenBugPayload, error) {
- repo, err := r.getRepo(input.RepoRef)
+ b, err := r.getBug(input.RepoRef, input.Prefix)
if err != nil {
return nil, err
}
- b, err := repo.ResolveBugPrefix(input.Prefix)
+ op, err := b.Open()
if err != nil {
return nil, err
}
- op, err := b.Open()
+ err = b.Commit()
if err != nil {
return nil, err
}
@@ -117,17 +126,17 @@ func (r mutationResolver) OpenBug(_ context.Context, input models.OpenBugInput)
}
func (r mutationResolver) CloseBug(_ context.Context, input models.CloseBugInput) (*models.CloseBugPayload, error) {
- repo, err := r.getRepo(input.RepoRef)
+ b, err := r.getBug(input.RepoRef, input.Prefix)
if err != nil {
return nil, err
}
- b, err := repo.ResolveBugPrefix(input.Prefix)
+ op, err := b.Close()
if err != nil {
return nil, err
}
- op, err := b.Close()
+ err = b.Commit()
if err != nil {
return nil, err
}
@@ -140,12 +149,7 @@ func (r mutationResolver) CloseBug(_ context.Context, input models.CloseBugInput
}
func (r mutationResolver) SetTitle(_ context.Context, input models.SetTitleInput) (*models.SetTitlePayload, error) {
- repo, err := r.getRepo(input.RepoRef)
- if err != nil {
- return nil, err
- }
-
- b, err := repo.ResolveBugPrefix(input.Prefix)
+ b, err := r.getBug(input.RepoRef, input.Prefix)
if err != nil {
return nil, err
}
@@ -155,53 +159,14 @@ func (r mutationResolver) SetTitle(_ context.Context, input models.SetTitleInput
return nil, err
}
- return &models.SetTitlePayload{
- ClientMutationID: input.ClientMutationID,
- Bug: models.NewLoadedBug(b.Snapshot()),
- Operation: op,
- }, nil
-}
-
-func (r mutationResolver) Commit(_ context.Context, input models.CommitInput) (*models.CommitPayload, error) {
- repo, err := r.getRepo(input.RepoRef)
- if err != nil {
- return nil, err
- }
-
- b, err := repo.ResolveBugPrefix(input.Prefix)
- if err != nil {
- return nil, err
- }
-
err = b.Commit()
if err != nil {
return nil, err
}
- return &models.CommitPayload{
- ClientMutationID: input.ClientMutationID,
- Bug: models.NewLoadedBug(b.Snapshot()),
- }, nil
-}
-
-func (r mutationResolver) CommitAsNeeded(_ context.Context, input models.CommitAsNeededInput) (*models.CommitAsNeededPayload, error) {
- repo, err := r.getRepo(input.RepoRef)
- if err != nil {
- return nil, err
- }
-
- b, err := repo.ResolveBugPrefix(input.Prefix)
- if err != nil {
- return nil, err
- }
-
- err = b.CommitAsNeeded()
- if err != nil {
- return nil, err
- }
-
- return &models.CommitAsNeededPayload{
+ return &models.SetTitlePayload{
ClientMutationID: input.ClientMutationID,
Bug: models.NewLoadedBug(b.Snapshot()),
+ Operation: op,
}, nil
}
@@ -27,8 +27,15 @@ func (r rootQueryResolver) DefaultRepository(_ context.Context) (*models.Reposit
}, nil
}
-func (r rootQueryResolver) Repository(_ context.Context, ref string) (*models.Repository, error) {
- repo, err := r.cache.ResolveRepo(ref)
+func (r rootQueryResolver) Repository(_ context.Context, ref *string) (*models.Repository, error) {
+ var repo *cache.RepoCache
+ var err error
+
+ if ref == nil {
+ repo, err = r.cache.DefaultRepo()
+ } else {
+ repo, err = r.cache.ResolveRepo(*ref)
+ }
if err != nil {
return nil, err
@@ -15,6 +15,11 @@ var _ graph.RepositoryResolver = &repoResolver{}
type repoResolver struct{}
+func (repoResolver) Name(_ context.Context, obj *models.Repository) (*string, error) {
+ name := obj.Repo.Name()
+ return &name, nil
+}
+
func (repoResolver) AllBugs(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, queryStr *string) (*models.BugConnection, error) {
input := models.ConnectionInput{
Before: before,
@@ -153,7 +158,7 @@ func (repoResolver) UserIdentity(_ context.Context, obj *models.Repository) (mod
return models.NewLazyIdentity(obj.Repo, excerpt), nil
}
-func (resolver repoResolver) ValidLabels(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.LabelConnection, error) {
+func (repoResolver) ValidLabels(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.LabelConnection, error) {
input := models.ConnectionInput{
Before: before,
After: after,
@@ -136,35 +136,3 @@ type SetTitlePayload {
"""The resulting operation"""
operation: SetTitleOperation!
}
-
-input CommitInput {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """"The name of the repository. If not set, the default repository is used."""
- repoRef: String
- """The bug ID's prefix."""
- prefix: String!
-}
-
-type CommitPayload {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """The affected bug."""
- bug: Bug!
-}
-
-input CommitAsNeededInput {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """"The name of the repository. If not set, the default repository is used."""
- repoRef: String
- """The bug ID's prefix."""
- prefix: String!
-}
-
-type CommitAsNeededPayload {
- """A unique identifier for the client performing the mutation."""
- clientMutationId: String
- """The affected bug."""
- bug: Bug!
-}
@@ -1,5 +1,8 @@
type Repository {
+ """The name of the repository"""
+ name: String
+
"""All the bugs"""
allBugs(
"""Returns the elements in the list that come after the specified cursor."""
@@ -10,7 +13,7 @@ type Repository {
first: Int
"""Returns the last _n_ elements from the list."""
last: Int
- """A query to select and order bugs"""
+ """A query to select and order bugs."""
query: String
): BugConnection!
@@ -1,10 +1,6 @@
type Query {
- """The default unnamend repository."""
- defaultRepository: Repository
- """Access a repository by reference/name."""
- repository(ref: String!): Repository
-
- #TODO: connection for all repositories
+ """Access a repository by reference/name. If no ref is given, the default repository is returned if any."""
+ repository(ref: String): Repository
}
type Mutation {
@@ -20,8 +16,4 @@ type Mutation {
closeBug(input: CloseBugInput!): CloseBugPayload!
"""Change a bug's title"""
setTitle(input: SetTitleInput!): SetTitlePayload!
- """Commit write the pending operations into storage. This mutation fail if nothing is pending"""
- commit(input: CommitInput!): CommitPayload!
- """Commit write the pending operations into storage. This mutation succed if nothing is pending"""
- commitAsNeeded(input: CommitAsNeededInput!): CommitAsNeededPayload!
}
@@ -1,4 +0,0 @@
-{
- "extends": ["react-app", "plugin:prettier/recommended"],
- "ignorePatterns": ["src/fragmentTypes.js"]
-}
@@ -0,0 +1,37 @@
+module.exports = {
+ extends: [
+ 'react-app',
+ 'prettier/@typescript-eslint',
+ 'plugin:prettier/recommended',
+ ],
+ plugins: ['graphql'],
+ rules: {
+ 'graphql/template-strings': [
+ 'error',
+ {
+ schemaJson: require('./src/schema.json'),
+ env: 'literal',
+ },
+ ],
+ 'import/order': [
+ 'error',
+ {
+ alphabetize: { order: 'asc' },
+ pathGroups: [
+ {
+ pattern: '@material-ui/**',
+ group: 'external',
+ position: 'after',
+ },
+ {
+ pattern: '*.generated',
+ group: 'sibling',
+ position: 'after',
+ },
+ ],
+ groups: [['builtin', 'external'], 'parent', ['sibling', 'index']],
+ 'newlines-between': 'always',
+ },
+ ],
+ },
+};
@@ -5,7 +5,9 @@ install:
npm install
test:
+ npm run generate
npm run lint
+ CI=true npm run test
build:
npm run build
@@ -7,10 +7,11 @@
2. Run the GraphQL backend on the port 3001
- `./git-bug webui -p 3001`
3. Run the hot-reloadable development WebUI
+
- run `npm start` in the **webui** directory
-
+
The development version of the WebUI is configured to query the backend on the port 3001. You can now live edit the js code and use the normal backend.
## Bundle the web UI
-Once the webUI is good enough for a new release, run `make pack-webui` from the root directory to bundle the compiled js into the go binary.
+Once the webUI is good enough for a new release, run `make pack-webui` from the root directory to bundle the compiled js into the go binary.
@@ -1,8 +1,32 @@
schema: '../graphql/schema/*.graphql'
overwrite: true
+documents: src/**/*.graphql
generates:
- ./src/fragmentTypes.js:
+ ./src/fragmentTypes.ts:
plugins:
- - fragment-matcher
+ - fragment-matcher
config:
module: es2015
+ ./src/gqlTypes.ts:
+ plugins:
+ - typescript
+ ./src/schema.json:
+ plugins:
+ - introspection
+ ./src/:
+ plugins:
+ - add: '/* eslint-disable @typescript-eslint/no-unused-vars, import/order */'
+ - typescript-operations
+ - typescript-react-apollo
+ preset: near-operation-file
+ presetConfig:
+ extension: .generated.tsx
+ baseTypesPath: gqlTypes.ts
+ config:
+ withComponent: false
+ withHOC: false
+ withHooks: true
+
+hooks:
+ afterAllFileWrite:
+ - prettier --write
@@ -114,6 +114,24 @@
"@apollographql/graphql-language-service-types": "^2.0.0"
}
},
+ "@ardatan/graphql-tools": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@ardatan/graphql-tools/-/graphql-tools-4.1.0.tgz",
+ "integrity": "sha512-0b+KH5RZN9vCMpEjxrwFwZ7v3K6QDjs1EH+R6eRrgKMR2X274JWqYraHKLWE1uJ8iwrkRaOYfCV12jLVuvWS+A==",
+ "dev": true,
+ "requires": {
+ "apollo-link": "^1.2.3",
+ "apollo-utilities": "^1.0.1",
+ "deprecated-decorator": "^0.1.6",
+ "iterall": "^1.1.3",
+ "uuid": "^3.1.0"
+ }
+ },
+ "@arrows/composition": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@arrows/composition/-/composition-1.2.2.tgz",
+ "integrity": "sha512-9fh1yHwrx32lundiB3SlZ/VwuStPB4QakPsSLrGJFH6rCXvdrd060ivAZ7/2vlqPnEjBkPRRXOcG1YOu19p2GQ=="
+ },
"@babel/code-frame": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
@@ -123,36 +141,30 @@
}
},
"@babel/compat-data": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.1.tgz",
- "integrity": "sha512-Z+6ZOXvyOWYxJ50BwxzdhRnRsGST8Y3jaZgxYig575lTjVSs3KtJnmESwZegg6e2Dn0td1eDhoWlp1wI4BTCPw==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.4.tgz",
+ "integrity": "sha512-lHLhlsvFjJAqNU71b7k6Vv9ewjmTXKvqaMv7n0G1etdCabWLw3nEYE8mmgoVOxMIFE07xOvo7H7XBASirX6Rrg==",
"requires": {
- "browserslist": "^4.8.2",
+ "browserslist": "^4.8.5",
"invariant": "^2.2.4",
"semver": "^5.5.0"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
- }
}
},
"@babel/core": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz",
- "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==",
- "requires": {
- "@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.4",
- "@babel/helpers": "^7.7.4",
- "@babel/parser": "^7.7.4",
- "@babel/template": "^7.7.4",
- "@babel/traverse": "^7.7.4",
- "@babel/types": "^7.7.4",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz",
+ "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.8.4",
+ "@babel/helpers": "^7.8.4",
+ "@babel/parser": "^7.8.4",
+ "@babel/template": "^7.8.3",
+ "@babel/traverse": "^7.8.4",
+ "@babel/types": "^7.8.3",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
"json5": "^2.1.0",
"lodash": "^4.17.13",
"resolve": "^1.3.2",
@@ -160,22 +172,50 @@
"source-map": "^0.5.0"
},
"dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ "@babel/parser": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
+ "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw=="
+ },
+ "@babel/traverse": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
+ "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.8.4",
+ "@babel/helper-function-name": "^7.8.3",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/parser": "^7.8.4",
+ "@babel/types": "^7.8.3",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
}
}
},
"@babel/generator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz",
- "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
+ "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
"requires": {
"@babel/types": "^7.8.3",
"jsesc": "^2.5.1",
"lodash": "^4.17.13",
"source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
}
},
"@babel/helper-annotate-as-pure": {
@@ -215,22 +255,15 @@
}
},
"@babel/helper-compilation-targets": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.3.tgz",
- "integrity": "sha512-JLylPCsFjhLN+6uBSSh3iYdxKdeO9MNmoY96PE/99d8kyBFaXLORtAVhqN6iHa+wtPeqxKLghDOZry0+Aiw9Tw==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz",
+ "integrity": "sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg==",
"requires": {
- "@babel/compat-data": "^7.8.1",
- "browserslist": "^4.8.2",
+ "@babel/compat-data": "^7.8.4",
+ "browserslist": "^4.8.5",
"invariant": "^2.2.4",
- "levenary": "^1.1.0",
+ "levenary": "^1.1.1",
"semver": "^5.5.0"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
- }
}
},
"@babel/helper-create-class-features-plugin": {
@@ -402,13 +435,36 @@
}
},
"@babel/helpers": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz",
- "integrity": "sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz",
+ "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==",
"requires": {
"@babel/template": "^7.8.3",
- "@babel/traverse": "^7.8.3",
+ "@babel/traverse": "^7.8.4",
"@babel/types": "^7.8.3"
+ },
+ "dependencies": {
+ "@babel/parser": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
+ "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw=="
+ },
+ "@babel/traverse": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
+ "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.8.4",
+ "@babel/helper-function-name": "^7.8.3",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/parser": "^7.8.4",
+ "@babel/types": "^7.8.3",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ }
}
},
"@babel/highlight": {
@@ -419,6 +475,18 @@
"chalk": "^2.0.0",
"esutils": "^2.0.2",
"js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ }
}
},
"@babel/parser": {
@@ -437,22 +505,22 @@
}
},
"@babel/plugin-proposal-class-properties": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.4.tgz",
- "integrity": "sha512-EcuXeV4Hv1X3+Q1TsuOmyyxeTRiSqurGJ26+I/FW1WbymmRRapVORm6x1Zl3iDIHyRxEs+VXWp6qnlcfcJSbbw==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz",
+ "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==",
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.7.4",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-create-class-features-plugin": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3"
}
},
"@babel/plugin-proposal-decorators": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.7.4.tgz",
- "integrity": "sha512-GftcVDcLCwVdzKmwOBDjATd548+IE+mBo7ttgatqNDR7VG7GqIuZPtRWlMLHbhTXhcnFZiGER8iIYl1n/imtsg==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz",
+ "integrity": "sha512-e3RvdvS4qPJVTe288DlXjwKflpfy1hr0j5dz5WpIYYeP7vQZg2WfAEIp8k5/Lwis/m5REXEteIz6rrcDtXXG7w==",
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.7.4",
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-decorators": "^7.7.4"
+ "@babel/helper-create-class-features-plugin": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-decorators": "^7.8.3"
}
},
"@babel/plugin-proposal-dynamic-import": {
@@ -483,12 +551,12 @@
}
},
"@babel/plugin-proposal-numeric-separator": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.7.4.tgz",
- "integrity": "sha512-CG605v7lLpVgVldSY6kxsN9ui1DxFOyepBfuX2AzU2TNriMAYApoU55mrGw9Jr4TlrTzPCG10CL8YXyi+E/iPw==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz",
+ "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-numeric-separator": "^7.7.4"
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3"
}
},
"@babel/plugin-proposal-object-rest-spread": {
@@ -535,6 +603,15 @@
"@babel/helper-plugin-utils": "^7.8.0"
}
},
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz",
+ "integrity": "sha512-UcAyQWg2bAN647Q+O811tG9MrJ38Z10jjhQdKNAL8fsyPzE3cCN/uT+f55cFVY4aGO4jqJAvmqsuY3GQDwAoXg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
"@babel/plugin-syntax-decorators": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.8.3.tgz",
@@ -724,18 +801,18 @@
}
},
"@babel/plugin-transform-flow-strip-types": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.7.4.tgz",
- "integrity": "sha512-w9dRNlHY5ElNimyMYy0oQowvQpwt/PRHI0QS98ZJCTZU2bvSnKXo5zEiD5u76FBPigTm8TkqzmnUTg16T7qbkA==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz",
+ "integrity": "sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-flow": "^7.7.4"
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-flow": "^7.8.3"
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.3.tgz",
- "integrity": "sha512-ZjXznLNTxhpf4Q5q3x1NsngzGA38t9naWH8Gt+0qYZEJAcvPI9waSStSh56u19Ofjr7QmD0wUsQ8hw8s/p1VnA==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz",
+ "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==",
"requires": {
"@babel/helper-plugin-utils": "^7.8.3"
}
@@ -832,9 +909,9 @@
}
},
"@babel/plugin-transform-parameters": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.3.tgz",
- "integrity": "sha512-/pqngtGb54JwMBZ6S/D3XYylQDFtGjWrnoCF4gXZOUpFV/ujbxnoNGNvDGu6doFWRPBveE72qTx/RRU44j5I/Q==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz",
+ "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==",
"requires": {
"@babel/helper-call-delegate": "^7.8.3",
"@babel/helper-get-function-arity": "^7.8.3",
@@ -911,21 +988,14 @@
}
},
"@babel/plugin-transform-runtime": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.4.tgz",
- "integrity": "sha512-O8kSkS5fP74Ad/8pfsCMGa8sBRdLxYoSReaARRNSz3FbFQj3z/QUvoUmJ28gn9BO93YfnXc3j+Xyaqe8cKDNBQ==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz",
+ "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==",
"requires": {
- "@babel/helper-module-imports": "^7.7.4",
- "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-module-imports": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3",
"resolve": "^1.8.1",
"semver": "^5.5.1"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
- }
}
},
"@babel/plugin-transform-shorthand-properties": {
@@ -963,9 +1033,9 @@
}
},
"@babel/plugin-transform-typeof-symbol": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.3.tgz",
- "integrity": "sha512-3TrkKd4LPqm4jHs6nPtSDI/SV9Cm5PRJkHLUgTcqRQQTMAZ44ZaAdDZJtvWFSaRcvT0a1rTmJ5ZA5tDKjleF3g==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz",
+ "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==",
"requires": {
"@babel/helper-plugin-utils": "^7.8.3"
}
@@ -990,12 +1060,12 @@
}
},
"@babel/preset-env": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.3.tgz",
- "integrity": "sha512-Rs4RPL2KjSLSE2mWAx5/iCH+GC1ikKdxPrhnRS6PfFVaiZeom22VFKN4X8ZthyN61kAaR05tfXTbCvatl9WIQg==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.4.tgz",
+ "integrity": "sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w==",
"requires": {
- "@babel/compat-data": "^7.8.0",
- "@babel/helper-compilation-targets": "^7.8.3",
+ "@babel/compat-data": "^7.8.4",
+ "@babel/helper-compilation-targets": "^7.8.4",
"@babel/helper-module-imports": "^7.8.3",
"@babel/helper-plugin-utils": "^7.8.3",
"@babel/plugin-proposal-async-generator-functions": "^7.8.3",
@@ -1024,7 +1094,7 @@
"@babel/plugin-transform-dotall-regex": "^7.8.3",
"@babel/plugin-transform-duplicate-keys": "^7.8.3",
"@babel/plugin-transform-exponentiation-operator": "^7.8.3",
- "@babel/plugin-transform-for-of": "^7.8.3",
+ "@babel/plugin-transform-for-of": "^7.8.4",
"@babel/plugin-transform-function-name": "^7.8.3",
"@babel/plugin-transform-literals": "^7.8.3",
"@babel/plugin-transform-member-expression-literals": "^7.8.3",
@@ -1035,7 +1105,7 @@
"@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3",
"@babel/plugin-transform-new-target": "^7.8.3",
"@babel/plugin-transform-object-super": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.8.4",
"@babel/plugin-transform-property-literals": "^7.8.3",
"@babel/plugin-transform-regenerator": "^7.8.3",
"@babel/plugin-transform-reserved-words": "^7.8.3",
@@ -1043,21 +1113,14 @@
"@babel/plugin-transform-spread": "^7.8.3",
"@babel/plugin-transform-sticky-regex": "^7.8.3",
"@babel/plugin-transform-template-literals": "^7.8.3",
- "@babel/plugin-transform-typeof-symbol": "^7.8.3",
+ "@babel/plugin-transform-typeof-symbol": "^7.8.4",
"@babel/plugin-transform-unicode-regex": "^7.8.3",
"@babel/types": "^7.8.3",
- "browserslist": "^4.8.2",
+ "browserslist": "^4.8.5",
"core-js-compat": "^3.6.2",
"invariant": "^2.2.2",
- "levenary": "^1.1.0",
+ "levenary": "^1.1.1",
"semver": "^5.5.0"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
- }
}
},
"@babel/preset-react": {
@@ -1073,12 +1136,12 @@
}
},
"@babel/preset-typescript": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.7.4.tgz",
- "integrity": "sha512-rqrjxfdiHPsnuPur0jKrIIGQCIgoTWMTjlbWE69G4QJ6TIOVnnRnIJhUxNTL/VwDmEAVX08Tq3B1nirer5341w==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz",
+ "integrity": "sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-transform-typescript": "^7.7.4"
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-transform-typescript": "^7.8.3"
}
},
"@babel/runtime": {
@@ -1090,9 +1153,9 @@
}
},
"@babel/runtime-corejs3": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.8.3.tgz",
- "integrity": "sha512-lrIU4aVbmlM/wQPzhEvzvNJskKyYptuXb0fGC0lTQTupTOYtR2Vqbu6/jf8vTr4M8Wt1nIzxVrSvPI5qESa/xA==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.8.4.tgz",
+ "integrity": "sha512-+wpLqy5+fbQhvbllvlJEVRIpYj+COUWnnsm+I4jZlA8Lo7/MJmBhGTCHyk1/RWfOqBRJ2MbadddG6QltTKTlrg==",
"requires": {
"core-js-pure": "^3.0.0",
"regenerator-runtime": "^0.13.2"
@@ -1170,24 +1233,55 @@
"tslib": "^1"
}
},
+ "@graphql-codegen/add": {
+ "version": "1.12.2-alpha-ea7264f9.15",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-1.12.2-alpha-ea7264f9.15.tgz",
+ "integrity": "sha512-XfOZH2lIR3qw/mHqXThb32EA7NR37nPJpzuNtx1McGTy0sEEd5PVTLP4u89cgvMXfx18cMMM7ZWAnz2T7XCCkQ==",
+ "dev": true,
+ "requires": {
+ "@graphql-codegen/plugin-helpers": "1.12.2-alpha-ea7264f9.15+ea7264f9",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "@graphql-codegen/plugin-helpers": {
+ "version": "1.12.2-alpha-ea7264f9.15",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.12.2-alpha-ea7264f9.15.tgz",
+ "integrity": "sha512-EgRHQVFswVQUevMEtsrsA45JmTWj3UAUK8laMyDqbQQuOqlTOgpqdceTLYWWCpyfybaEaagw+rWpkwPXyUjWYQ==",
+ "dev": true,
+ "requires": {
+ "@graphql-toolkit/common": "0.9.7",
+ "camel-case": "4.1.1",
+ "common-tags": "1.8.0",
+ "constant-case": "3.0.3",
+ "import-from": "3.0.0",
+ "lower-case": "2.0.1",
+ "param-case": "3.0.3",
+ "pascal-case": "3.1.1",
+ "tslib": "1.10.0",
+ "upper-case": "2.0.1"
+ }
+ }
+ }
+ },
"@graphql-codegen/cli": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.11.2.tgz",
- "integrity": "sha512-ox0vqUq+BWngD+UBCpzXuLrOBTPQZza7IGPxKSF3Z7lOPim+NX75HL5sO/58xU8I/5lEjaZpHx3hvSZdiGu4kg==",
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.12.1.tgz",
+ "integrity": "sha512-ObbuUaBC48i8glFXcBNo9oBMfv9HZ4JQtP52UX6Ppv/KUOISQWCYvC1YmtWIkuVYRz65Ds2kHpNS9YknVf7eEQ==",
"dev": true,
"requires": {
- "@babel/parser": "7.7.7",
- "@graphql-codegen/core": "1.11.2",
- "@graphql-codegen/plugin-helpers": "1.11.2",
- "@graphql-toolkit/apollo-engine-loader": "0.9.0",
- "@graphql-toolkit/code-file-loader": "0.9.0",
- "@graphql-toolkit/core": "0.9.0",
- "@graphql-toolkit/git-loader": "0.9.0",
- "@graphql-toolkit/github-loader": "0.9.0",
- "@graphql-toolkit/graphql-file-loader": "0.9.0",
- "@graphql-toolkit/json-file-loader": "0.9.0",
- "@graphql-toolkit/prisma-loader": "0.9.0",
- "@graphql-toolkit/url-loader": "0.9.0",
+ "@babel/parser": "7.8.3",
+ "@graphql-codegen/core": "1.12.1",
+ "@graphql-codegen/plugin-helpers": "1.12.1",
+ "@graphql-toolkit/apollo-engine-loader": "0.9.7",
+ "@graphql-toolkit/code-file-loader": "0.9.7",
+ "@graphql-toolkit/common": "0.9.7",
+ "@graphql-toolkit/core": "0.9.7",
+ "@graphql-toolkit/git-loader": "0.9.7",
+ "@graphql-toolkit/github-loader": "0.9.7",
+ "@graphql-toolkit/graphql-file-loader": "0.9.7",
+ "@graphql-toolkit/json-file-loader": "0.9.7",
+ "@graphql-toolkit/prisma-loader": "0.9.7",
+ "@graphql-toolkit/url-loader": "0.9.7",
"@types/debounce": "1.2.0",
"@types/is-glob": "4.0.1",
"@types/mkdirp": "0.5.2",
@@ -1202,21 +1296,20 @@
"debounce": "1.2.0",
"detect-indent": "6.0.0",
"glob": "7.1.6",
- "graphql-config": "3.0.0-alpha.16",
+ "graphql-config": "3.0.0-alpha.18",
"graphql-import": "0.7.1",
"graphql-tag-pluck": "0.8.7",
"graphql-tools": "4.0.6",
"indent-string": "4.0.0",
- "inquirer": "7.0.3",
+ "inquirer": "7.0.4",
"is-glob": "4.0.1",
- "is-valid-path": "0.1.1",
"json-to-pretty-yaml": "1.2.2",
"listr": "0.14.3",
"listr-update-renderer": "0.5.0",
"log-symbols": "3.0.0",
"log-update": "3.3.0",
"lower-case": "2.0.1",
- "mkdirp": "0.5.1",
+ "mkdirp": "1.0.3",
"pascal-case": "3.1.1",
"prettier": "1.19.1",
"request": "2.88.0",
@@ -1224,616 +1317,337 @@
"tslib": "1.10.0",
"upper-case": "2.0.1",
"valid-url": "1.0.9"
+ }
+ },
+ "@graphql-codegen/core": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.12.1.tgz",
+ "integrity": "sha512-tlGVaqbJ6sWCC28wrNaLGigw7SXPti1lEse0In5+sePZRjbNof8AbNQIICBOgaNxvt9TVfZ80VVM/pCFNCU2vA==",
+ "dev": true,
+ "requires": {
+ "@graphql-codegen/plugin-helpers": "1.12.1",
+ "@graphql-toolkit/common": "0.9.7",
+ "@graphql-toolkit/schema-merging": "0.9.7",
+ "tslib": "1.10.0"
+ }
+ },
+ "@graphql-codegen/fragment-matcher": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/fragment-matcher/-/fragment-matcher-1.12.1.tgz",
+ "integrity": "sha512-WDg1aNiz3/+ksCJ8QEOX6dk7Ki6o0jurdp/Itc2ZjVKbeLypH7omOFonDoM7mi9uq0uDsXk9MioW7wsoIVfHCA==",
+ "dev": true,
+ "requires": {
+ "@graphql-codegen/plugin-helpers": "1.12.1"
+ }
+ },
+ "@graphql-codegen/introspection": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/introspection/-/introspection-1.12.2.tgz",
+ "integrity": "sha512-YMQIn1R2CxYZLkxkW6fUxqfTBr2WC3Cimp6/0oEcSyLA/W1scVuDw/IUeU5Iu4CEmz8IaqPSjSMEN+8l95wKlA==",
+ "dev": true,
+ "requires": {
+ "@graphql-codegen/plugin-helpers": "1.12.2",
+ "tslib": "1.10.0"
},
"dependencies": {
- "@babel/parser": {
- "version": "7.7.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
- "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw==",
- "dev": true
- },
- "ansi-styles": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
- "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
- "dev": true,
- "requires": {
- "@types/color-name": "^1.1.1",
- "color-convert": "^2.0.1"
- }
- },
- "anymatch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
- "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
- "dev": true,
- "requires": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- }
- },
- "binary-extensions": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
- "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
- "dev": true
- },
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "requires": {
- "fill-range": "^7.0.1"
- }
- },
- "camel-case": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz",
- "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==",
- "dev": true,
- "requires": {
- "pascal-case": "^3.1.1",
- "tslib": "^1.10.0"
- }
- },
- "chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "chokidar": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
- "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==",
- "dev": true,
- "requires": {
- "anymatch": "~3.1.1",
- "braces": "~3.0.2",
- "fsevents": "~2.1.2",
- "glob-parent": "~5.1.0",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.3.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "commander": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz",
- "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==",
- "dev": true
- },
- "cosmiconfig": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
- "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
- "dev": true,
- "requires": {
- "@types/parse-json": "^4.0.0",
- "import-fresh": "^3.1.0",
- "parse-json": "^5.0.0",
- "path-type": "^4.0.0",
- "yaml": "^1.7.2"
- }
- },
- "fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "requires": {
- "to-regex-range": "^5.0.1"
- }
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
- },
- "import-fresh": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
- "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+ "@graphql-codegen/plugin-helpers": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.12.2.tgz",
+ "integrity": "sha512-N294rqdBh+mCi4HWHbhPV9wE0XLCVKx524pYL4yp8qWiSdAs3Iz9+q9C9QNsLBvHypZdqml44M8kBMG41A9I/Q==",
"dev": true,
"requires": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
+ "@graphql-toolkit/common": "0.9.7",
+ "camel-case": "4.1.1",
+ "common-tags": "1.8.0",
+ "constant-case": "3.0.3",
+ "import-from": "3.0.0",
+ "lower-case": "2.0.1",
+ "param-case": "3.0.3",
+ "pascal-case": "3.1.1",
+ "tslib": "1.10.0",
+ "upper-case": "2.0.1"
}
- },
- "is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ }
+ }
+ },
+ "@graphql-codegen/near-operation-file-preset": {
+ "version": "1.12.2-alpha-ea7264f9.15",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/near-operation-file-preset/-/near-operation-file-preset-1.12.2-alpha-ea7264f9.15.tgz",
+ "integrity": "sha512-jbj7+2FlHRLpqN3e44EZ88n2juImhMuXzv6Mlun4CEVkxC8zW6MYkptaeAxb+iCn2r2nO3vXNrNEPs/1czF97w==",
+ "dev": true,
+ "requires": {
+ "@graphql-codegen/add": "1.12.2-alpha-ea7264f9.15+ea7264f9",
+ "@graphql-codegen/plugin-helpers": "1.12.2-alpha-ea7264f9.15+ea7264f9",
+ "@graphql-codegen/visitor-plugin-common": "1.12.2-alpha-ea7264f9.15+ea7264f9",
+ "tslib": "1.10.0"
+ },
+ "dependencies": {
+ "@graphql-codegen/plugin-helpers": {
+ "version": "1.12.2-alpha-ea7264f9.15",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.12.2-alpha-ea7264f9.15.tgz",
+ "integrity": "sha512-EgRHQVFswVQUevMEtsrsA45JmTWj3UAUK8laMyDqbQQuOqlTOgpqdceTLYWWCpyfybaEaagw+rWpkwPXyUjWYQ==",
"dev": true,
"requires": {
- "binary-extensions": "^2.0.0"
- }
- },
- "is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
- },
- "lower-case": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz",
- "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==",
+ "@graphql-toolkit/common": "0.9.7",
+ "camel-case": "4.1.1",
+ "common-tags": "1.8.0",
+ "constant-case": "3.0.3",
+ "import-from": "3.0.0",
+ "lower-case": "2.0.1",
+ "param-case": "3.0.3",
+ "pascal-case": "3.1.1",
+ "tslib": "1.10.0",
+ "upper-case": "2.0.1"
+ }
+ },
+ "@graphql-codegen/visitor-plugin-common": {
+ "version": "1.12.2-alpha-ea7264f9.15",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.12.2-alpha-ea7264f9.15.tgz",
+ "integrity": "sha512-Y+4b5ArGOcXtGZ7gCLKhfOfiElH36uNSYs/8y0+9bxbjV1OuGfunnluysvpDSqIqatyVXviJh+P832VjO5Cviw==",
"dev": true,
"requires": {
- "tslib": "^1.10.0"
- }
- },
- "normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true
- },
- "parse-json": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
- "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1",
- "lines-and-columns": "^1.1.6"
- }
- },
- "path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true
- },
- "readdirp": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz",
- "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==",
- "dev": true,
- "requires": {
- "picomatch": "^2.0.7"
- }
- },
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true
- },
- "supports-color": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
- "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- },
- "to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "requires": {
- "is-number": "^7.0.0"
- }
- },
- "upper-case": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.1.tgz",
- "integrity": "sha512-laAsbea9SY5osxrv7S99vH9xAaJKrw5Qpdh4ENRLcaxipjKsiaBwiAsxfa8X5mObKNTQPsupSq0J/VIxsSJe3A==",
- "dev": true,
- "requires": {
- "tslib": "^1.10.0"
+ "@graphql-codegen/plugin-helpers": "1.12.2-alpha-ea7264f9.15+ea7264f9",
+ "@graphql-toolkit/relay-operation-optimizer": "0.9.7",
+ "auto-bind": "4.0.0",
+ "dependency-graph": "0.8.1",
+ "graphql-tag": "2.10.1",
+ "pascal-case": "3.1.1",
+ "tslib": "1.10.0"
}
}
}
},
- "@graphql-codegen/core": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.11.2.tgz",
- "integrity": "sha512-ZEHbCtivUQXXPkTd+vrb6sSmCss45Z7YjeyC1mf0kStcEeAKygs6XM2k7F5a9wUQn3mxnyJRAnqfqNIdoagoUg==",
+ "@graphql-codegen/plugin-helpers": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.12.1.tgz",
+ "integrity": "sha512-mrc+trorCTuJYeD0gJLXO7xxabAyOmwXvDkPTxecWNfw5oJIloKsIorWkK00ZFbPHjorzJlOgON8vgXljREzKA==",
+ "dev": true,
+ "requires": {
+ "@graphql-toolkit/common": "0.9.7",
+ "camel-case": "4.1.1",
+ "common-tags": "1.8.0",
+ "constant-case": "3.0.3",
+ "import-from": "3.0.0",
+ "lower-case": "2.0.1",
+ "param-case": "3.0.3",
+ "pascal-case": "3.1.1",
+ "tslib": "1.10.0",
+ "upper-case": "2.0.1"
+ }
+ },
+ "@graphql-codegen/typescript": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-1.12.1.tgz",
+ "integrity": "sha512-j2iQrxSIMxF6MlzJ5OvnawRyewfEHlC21It+Z6Md2z7yJK5T2bYLs4jd0RkzDGVezodnpd0TzV/Yv+jGxdMjSQ==",
"dev": true,
"requires": {
- "@graphql-codegen/plugin-helpers": "1.11.2",
- "@graphql-toolkit/common": "0.9.0",
- "@graphql-toolkit/schema-merging": "0.9.0",
+ "@graphql-codegen/plugin-helpers": "1.12.1",
+ "@graphql-codegen/visitor-plugin-common": "1.12.1",
+ "auto-bind": "4.0.0",
"tslib": "1.10.0"
}
},
- "@graphql-codegen/fragment-matcher": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@graphql-codegen/fragment-matcher/-/fragment-matcher-1.11.2.tgz",
- "integrity": "sha512-pLXTwf1dN+CmeZb+5fIjVq41ygPFgQ4rnj6S5N/efHY8AYuGROS58+YXFjU4Nx0eMFj18ymsrrTBWEr2Xug7ZQ==",
+ "@graphql-codegen/typescript-operations": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-1.12.1.tgz",
+ "integrity": "sha512-lGF5wzi5Rndca4YoQCTczRamBrKkieuLIMW3/WT+t3s9wwTkC802HAuNLmUW9CUO+lcArrXV23qpyi9hElKZAA==",
"dev": true,
"requires": {
- "@graphql-codegen/plugin-helpers": "1.11.2"
+ "@graphql-codegen/plugin-helpers": "1.12.1",
+ "@graphql-codegen/typescript": "1.12.1",
+ "@graphql-codegen/visitor-plugin-common": "1.12.1",
+ "auto-bind": "4.0.0",
+ "tslib": "1.10.0"
}
},
- "@graphql-codegen/plugin-helpers": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.11.2.tgz",
- "integrity": "sha512-jggDX2ykLU8EOdP8bpArkMtPTvJ72XYWa44f0GFIdhfSfZtK8PO/gMaSY8iPbV5DqD4HnYvMc3mXCoJTAPT8VQ==",
+ "@graphql-codegen/typescript-react-apollo": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-react-apollo/-/typescript-react-apollo-1.12.1.tgz",
+ "integrity": "sha512-uy6R2M6EvLXu9BWA9untZBpE+64OUnC2zjV0TO2cK6tz1Ktut9pyC7F4BNGoFHfTvmx80dxtKfwbqdmP48mddQ==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
+ "@graphql-codegen/plugin-helpers": "1.12.1",
+ "@graphql-codegen/visitor-plugin-common": "1.12.1",
+ "auto-bind": "4.0.0",
"camel-case": "4.1.1",
- "common-tags": "1.8.0",
- "constant-case": "3.0.3",
- "import-from": "3.0.0",
- "lower-case": "2.0.1",
- "param-case": "3.0.3",
"pascal-case": "3.1.1",
- "tslib": "1.10.0",
- "upper-case": "2.0.1"
- },
- "dependencies": {
- "camel-case": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz",
- "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==",
- "dev": true,
- "requires": {
- "pascal-case": "^3.1.1",
- "tslib": "^1.10.0"
- }
- },
- "import-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz",
- "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==",
- "dev": true,
- "requires": {
- "resolve-from": "^5.0.0"
- }
- },
- "lower-case": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz",
- "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==",
- "dev": true,
- "requires": {
- "tslib": "^1.10.0"
- }
- },
- "param-case": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.3.tgz",
- "integrity": "sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA==",
- "dev": true,
- "requires": {
- "dot-case": "^3.0.3",
- "tslib": "^1.10.0"
- }
- },
- "resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true
- },
- "upper-case": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.1.tgz",
- "integrity": "sha512-laAsbea9SY5osxrv7S99vH9xAaJKrw5Qpdh4ENRLcaxipjKsiaBwiAsxfa8X5mObKNTQPsupSq0J/VIxsSJe3A==",
- "dev": true,
- "requires": {
- "tslib": "^1.10.0"
- }
- }
+ "tslib": "1.10.0"
+ }
+ },
+ "@graphql-codegen/visitor-plugin-common": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.12.1.tgz",
+ "integrity": "sha512-dfcb0d1u0bGo7KgaGoWMUrFec9rKB5JiiFatHfs2CK6h6iT6giqkuyHy8247tH3yvjk+xFoIG2NVIqg9jUyv+w==",
+ "dev": true,
+ "requires": {
+ "@graphql-codegen/plugin-helpers": "1.12.1",
+ "@graphql-toolkit/relay-operation-optimizer": "0.9.7",
+ "auto-bind": "4.0.0",
+ "dependency-graph": "0.8.1",
+ "graphql-tag": "2.10.1",
+ "pascal-case": "3.1.1",
+ "tslib": "1.10.0"
}
},
"@graphql-toolkit/apollo-engine-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/apollo-engine-loader/-/apollo-engine-loader-0.9.0.tgz",
- "integrity": "sha512-CryB0LklKpMFSWTjp9YpFabrL7DZZsSzSt4jzY1f+cHC8Em/2icTJAe102NzUMxljKxVGo/FeAJIxOaV1hKVFQ==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/apollo-engine-loader/-/apollo-engine-loader-0.9.7.tgz",
+ "integrity": "sha512-gIrkMUOkkY1yIXxyR3K9e8xwj+sR4WHlCUWzjk5UTuReCcv4CZlm8omEqQjeZrPg9Naj+D2velKYxhgXhxm2ZQ==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
- "apollo-language-server": "1.17.2",
+ "@graphql-toolkit/common": "0.9.7",
+ "apollo-language-server": "1.18.0",
"tslib": "1.10.0"
}
},
"@graphql-toolkit/code-file-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/code-file-loader/-/code-file-loader-0.9.0.tgz",
- "integrity": "sha512-Aswx0oFctDhzg53jY1nwyMwRl/NLYB8jP0Du2SQkXIeSWy5UDqMdMa48VQgwERnmXv13OIqeSR4Oh+Ri30bhyw==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/code-file-loader/-/code-file-loader-0.9.7.tgz",
+ "integrity": "sha512-Vs2E7ojJ2gmhTz+U0MRLMib8yPz4+U1THCE3QgP4Pqnrqnkp/kEI7qpt3G3XI7JRRBWDHU2gdwOydnHmM/Cjow==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
- "@graphql-toolkit/graphql-tag-pluck": "0.9.0",
+ "@graphql-toolkit/common": "0.9.7",
+ "@graphql-toolkit/graphql-tag-pluck": "0.9.7",
"tslib": "1.10.0"
}
},
"@graphql-toolkit/common": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/common/-/common-0.9.0.tgz",
- "integrity": "sha512-bLuyt4yV/XIHUS+gP4aF5xjnb5M2K+uuB35Hojw0er+tkNhWiOuWQzRMWPovds/4WN2C9PuknQby/+ntgBOm/g==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/common/-/common-0.9.7.tgz",
+ "integrity": "sha512-dpSRBMLeIiRct2gkjj24bp0EV7hbK/7dpJAPqNgvDH2535LhOkprYiCXQJyP4N1LODAEkpN/zzlJfKMVn773MQ==",
"dev": true,
"requires": {
- "@kamilkisiela/graphql-tools": "4.0.6",
+ "@ardatan/graphql-tools": "4.1.0",
"aggregate-error": "3.0.1",
"lodash": "4.17.15"
}
},
"@graphql-toolkit/core": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/core/-/core-0.9.0.tgz",
- "integrity": "sha512-/0Q9S4uw27D/Q1zJsfswrsMHO2cTsvBU9G9tVxQKSI5WjHQGNJUOn0mA+Fl0bfQAjRDoC0p4BSsH1PcS5yagPA==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/core/-/core-0.9.7.tgz",
+ "integrity": "sha512-w1WU0iOq6AEBTICDxcu1xjFruFfGCHg6ERdWTWdIBOTn30qysIC0ek+XWN67vF9yV9QIdAxNu66gXKjUUWm2Tg==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
- "@graphql-toolkit/schema-merging": "0.9.0",
+ "@graphql-toolkit/common": "0.9.7",
+ "@graphql-toolkit/schema-merging": "0.9.7",
"aggregate-error": "3.0.1",
"globby": "11.0.0",
+ "import-from": "^3.0.0",
"is-glob": "4.0.1",
+ "lodash": "4.17.15",
"resolve-from": "5.0.0",
"tslib": "1.10.0",
"unixify": "1.0.0",
"valid-url": "1.0.9"
- },
- "dependencies": {
- "@nodelib/fs.stat": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
- "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
- "dev": true
- },
- "array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true
- },
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "requires": {
- "fill-range": "^7.0.1"
- }
- },
- "dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "requires": {
- "path-type": "^4.0.0"
- }
- },
- "fast-glob": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz",
- "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==",
- "dev": true,
- "requires": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.0",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.2"
- }
- },
- "fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "requires": {
- "to-regex-range": "^5.0.1"
- }
- },
- "globby": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz",
- "integrity": "sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==",
- "dev": true,
- "requires": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.1.1",
- "ignore": "^5.1.4",
- "merge2": "^1.3.0",
- "slash": "^3.0.0"
- }
- },
- "ignore": {
- "version": "5.1.4",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
- "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==",
- "dev": true
- },
- "is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
- },
- "micromatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
- "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
- "dev": true,
- "requires": {
- "braces": "^3.0.1",
- "picomatch": "^2.0.5"
- }
- },
- "path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true
- },
- "resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true
- },
- "slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true
- },
- "to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "requires": {
- "is-number": "^7.0.0"
- }
- }
+ }
+ },
+ "@graphql-toolkit/file-loading": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/file-loading/-/file-loading-0.9.1.tgz",
+ "integrity": "sha512-jiN2cvWjBR4ubwesU+IlpSCyXBZ1E7Xl5rakq63mFT9zVR5w0kEbO7Bs1nmIGlVbSvjbCzmn4d/kzrpgfwL7UQ==",
+ "dev": true,
+ "requires": {
+ "globby": "11.0.0",
+ "unixify": "1.0.0"
}
},
"@graphql-toolkit/git-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/git-loader/-/git-loader-0.9.0.tgz",
- "integrity": "sha512-B3QpM3YQhekjrLVIBev8qi95HK6As/gezjfdwT75sTYZ9+VgJwU2MDo08EKUWjHU1KoV1MDBGJNOtzopiogUlA==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/git-loader/-/git-loader-0.9.7.tgz",
+ "integrity": "sha512-/uJa6kudtPv/M8iPlGpm87mnJIAYQ5hcNG8wPY4frgol5a13Jvq9ro8jvaCueTa+kpybgUtVl4ZuCqsGa2P6CA==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
- "simple-git": "1.129.0"
+ "@graphql-toolkit/common": "0.9.7",
+ "@graphql-toolkit/graphql-tag-pluck": "0.9.7",
+ "simple-git": "1.131.0"
}
},
"@graphql-toolkit/github-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/github-loader/-/github-loader-0.9.0.tgz",
- "integrity": "sha512-srLPYVXkqZkLzJsqRo+IcLAu+HfRm6QXjLNrn6XOUb0JLmqZnXoFOMGG9k3rlHO8mPm36F+bkq2hE4tmk/mW5A==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/github-loader/-/github-loader-0.9.7.tgz",
+ "integrity": "sha512-30f0IMCn/abufu05YGiLuTdzwZk7N93zY+AEfEx7nSCpxVZYu7FSWuDxYxdMFQ2eWJvFXrh6u0As+TXB0njHZA==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
+ "@graphql-toolkit/common": "0.9.7",
+ "@graphql-toolkit/graphql-tag-pluck": "0.9.7",
"cross-fetch": "3.0.4"
}
},
"@graphql-toolkit/graphql-file-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/graphql-file-loader/-/graphql-file-loader-0.9.0.tgz",
- "integrity": "sha512-mUgmjCF1oLhYbbQC0bcX/5DdQJNJ63Pmm8JCyPhgZOy2pdbLwLKQj6KnWznny2VOGF63jjTiGUp1JfxsvYpXmQ==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/graphql-file-loader/-/graphql-file-loader-0.9.7.tgz",
+ "integrity": "sha512-t7CfYjghuXAtIqzwHhkUoE/u0a918UTOOVtHdLHh8rojjIUfsSeLeqMcFacRv+/z+kyKl9lgi4TE/qiyIpyR5A==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
+ "@graphql-toolkit/common": "0.9.7",
"tslib": "1.10.0"
}
},
"@graphql-toolkit/graphql-tag-pluck": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/graphql-tag-pluck/-/graphql-tag-pluck-0.9.0.tgz",
- "integrity": "sha512-MiMxyBM4DK+7hZNjdWeiNTw/K/8M/gSHkEPtbSGaCn0csy9GYeLM6ojz2JDdg0rxNT4Zb9Z1DzQcauMpnX3tmA==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/graphql-tag-pluck/-/graphql-tag-pluck-0.9.7.tgz",
+ "integrity": "sha512-hfHs9m/6rK0JRPrZg9LW8fPmQiNy7zvueey+TUH+qLHOkQiklDVDtQ/2yje35B16bwiyk3axxmHZ/H3fb5nWiQ==",
"dev": true,
"requires": {
- "@babel/parser": "7.7.7",
- "@babel/traverse": "7.7.4",
- "@babel/types": "7.7.4",
- "vue-template-compiler": "^2.6.10"
- },
- "dependencies": {
- "@babel/parser": {
- "version": "7.7.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz",
- "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw==",
- "dev": true
- },
- "@babel/traverse": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
- "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.5.5",
- "@babel/generator": "^7.7.4",
- "@babel/helper-function-name": "^7.7.4",
- "@babel/helper-split-export-declaration": "^7.7.4",
- "@babel/parser": "^7.7.4",
- "@babel/types": "^7.7.4",
- "debug": "^4.1.0",
- "globals": "^11.1.0",
- "lodash": "^4.17.13"
- }
- },
- "@babel/types": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
- "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2",
- "lodash": "^4.17.13",
- "to-fast-properties": "^2.0.0"
- }
- }
+ "@babel/parser": "7.8.3",
+ "@babel/traverse": "7.8.3",
+ "@babel/types": "7.8.3",
+ "@graphql-toolkit/common": "0.9.7",
+ "vue-template-compiler": "^2.6.11"
}
},
"@graphql-toolkit/json-file-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/json-file-loader/-/json-file-loader-0.9.0.tgz",
- "integrity": "sha512-YyS7HP0gVj3SuyjFAu550BUi7nQ7m++OF8ZOsEkV6KHObrKXRF4GYocffRDcdCefb02MjjrkLwcXzvMYNq8dKQ==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/json-file-loader/-/json-file-loader-0.9.7.tgz",
+ "integrity": "sha512-MNnCX201p011FPOm/rlDLkBTpx4LvooG9pdMU1ijRD/sqpHSkhZ2U/aKyoiDDKrLUgK7cvHws1KXBvLcg7r6aQ==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
+ "@graphql-toolkit/common": "0.9.7",
"tslib": "1.10.0"
}
},
"@graphql-toolkit/prisma-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/prisma-loader/-/prisma-loader-0.9.0.tgz",
- "integrity": "sha512-+vQgKp+7hhcd5DNv/fB9OQcgoThqiHflaI7UzKOPikUf24wYRNknZiAwie+9u3IP8NEymvnFaOy2nUQxqRCc3w==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/prisma-loader/-/prisma-loader-0.9.7.tgz",
+ "integrity": "sha512-SSl7bqGomTzhpXORHSEa4fThF6XC2zOuHJlOqwxGMdsbkouogR77vn7OXlCxRhNxClfBF/f7nSQdSOONVlFBvw==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
- "@graphql-toolkit/url-loader": "0.9.0",
+ "@graphql-toolkit/common": "0.9.7",
+ "@graphql-toolkit/url-loader": "0.9.7",
"prisma-yml": "1.34.10",
"tslib": "1.10.0"
}
},
+ "@graphql-toolkit/relay-operation-optimizer": {
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/relay-operation-optimizer/-/relay-operation-optimizer-0.9.7.tgz",
+ "integrity": "sha512-IPFAbKMOX3RdjyDuamK9ziuTFD5tsCiTVvHACHA2wgg+32krJZJsV6STKhFLqIwytS40vt5zhZydQCFxIrCD5g==",
+ "dev": true,
+ "requires": {
+ "@graphql-toolkit/common": "0.9.7",
+ "relay-compiler": "8.0.0"
+ }
+ },
"@graphql-toolkit/schema-merging": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/schema-merging/-/schema-merging-0.9.0.tgz",
- "integrity": "sha512-vrzkqkFXxZ4dXQrHeNGDDWONbOAVDeJmGPwK0cRu2aVszftvkYVJXBrmkMYzZJHwk+tGVkNywf1r00GR6prpOw==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/schema-merging/-/schema-merging-0.9.7.tgz",
+ "integrity": "sha512-RLhP0+XT4JGoPGCvlcTPdCE8stA7l0D5+gZ8ZP0snqzZOdsDFG4cNxpJtwf48i7uArsXkfu5OjOvTwh0MR0Wrw==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
- "@kamilkisiela/graphql-tools": "4.0.6",
+ "@ardatan/graphql-tools": "4.1.0",
+ "@graphql-toolkit/common": "0.9.7",
"deepmerge": "4.2.2",
"tslib": "1.10.0"
}
},
"@graphql-toolkit/url-loader": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@graphql-toolkit/url-loader/-/url-loader-0.9.0.tgz",
- "integrity": "sha512-umz+V9KbFv4oCWjZWiiIIH2PQrdK7tPxs8vbLdNy+EvdQrFSV5lJSknfsusyAoJfOpH+W294Ugfs0ySH5jZDxw==",
+ "version": "0.9.7",
+ "resolved": "https://registry.npmjs.org/@graphql-toolkit/url-loader/-/url-loader-0.9.7.tgz",
+ "integrity": "sha512-cOT2XJVZLWOKG4V9ucVtUTqJMW0BJqEqrHvpR8YcIWffrEChmzZQX+ug3BkRNomaUe8ywgExJ80aZuKWeSHvew==",
"dev": true,
"requires": {
- "@graphql-toolkit/common": "0.9.0",
+ "@ardatan/graphql-tools": "4.1.0",
+ "@graphql-toolkit/common": "0.9.7",
"cross-fetch": "3.0.4",
"tslib": "1.10.0",
"valid-url": "1.0.9"
@@ -4,28 +4,41 @@
"private": true,
"dependencies": {
"@apollo/react-hooks": "^3.1.3",
+ "@arrows/composition": "^1.2.2",
"@material-ui/core": "^4.9.0",
"@material-ui/icons": "^4.2.1",
"@material-ui/lab": "^4.0.0-alpha.40",
"@material-ui/styles": "^4.9.0",
+ "@types/node": "^13.5.3",
+ "@types/react": "^16.9.19",
+ "@types/react-dom": "^16.9.5",
+ "@types/react-router-dom": "^5.1.3",
"apollo-boost": "^0.4.7",
- "graphql": "^14.3.0",
+ "clsx": "^1.1.0",
+ "graphql": "^14.6.0",
+ "graphql.macro": "^1.4.2",
"moment": "^2.24.0",
"react": "^16.8.6",
"react-apollo": "^3.1.3",
"react-dom": "^16.8.6",
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0",
- "react-scripts": "^3.1.1",
+ "react-scripts": "^3.3.1",
"remark-html": "^10.0.0",
"remark-parse": "^7.0.2",
"remark-react": "^6.0.0",
+ "typescript": "^3.7.5",
"unified": "^8.4.2"
},
"devDependencies": {
- "@graphql-codegen/cli": "^1.11.2",
- "@graphql-codegen/fragment-matcher": "^1.11.2",
- "eslint-config-prettier": "^6.9.0",
+ "@graphql-codegen/cli": "^1.12.1",
+ "@graphql-codegen/fragment-matcher": "^1.12.1",
+ "@graphql-codegen/near-operation-file-preset": "^1.12.2-alpha-ea7264f9.15",
+ "@graphql-codegen/typescript-operations": "^1.12.1",
+ "@graphql-codegen/typescript-react-apollo": "^1.12.1",
+ "@graphql-codegen/introspection": "^1.12.2",
+ "eslint-config-prettier": "^6.10.0",
+ "eslint-plugin-graphql": "^3.1.1",
"eslint-plugin-prettier": "^3.1.2",
"prettier": "^1.19.1"
},
@@ -35,7 +48,7 @@
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"generate": "graphql-codegen",
- "lint": "eslint src/"
+ "lint": "eslint src --ext .ts --ext .tsx --ext .js --ext .jsx --ext .graphql"
},
"proxy": "http://localhost:3001",
"browserslist": [
@@ -1 +1,4 @@
-fragmentTypes.js
+fragmentTypes.ts
+gqlTypes.ts
+*.generated.*
+schema.json
@@ -1,15 +1,18 @@
import AppBar from '@material-ui/core/AppBar';
import CssBaseline from '@material-ui/core/CssBaseline';
-import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
-import { makeStyles } from '@material-ui/styles';
import Toolbar from '@material-ui/core/Toolbar';
+import {
+ createMuiTheme,
+ ThemeProvider,
+ makeStyles,
+} from '@material-ui/core/styles';
import React from 'react';
import { Route, Switch } from 'react-router';
import { Link } from 'react-router-dom';
+import CurrentIdentity from './CurrentIdentity';
import BugQuery from './bug/BugQuery';
import ListQuery from './list/ListQuery';
-import CurrentIdentity from './CurrentIdentity';
const theme = createMuiTheme({
palette: {
@@ -20,7 +23,9 @@ const theme = createMuiTheme({
});
const useStyles = makeStyles(theme => ({
- offset: theme.mixins.toolbar,
+ offset: {
+ ...theme.mixins.toolbar,
+ },
filler: {
flexGrow: 1,
},
@@ -46,7 +51,7 @@ export default function App() {
<AppBar position="fixed" color="primary">
<Toolbar>
<Link to="/" className={classes.appTitle}>
- <img src="logo.svg" className={classes.logo} alt="git-bug" />
+ <img src="/logo.svg" className={classes.logo} alt="git-bug" />
git-bug
</Link>
<div className={classes.filler}></div>
@@ -0,0 +1,8 @@
+fragment authored on Authored {
+ author {
+ name
+ email
+ displayName
+ avatarUrl
+ }
+}
@@ -1,9 +1,15 @@
-import gql from 'graphql-tag';
-import Tooltip from '@material-ui/core/Tooltip/Tooltip';
import MAvatar from '@material-ui/core/Avatar';
+import Tooltip from '@material-ui/core/Tooltip/Tooltip';
import React from 'react';
-const Author = ({ author, ...props }) => {
+import { AuthoredFragment } from './Author.generated';
+
+type Props = AuthoredFragment & {
+ className?: string;
+ bold?: boolean;
+};
+
+const Author = ({ author, ...props }: Props) => {
if (!author.email) {
return <span {...props}>{author.displayName}</span>;
}
@@ -15,18 +21,7 @@ const Author = ({ author, ...props }) => {
);
};
-Author.fragment = gql`
- fragment authored on Authored {
- author {
- name
- email
- displayName
- avatarUrl
- }
- }
-`;
-
-export const Avatar = ({ author, ...props }) => {
+export const Avatar = ({ author, ...props }: Props) => {
if (author.avatarUrl) {
return <MAvatar src={author.avatarUrl} {...props} />;
}
@@ -1,11 +1,14 @@
-import unified from 'unified';
-import parse from 'remark-parse';
+import React from 'react';
import html from 'remark-html';
+import parse from 'remark-parse';
import remark2react from 'remark-react';
+import unified from 'unified';
+
import ImageTag from './tag/ImageTag';
import PreTag from './tag/PreTag';
-const Content = ({ markdown }) => {
+type Props = { markdown: string };
+const Content: React.FC<Props> = ({ markdown }: Props) => {
const processor = unified()
.use(parse)
.use(html)
@@ -16,7 +19,8 @@ const Content = ({ markdown }) => {
},
});
- return processor.processSync(markdown).contents;
+ const contents: React.ReactNode = processor.processSync(markdown).contents;
+ return <>{contents}</>;
};
export default Content;
@@ -0,0 +1,8 @@
+query CurrentIdentity {
+ repository {
+ userIdentity {
+ displayName
+ avatarUrl
+ }
+ }
+}
@@ -1,45 +0,0 @@
-import React from 'react';
-import gql from 'graphql-tag';
-import { Query } from 'react-apollo';
-import Avatar from '@material-ui/core/Avatar';
-import { makeStyles } from '@material-ui/styles';
-
-const useStyles = makeStyles(theme => ({
- displayName: {
- marginLeft: theme.spacing(2),
- },
-}));
-
-const QUERY = gql`
- {
- defaultRepository {
- userIdentity {
- displayName
- avatarUrl
- }
- }
- }
-`;
-
-const CurrentIdentity = () => {
- const classes = useStyles();
- return (
- <Query query={QUERY}>
- {({ loading, error, data }) => {
- if (error || loading || !data.defaultRepository.userIdentity)
- return null;
- const user = data.defaultRepository.userIdentity;
- return (
- <>
- <Avatar src={user.avatarUrl}>
- {user.displayName.charAt(0).toUpperCase()}
- </Avatar>
- <div className={classes.displayName}>{user.displayName}</div>
- </>
- );
- }}
- </Query>
- );
-};
-
-export default CurrentIdentity;
@@ -0,0 +1,30 @@
+import Avatar from '@material-ui/core/Avatar';
+import { makeStyles } from '@material-ui/core/styles';
+import React from 'react';
+
+import { useCurrentIdentityQuery } from './CurrentIdentity.generated';
+
+const useStyles = makeStyles(theme => ({
+ displayName: {
+ marginLeft: theme.spacing(2),
+ },
+}));
+
+const CurrentIdentity = () => {
+ const classes = useStyles();
+ const { loading, error, data } = useCurrentIdentityQuery();
+
+ if (error || loading || !data?.repository?.userIdentity) return null;
+
+ const user = data.repository.userIdentity;
+ return (
+ <>
+ <Avatar src={user.avatarUrl ? user.avatarUrl : undefined}>
+ {user.displayName.charAt(0).toUpperCase()}
+ </Avatar>
+ <div className={classes.displayName}>{user.displayName}</div>
+ </>
+ );
+};
+
+export default CurrentIdentity;
@@ -1,8 +1,9 @@
import Tooltip from '@material-ui/core/Tooltip/Tooltip';
-import * as moment from 'moment';
+import moment from 'moment';
import React from 'react';
-const Date = ({ date }) => (
+type Props = { date: string };
+const Date = ({ date }: Props) => (
<Tooltip title={moment(date).format('MMMM D, YYYY, h:mm a')}>
<span> {moment(date).fromNow()} </span>
</Tooltip>
@@ -0,0 +1,8 @@
+fragment Label on Label {
+ name
+ color {
+ R
+ G
+ B
+ }
+}
@@ -1,25 +1,28 @@
-import React from 'react';
-import gql from 'graphql-tag';
-import { makeStyles } from '@material-ui/styles';
+import { common } from '@material-ui/core/colors';
+import { makeStyles } from '@material-ui/core/styles';
import {
getContrastRatio,
darken,
} from '@material-ui/core/styles/colorManipulator';
-import { common } from '@material-ui/core/colors';
+import React from 'react';
+
+import { LabelFragment } from './Label.generated';
+import { Color } from './gqlTypes';
// Minimum contrast between the background and the text color
const contrastThreshold = 2.5;
// Guess the text color based on the background color
-const getTextColor = background =>
+const getTextColor = (background: string) =>
getContrastRatio(background, common.white) >= contrastThreshold
? common.white // White on dark backgrounds
: common.black; // And black on light ones
-const _rgb = color => 'rgb(' + color.R + ',' + color.G + ',' + color.B + ')';
+const _rgb = (color: Color) =>
+ 'rgb(' + color.R + ',' + color.G + ',' + color.B + ')';
// Create a style object from the label RGB colors
-const createStyle = color => ({
+const createStyle = (color: Color) => ({
backgroundColor: _rgb(color),
color: getTextColor(_rgb(color)),
borderBottomColor: darken(_rgb(color), 0.2),
@@ -30,7 +33,7 @@ const useStyles = makeStyles(theme => ({
...theme.typography.body1,
padding: '1px 6px 0.5px',
fontSize: '0.9em',
- fontWeight: '500',
+ fontWeight: 500,
margin: '0.05em 1px calc(-1.5px + 0.05em)',
borderRadius: '3px',
display: 'inline-block',
@@ -39,7 +42,8 @@ const useStyles = makeStyles(theme => ({
},
}));
-function Label({ label }) {
+type Props = { label: LabelFragment };
+function Label({ label }: Props) {
const classes = useStyles();
return (
<span className={classes.label} style={createStyle(label.color)}>
@@ -48,15 +52,4 @@ function Label({ label }) {
);
}
-Label.fragment = gql`
- fragment Label on Label {
- name
- color {
- R
- G
- B
- }
- }
-`;
-
export default Label;
@@ -0,0 +1,14 @@
+#import "../Label.graphql"
+#import "../Author.graphql"
+
+fragment Bug on Bug {
+ id
+ humanId
+ status
+ title
+ labels {
+ ...Label
+ }
+ createdAt
+ ...authored
+}
@@ -1,12 +1,14 @@
-import { makeStyles } from '@material-ui/styles';
import Typography from '@material-ui/core/Typography/Typography';
-import gql from 'graphql-tag';
+import { makeStyles } from '@material-ui/core/styles';
import React from 'react';
+
import Author from '../Author';
import Date from '../Date';
-import TimelineQuery from './TimelineQuery';
import Label from '../Label';
+import { BugFragment } from './Bug.generated';
+import TimelineQuery from './TimelineQuery';
+
const useStyles = makeStyles(theme => ({
main: {
maxWidth: 800,
@@ -51,7 +53,11 @@ const useStyles = makeStyles(theme => ({
},
}));
-function Bug({ bug }) {
+type Props = {
+ bug: BugFragment;
+};
+
+function Bug({ bug }: Props) {
const classes = useStyles();
return (
<main className={classes.main}>
@@ -85,20 +91,4 @@ function Bug({ bug }) {
);
}
-Bug.fragment = gql`
- fragment Bug on Bug {
- id
- humanId
- status
- title
- labels {
- ...Label
- }
- createdAt
- ...authored
- }
- ${Label.fragment}
- ${Author.fragment}
-`;
-
export default Bug;
@@ -0,0 +1,9 @@
+#import "./Bug.graphql"
+
+query GetBug($id: String!) {
+ repository {
+ bug(prefix: $id) {
+ ...Bug
+ }
+ }
+}
@@ -1,30 +0,0 @@
-import CircularProgress from '@material-ui/core/CircularProgress';
-import gql from 'graphql-tag';
-import React from 'react';
-import { Query } from 'react-apollo';
-
-import Bug from './Bug';
-
-const QUERY = gql`
- query GetBug($id: String!) {
- defaultRepository {
- bug(prefix: $id) {
- ...Bug
- }
- }
- }
-
- ${Bug.fragment}
-`;
-
-const BugQuery = ({ match }) => (
- <Query query={QUERY} variables={{ id: match.params.id }}>
- {({ loading, error, data }) => {
- if (loading) return <CircularProgress />;
- if (error) return <p>Error: {error}</p>;
- return <Bug bug={data.defaultRepository.bug} />;
- }}
- </Query>
-);
-
-export default BugQuery;
@@ -0,0 +1,22 @@
+import CircularProgress from '@material-ui/core/CircularProgress';
+import React from 'react';
+import { RouteComponentProps } from 'react-router-dom';
+
+import Bug from './Bug';
+import { useGetBugQuery } from './BugQuery.generated';
+
+type Props = RouteComponentProps<{
+ id: string;
+}>;
+
+const BugQuery: React.FC<Props> = ({ match }: Props) => {
+ const { loading, error, data } = useGetBugQuery({
+ variables: { id: match.params.id },
+ });
+ if (loading) return <CircularProgress />;
+ if (error) return <p>Error: {error}</p>;
+ if (!data?.repository?.bug) return <p>404.</p>;
+ return <Bug bug={data.repository.bug} />;
+};
+
+export default BugQuery;
@@ -1,10 +1,12 @@
-import { makeStyles } from '@material-ui/styles';
-import gql from 'graphql-tag';
+import { makeStyles } from '@material-ui/core/styles';
import React from 'react';
+
import Author from '../Author';
import Date from '../Date';
import Label from '../Label';
+import { LabelChangeFragment } from './LabelChangeFragment.generated';
+
const useStyles = makeStyles(theme => ({
main: {
...theme.typography.body1,
@@ -15,7 +17,11 @@ const useStyles = makeStyles(theme => ({
},
}));
-function LabelChange({ op }) {
+type Props = {
+ op: LabelChangeFragment;
+};
+
+function LabelChange({ op }: Props) {
const { added, removed } = op;
const classes = useStyles();
return (
@@ -40,22 +46,4 @@ function LabelChange({ op }) {
);
}
-LabelChange.fragment = gql`
- fragment LabelChange on TimelineItem {
- ... on LabelChangeTimelineItem {
- date
- ...authored
- added {
- ...Label
- }
- removed {
- ...Label
- }
- }
- }
-
- ${Label.fragment}
- ${Author.fragment}
-`;
-
export default LabelChange;
@@ -0,0 +1,13 @@
+#import "../Author.graphql"
+#import "../Label.graphql"
+
+fragment LabelChange on LabelChangeTimelineItem {
+ date
+ ...authored
+ added {
+ ...Label
+ }
+ removed {
+ ...Label
+ }
+}
@@ -1,11 +1,14 @@
-import { makeStyles } from '@material-ui/styles';
import Paper from '@material-ui/core/Paper';
-import gql from 'graphql-tag';
+import { makeStyles } from '@material-ui/core/styles';
import React from 'react';
+
import Author from '../Author';
import { Avatar } from '../Author';
-import Date from '../Date';
import Content from '../Content';
+import Date from '../Date';
+
+import { AddCommentFragment } from './MessageCommentFragment.generated';
+import { CreateFragment } from './MessageCreateFragment.generated';
const useStyles = makeStyles(theme => ({
author: {
@@ -47,7 +50,11 @@ const useStyles = makeStyles(theme => ({
},
}));
-function Message({ op }) {
+type Props = {
+ op: AddCommentFragment | CreateFragment;
+};
+
+function Message({ op }: Props) {
const classes = useStyles();
return (
<article className={classes.container}>
@@ -69,30 +76,4 @@ function Message({ op }) {
);
}
-Message.createFragment = gql`
- fragment Create on TimelineItem {
- ... on CreateTimelineItem {
- createdAt
- ...authored
- edited
- message
- }
- }
-
- ${Author.fragment}
-`;
-
-Message.commentFragment = gql`
- fragment AddComment on TimelineItem {
- ... on AddCommentTimelineItem {
- createdAt
- ...authored
- edited
- message
- }
- }
-
- ${Author.fragment}
-`;
-
export default Message;
@@ -0,0 +1,8 @@
+#import "../Author.graphql"
+
+fragment AddComment on AddCommentTimelineItem {
+ createdAt
+ ...authored
+ edited
+ message
+}
@@ -0,0 +1,8 @@
+#import "../Author.graphql"
+
+fragment Create on CreateTimelineItem {
+ createdAt
+ ...authored
+ edited
+ message
+}
@@ -1,9 +1,11 @@
-import { makeStyles } from '@material-ui/styles';
-import gql from 'graphql-tag';
+import { makeStyles } from '@material-ui/core/styles';
import React from 'react';
+
import Author from '../Author';
import Date from '../Date';
+import { SetStatusFragment } from './SetStatusFragment.generated';
+
const useStyles = makeStyles(theme => ({
main: {
...theme.typography.body1,
@@ -11,7 +13,11 @@ const useStyles = makeStyles(theme => ({
},
}));
-function SetStatus({ op }) {
+type Props = {
+ op: SetStatusFragment;
+};
+
+function SetStatus({ op }: Props) {
const classes = useStyles();
return (
<div className={classes.main}>
@@ -22,16 +28,4 @@ function SetStatus({ op }) {
);
}
-SetStatus.fragment = gql`
- fragment SetStatus on TimelineItem {
- ... on SetStatusTimelineItem {
- date
- ...authored
- status
- }
- }
-
- ${Author.fragment}
-`;
-
export default SetStatus;
@@ -0,0 +1,7 @@
+#import "../Author.graphql"
+
+fragment SetStatus on SetStatusTimelineItem {
+ date
+ ...authored
+ status
+}
@@ -1,9 +1,11 @@
-import { makeStyles } from '@material-ui/styles';
-import gql from 'graphql-tag';
+import { makeStyles } from '@material-ui/core/styles';
import React from 'react';
+
import Author from '../Author';
import Date from '../Date';
+import { SetTitleFragment } from './SetTitleFragment.generated';
+
const useStyles = makeStyles(theme => ({
main: {
...theme.typography.body1,
@@ -14,7 +16,11 @@ const useStyles = makeStyles(theme => ({
},
}));
-function SetTitle({ op }) {
+type Props = {
+ op: SetTitleFragment;
+};
+
+function SetTitle({ op }: Props) {
const classes = useStyles();
return (
<div className={classes.main}>
@@ -28,17 +34,4 @@ function SetTitle({ op }) {
);
}
-SetTitle.fragment = gql`
- fragment SetTitle on TimelineItem {
- ... on SetTitleTimelineItem {
- date
- ...authored
- title
- was
- }
- }
-
- ${Author.fragment}
-`;
-
export default SetTitle;
@@ -0,0 +1,8 @@
+#import "../Author.graphql"
+
+fragment SetTitle on SetTitleTimelineItem {
+ date
+ ...authored
+ title
+ was
+}
@@ -1,43 +0,0 @@
-import { makeStyles } from '@material-ui/styles';
-import React from 'react';
-import LabelChange from './LabelChange';
-import Message from './Message';
-import SetStatus from './SetStatus';
-import SetTitle from './SetTitle';
-
-const useStyles = makeStyles(theme => ({
- main: {
- '& > *:not(:last-child)': {
- marginBottom: theme.spacing(2),
- },
- },
-}));
-
-const componentMap = {
- CreateTimelineItem: Message,
- AddCommentTimelineItem: Message,
- LabelChangeTimelineItem: LabelChange,
- SetTitleTimelineItem: SetTitle,
- SetStatusTimelineItem: SetStatus,
-};
-
-function Timeline({ ops }) {
- const classes = useStyles();
-
- return (
- <div className={classes.main}>
- {ops.map((op, index) => {
- const Component = componentMap[op.__typename];
-
- if (!Component) {
- console.warn('unsupported operation type ' + op.__typename);
- return null;
- }
-
- return <Component key={index} op={op} />;
- })}
- </div>
- );
-}
-
-export default Timeline;
@@ -0,0 +1,48 @@
+import { makeStyles } from '@material-ui/core/styles';
+import React from 'react';
+
+import LabelChange from './LabelChange';
+import Message from './Message';
+import SetStatus from './SetStatus';
+import SetTitle from './SetTitle';
+import { TimelineItemFragment } from './TimelineQuery.generated';
+
+const useStyles = makeStyles(theme => ({
+ main: {
+ '& > *:not(:last-child)': {
+ marginBottom: theme.spacing(2),
+ },
+ },
+}));
+
+type Props = {
+ ops: Array<TimelineItemFragment>;
+};
+
+function Timeline({ ops }: Props) {
+ const classes = useStyles();
+
+ return (
+ <div className={classes.main}>
+ {ops.map((op, index) => {
+ switch (op.__typename) {
+ case 'CreateTimelineItem':
+ return <Message key={index} op={op} />;
+ case 'AddCommentTimelineItem':
+ return <Message key={index} op={op} />;
+ case 'LabelChangeTimelineItem':
+ return <LabelChange key={index} op={op} />;
+ case 'SetTitleTimelineItem':
+ return <SetTitle key={index} op={op} />;
+ case 'SetStatusTimelineItem':
+ return <SetStatus key={index} op={op} />;
+ }
+
+ console.warn('unsupported operation type ' + op.__typename);
+ return null;
+ })}
+ </div>
+ );
+}
+
+export default Timeline;
@@ -0,0 +1,39 @@
+#import "./MessageCreateFragment.graphql"
+#import "./MessageCommentFragment.graphql"
+#import "./LabelChangeFragment.graphql"
+#import "./SetTitleFragment.graphql"
+#import "./SetStatusFragment.graphql"
+
+query Timeline($id: String!, $first: Int = 10, $after: String) {
+ repository {
+ bug(prefix: $id) {
+ timeline(first: $first, after: $after) {
+ nodes {
+ ...TimelineItem
+ }
+ pageInfo {
+ hasNextPage
+ endCursor
+ }
+ }
+ }
+ }
+}
+
+fragment TimelineItem on TimelineItem {
+ ... on LabelChangeTimelineItem {
+ ...LabelChange
+ }
+ ... on SetStatusTimelineItem {
+ ...SetStatus
+ }
+ ... on SetTitleTimelineItem {
+ ...SetTitle
+ }
+ ... on AddCommentTimelineItem {
+ ...AddComment
+ }
+ ... on CreateTimelineItem {
+ ...Create
+ }
+}
@@ -1,53 +0,0 @@
-import CircularProgress from '@material-ui/core/CircularProgress';
-import gql from 'graphql-tag';
-import React from 'react';
-import { Query } from 'react-apollo';
-import LabelChange from './LabelChange';
-import SetStatus from './SetStatus';
-import SetTitle from './SetTitle';
-import Timeline from './Timeline';
-import Message from './Message';
-
-const QUERY = gql`
- query($id: String!, $first: Int = 10, $after: String) {
- defaultRepository {
- bug(prefix: $id) {
- timeline(first: $first, after: $after) {
- nodes {
- ...LabelChange
- ...SetStatus
- ...SetTitle
- ...AddComment
- ...Create
- }
- pageInfo {
- hasNextPage
- endCursor
- }
- }
- }
- }
- }
- ${Message.createFragment}
- ${Message.commentFragment}
- ${LabelChange.fragment}
- ${SetTitle.fragment}
- ${SetStatus.fragment}
-`;
-
-const TimelineQuery = ({ id }) => (
- <Query query={QUERY} variables={{ id, first: 100 }}>
- {({ loading, error, data, fetchMore }) => {
- if (loading) return <CircularProgress />;
- if (error) return <p>Error: {error}</p>;
- return (
- <Timeline
- ops={data.defaultRepository.bug.timeline.nodes}
- fetchMore={fetchMore}
- />
- );
- }}
- </Query>
-);
-
-export default TimelineQuery;
@@ -0,0 +1,30 @@
+import CircularProgress from '@material-ui/core/CircularProgress';
+import React from 'react';
+
+import Timeline from './Timeline';
+import { useTimelineQuery } from './TimelineQuery.generated';
+
+type Props = {
+ id: string;
+};
+
+const TimelineQuery = ({ id }: Props) => {
+ const { loading, error, data } = useTimelineQuery({
+ variables: {
+ id,
+ first: 100,
+ },
+ });
+
+ if (loading) return <CircularProgress />;
+ if (error) return <p>Error: {error}</p>;
+
+ const nodes = data?.repository?.bug?.timeline.nodes;
+ if (!nodes) {
+ return null;
+ }
+
+ return <Timeline ops={nodes} />;
+};
+
+export default TimelineQuery;
@@ -1,5 +1,5 @@
-import ThemeProvider from '@material-ui/styles/ThemeProvider';
import { createMuiTheme } from '@material-ui/core/styles';
+import ThemeProvider from '@material-ui/styles/ThemeProvider';
import ApolloClient from 'apollo-boost';
import {
IntrospectionFragmentMatcher,
@@ -10,8 +10,8 @@ import { ApolloProvider } from 'react-apollo';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
-import introspectionQueryResultData from './fragmentTypes';
import App from './App';
+import introspectionQueryResultData from './fragmentTypes';
const theme = createMuiTheme();
@@ -0,0 +1,14 @@
+#import "../Author.graphql"
+#import "../Label.graphql"
+
+fragment BugRow on Bug {
+ id
+ humanId
+ title
+ status
+ createdAt
+ labels {
+ ...Label
+ }
+ ...authored
+}
@@ -1,36 +1,43 @@
-import { makeStyles } from '@material-ui/styles';
import TableCell from '@material-ui/core/TableCell/TableCell';
import TableRow from '@material-ui/core/TableRow/TableRow';
import Tooltip from '@material-ui/core/Tooltip/Tooltip';
-import ErrorOutline from '@material-ui/icons/ErrorOutline';
+import { makeStyles } from '@material-ui/core/styles';
import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
-import gql from 'graphql-tag';
+import ErrorOutline from '@material-ui/icons/ErrorOutline';
import React from 'react';
import { Link } from 'react-router-dom';
+
import Date from '../Date';
import Label from '../Label';
-import Author from '../Author';
+import { Status } from '../gqlTypes';
-const Open = ({ className }) => (
+import { BugRowFragment } from './BugRow.generated';
+
+type OpenClosedProps = { className: string };
+const Open = ({ className }: OpenClosedProps) => (
<Tooltip title="Open">
<ErrorOutline htmlColor="#28a745" className={className} />
</Tooltip>
);
-const Closed = ({ className }) => (
+const Closed = ({ className }: OpenClosedProps) => (
<Tooltip title="Closed">
<CheckCircleOutline htmlColor="#cb2431" className={className} />
</Tooltip>
);
-const Status = ({ status, className }) => {
+type StatusProps = { className: string; status: Status };
+const BugStatus: React.FC<StatusProps> = ({
+ status,
+ className,
+}: StatusProps) => {
switch (status) {
case 'OPEN':
return <Open className={className} />;
case 'CLOSED':
return <Closed className={className} />;
default:
- return 'unknown status ' + status;
+ return <p>{'unknown status ' + status}</p>;
}
};
@@ -57,7 +64,6 @@ const useStyles = makeStyles(theme => ({
fontWeight: 500,
},
details: {
- ...theme.typography.textSecondary,
lineHeight: '1.5rem',
color: theme.palette.text.secondary,
},
@@ -69,12 +75,16 @@ const useStyles = makeStyles(theme => ({
},
}));
-function BugRow({ bug }) {
+type Props = {
+ bug: BugRowFragment;
+};
+
+function BugRow({ bug }: Props) {
const classes = useStyles();
return (
<TableRow hover>
<TableCell className={classes.cell}>
- <Status status={bug.status} className={classes.status} />
+ <BugStatus status={bug.status} className={classes.status} />
<div className={classes.expand}>
<Link to={'bug/' + bug.humanId}>
<div className={classes.expand}>
@@ -99,21 +109,4 @@ function BugRow({ bug }) {
);
}
-BugRow.fragment = gql`
- fragment BugRow on Bug {
- id
- humanId
- title
- status
- createdAt
- labels {
- ...Label
- }
- ...authored
- }
-
- ${Label.fragment}
- ${Author.fragment}
-`;
-
export default BugRow;
@@ -1,13 +1,18 @@
-import React, { useState, useRef } from 'react';
-import { Link } from 'react-router-dom';
-import { makeStyles } from '@material-ui/styles';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
+import { SvgIconProps } from '@material-ui/core/SvgIcon';
+import { makeStyles } from '@material-ui/core/styles';
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
+import clsx from 'clsx';
+import { LocationDescriptor } from 'history';
+import React, { useState, useRef } from 'react';
+import { Link } from 'react-router-dom';
-function parse(query) {
+export type Query = { [key: string]: Array<string> };
+
+function parse(query: string): Query {
// TODO: extract the rest of the query?
- const params = {};
+ const params: Query = {};
// TODO: support escaping without quotes
const re = /(\w+):([A-Za-z0-9-]+|(["'])(([^\3]|\\.)*)\3)+/g;
@@ -29,7 +34,7 @@ function parse(query) {
return params;
}
-function quote(value) {
+function quote(value: string): string {
const hasSingle = value.includes("'");
const hasDouble = value.includes('"');
const hasSpaces = value.includes(' ');
@@ -49,19 +54,19 @@ function quote(value) {
return `"${value}"`;
}
-function stringify(params) {
- const parts = Object.entries(params).map(([key, values]) => {
+function stringify(params: Query): string {
+ const parts: string[][] = Object.entries(params).map(([key, values]) => {
return values.map(value => `${key}:${quote(value)}`);
});
- return [].concat(...parts).join(' ');
+ return new Array<string>().concat(...parts).join(' ');
}
const useStyles = makeStyles(theme => ({
element: {
...theme.typography.body2,
- color: ({ active }) => (active ? '#333' : '#444'),
+ color: '#444',
padding: theme.spacing(0, 1),
- fontWeight: ({ active }) => (active ? 600 : 400),
+ fontWeight: 400,
textDecoration: 'none',
display: 'flex',
background: 'none',
@@ -69,21 +74,51 @@ const useStyles = makeStyles(theme => ({
},
itemActive: {
fontWeight: 600,
+ color: '#333',
},
icon: {
paddingRight: theme.spacing(0.5),
},
}));
-function Dropdown({ children, dropdown, itemActive, to, ...props }) {
+type DropdownTuple = [string, string];
+
+type FilterDropdownProps = {
+ children: React.ReactNode;
+ dropdown: DropdownTuple[];
+ itemActive: (key: string) => boolean;
+ icon?: React.ComponentType<SvgIconProps>;
+ to: (key: string) => LocationDescriptor;
+} & React.ButtonHTMLAttributes<HTMLButtonElement>;
+
+function FilterDropdown({
+ children,
+ dropdown,
+ itemActive,
+ icon: Icon,
+ to,
+ ...props
+}: FilterDropdownProps) {
const [open, setOpen] = useState(false);
- const buttonRef = useRef();
- const classes = useStyles();
+ const buttonRef = useRef<HTMLButtonElement>(null);
+ const classes = useStyles({ active: false });
+
+ const content = (
+ <>
+ {Icon && <Icon fontSize="small" classes={{ root: classes.icon }} />}
+ <div>{children}</div>
+ </>
+ );
return (
<>
- <button ref={buttonRef} onClick={() => setOpen(!open)} {...props}>
- {children}
+ <button
+ ref={buttonRef}
+ onClick={() => setOpen(!open)}
+ className={classes.element}
+ {...props}
+ >
+ {content}
<ArrowDropDown fontSize="small" />
</button>
<Menu
@@ -104,7 +139,7 @@ function Dropdown({ children, dropdown, itemActive, to, ...props }) {
<MenuItem
component={Link}
to={to(key)}
- className={itemActive(key) ? classes.itemActive : null}
+ className={itemActive(key) ? classes.itemActive : undefined}
onClick={() => setOpen(false)}
key={key}
>
@@ -116,8 +151,14 @@ function Dropdown({ children, dropdown, itemActive, to, ...props }) {
);
}
-function Filter({ active, to, children, icon: Icon, dropdown, ...props }) {
- const classes = useStyles({ active });
+export type FilterProps = {
+ active: boolean;
+ to: LocationDescriptor;
+ icon?: React.ComponentType<SvgIconProps>;
+ children: React.ReactNode;
+};
+function Filter({ active, to, children, icon: Icon }: FilterProps) {
+ const classes = useStyles();
const content = (
<>
@@ -126,29 +167,23 @@ function Filter({ active, to, children, icon: Icon, dropdown, ...props }) {
</>
);
- if (dropdown) {
+ if (to) {
return (
- <Dropdown
- {...props}
+ <Link
to={to}
- dropdown={dropdown}
- className={classes.element}
+ className={clsx(classes.element, active && classes.itemActive)}
>
{content}
- </Dropdown>
- );
- }
-
- if (to) {
- return (
- <Link to={to} {...props} className={classes.element}>
- {content}
</Link>
);
}
- return <div className={classes.element}>{content}</div>;
+ return (
+ <div className={clsx(classes.element, active && classes.itemActive)}>
+ {content}
+ </div>
+ );
}
export default Filter;
-export { parse, stringify, quote };
+export { parse, stringify, quote, FilterDropdown, Filter };
@@ -0,0 +1,7 @@
+query BugCount($query: String) {
+ repository {
+ bugs: allBugs(query: $query) {
+ totalCount
+ }
+ }
+}
@@ -1,16 +1,20 @@
-import { makeStyles } from '@material-ui/styles';
-import { useQuery } from '@apollo/react-hooks';
-import gql from 'graphql-tag';
-import React from 'react';
+import { pipe } from '@arrows/composition';
import Toolbar from '@material-ui/core/Toolbar';
-import ErrorOutline from '@material-ui/icons/ErrorOutline';
+import { makeStyles } from '@material-ui/core/styles';
import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
-import Filter, { parse, stringify } from './Filter';
+import ErrorOutline from '@material-ui/icons/ErrorOutline';
+import { LocationDescriptor } from 'history';
+import React from 'react';
-// simple pipe operator
-// pipe(o, f, g, h) <=> h(g(f(o)))
-// TODO: move this out?
-const pipe = (initial, ...funcs) => funcs.reduce((acc, f) => f(acc), initial);
+import {
+ FilterDropdown,
+ FilterProps,
+ Filter,
+ parse,
+ stringify,
+ Query,
+} from './Filter';
+import { useBugCountQuery } from './FilterToolbar.generated';
const useStyles = makeStyles(theme => ({
toolbar: {
@@ -25,27 +29,21 @@ const useStyles = makeStyles(theme => ({
},
}));
-const BUG_COUNT_QUERY = gql`
- query($query: String) {
- defaultRepository {
- bugs: allBugs(query: $query) {
- totalCount
- }
- }
- }
-`;
-
// This prepends the filter text with a count
-function CountingFilter({ query, children, ...props }) {
- const { data, loading, error } = useQuery(BUG_COUNT_QUERY, {
+type CountingFilterProps = {
+ query: string;
+ children: React.ReactNode;
+} & FilterProps;
+function CountingFilter({ query, children, ...props }: CountingFilterProps) {
+ const { data, loading, error } = useBugCountQuery({
variables: { query },
});
var prefix;
if (loading) prefix = '...';
- else if (error) prefix = '???';
+ else if (error || !data?.repository) prefix = '???';
// TODO: better prefixes & error handling
- else prefix = data.defaultRepository.bugs.totalCount;
+ else prefix = data.repository.bugs.totalCount;
return (
<Filter {...props}>
@@ -54,18 +52,26 @@ function CountingFilter({ query, children, ...props }) {
);
}
-function FilterToolbar({ query, queryLocation }) {
+type Props = {
+ query: string;
+ queryLocation: (query: string) => LocationDescriptor;
+};
+function FilterToolbar({ query, queryLocation }: Props) {
const classes = useStyles();
- const params = parse(query);
+ const params: Query = parse(query);
- const hasKey = key => params[key] && params[key].length > 0;
- const hasValue = (key, value) => hasKey(key) && params[key].includes(value);
- const loc = params => pipe(params, stringify, queryLocation);
- const replaceParam = (key, value) => params => ({
+ const hasKey = (key: string): boolean =>
+ params[key] && params[key].length > 0;
+ const hasValue = (key: string, value: string): boolean =>
+ hasKey(key) && params[key].includes(value);
+ const loc = pipe(stringify, queryLocation);
+ const replaceParam = (key: string, value: string) => (
+ params: Query
+ ): Query => ({
...params,
[key]: [value],
});
- const clearParam = key => params => ({
+ const clearParam = (key: string) => (params: Query): Query => ({
...params,
[key]: [],
});
@@ -76,12 +82,11 @@ function FilterToolbar({ query, queryLocation }) {
<CountingFilter
active={hasValue('status', 'open')}
query={pipe(
- params,
replaceParam('status', 'open'),
clearParam('sort'),
stringify
- )}
- to={pipe(params, replaceParam('status', 'open'), loc)}
+ )(params)}
+ to={pipe(replaceParam('status', 'open'), loc)(params)}
icon={ErrorOutline}
>
open
@@ -89,12 +94,11 @@ function FilterToolbar({ query, queryLocation }) {
<CountingFilter
active={hasValue('status', 'closed')}
query={pipe(
- params,
replaceParam('status', 'closed'),
clearParam('sort'),
stringify
- )}
- to={pipe(params, replaceParam('status', 'closed'), loc)}
+ )(params)}
+ to={pipe(replaceParam('status', 'closed'), loc)(params)}
icon={CheckCircleOutline}
>
closed
@@ -104,7 +108,7 @@ function FilterToolbar({ query, queryLocation }) {
<Filter active={hasKey('author')}>Author</Filter>
<Filter active={hasKey('label')}>Label</Filter>
*/}
- <Filter
+ <FilterDropdown
dropdown={[
['id', 'ID'],
['creation', 'Newest'],
@@ -112,12 +116,11 @@ function FilterToolbar({ query, queryLocation }) {
['edit', 'Recently updated'],
['edit-asc', 'Least recently updated'],
]}
- active={hasKey('sort')}
itemActive={key => hasValue('sort', key)}
- to={key => pipe(params, replaceParam('sort', key), loc)}
+ to={key => pipe(replaceParam('sort', key), loc)(params)}
>
Sort
- </Filter>
+ </FilterDropdown>
</Toolbar>
);
}
@@ -1,9 +1,12 @@
import Table from '@material-ui/core/Table/Table';
import TableBody from '@material-ui/core/TableBody/TableBody';
import React from 'react';
+
import BugRow from './BugRow';
+import { BugListFragment } from './ListQuery.generated';
-function List({ bugs }) {
+type Props = { bugs: BugListFragment };
+function List({ bugs }: Props) {
return (
<Table>
<TableBody>
@@ -0,0 +1,37 @@
+#import "./BugRow.graphql"
+
+query ListBugs(
+ $first: Int
+ $last: Int
+ $after: String
+ $before: String
+ $query: String
+) {
+ repository {
+ bugs: allBugs(
+ first: $first
+ last: $last
+ after: $after
+ before: $before
+ query: $query
+ ) {
+ ...BugList
+ pageInfo {
+ hasNextPage
+ hasPreviousPage
+ startCursor
+ endCursor
+ }
+ }
+ }
+}
+
+fragment BugList on BugConnection {
+ totalCount
+ edges {
+ cursor
+ node {
+ ...BugRow
+ }
+ }
+}
@@ -1,20 +1,21 @@
-import { fade, makeStyles } from '@material-ui/core/styles';
import IconButton from '@material-ui/core/IconButton';
+import InputBase from '@material-ui/core/InputBase';
+import Paper from '@material-ui/core/Paper';
+import { fade, makeStyles, Theme } from '@material-ui/core/styles';
+import ErrorOutline from '@material-ui/icons/ErrorOutline';
import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
-import ErrorOutline from '@material-ui/icons/ErrorOutline';
-import Paper from '@material-ui/core/Paper';
-import InputBase from '@material-ui/core/InputBase';
import Skeleton from '@material-ui/lab/Skeleton';
-import gql from 'graphql-tag';
+import { ApolloError } from 'apollo-boost';
import React, { useState, useEffect, useRef } from 'react';
-import { useQuery } from '@apollo/react-hooks';
import { useLocation, useHistory, Link } from 'react-router-dom';
-import BugRow from './BugRow';
-import List from './List';
+
import FilterToolbar from './FilterToolbar';
+import List from './List';
+import { useListBugsQuery } from './ListQuery.generated';
-const useStyles = makeStyles(theme => ({
+type StylesProps = { searching?: boolean };
+const useStyles = makeStyles<Theme, StylesProps>(theme => ({
main: {
maxWidth: 800,
margin: 'auto',
@@ -46,7 +47,11 @@ const useStyles = makeStyles(theme => ({
backgroundColor: fade(theme.palette.primary.main, 0.05),
padding: theme.spacing(0, 1),
width: ({ searching }) => (searching ? '20rem' : '15rem'),
- transition: theme.transitions.create(),
+ transition: theme.transitions.create([
+ 'width',
+ 'borderColor',
+ 'backgroundColor',
+ ]),
},
searchFocused: {
borderColor: fade(theme.palette.primary.main, 0.4),
@@ -91,51 +96,21 @@ const useStyles = makeStyles(theme => ({
},
}));
-const QUERY = gql`
- query(
- $first: Int
- $last: Int
- $after: String
- $before: String
- $query: String
- ) {
- defaultRepository {
- bugs: allBugs(
- first: $first
- last: $last
- after: $after
- before: $before
- query: $query
- ) {
- totalCount
- edges {
- cursor
- node {
- ...BugRow
- }
- }
- pageInfo {
- hasNextPage
- hasPreviousPage
- startCursor
- endCursor
- }
- }
- }
- }
-
- ${BugRow.fragment}
-`;
-
-function editParams(params, callback) {
+function editParams(
+ params: URLSearchParams,
+ callback: (params: URLSearchParams) => void
+) {
const cloned = new URLSearchParams(params.toString());
callback(cloned);
return cloned;
}
// TODO: factor this out
-const Placeholder = ({ count }) => {
- const classes = useStyles();
+type PlaceholderProps = { count: number };
+const Placeholder: React.FC<PlaceholderProps> = ({
+ count,
+}: PlaceholderProps) => {
+ const classes = useStyles({});
return (
<>
{new Array(count).fill(null).map((_, i) => (
@@ -158,7 +133,7 @@ const Placeholder = ({ count }) => {
// TODO: factor this out
const NoBug = () => {
- const classes = useStyles();
+ const classes = useStyles({});
return (
<div className={classes.message}>
<ErrorOutline fontSize="large" />
@@ -167,8 +142,9 @@ const NoBug = () => {
);
};
-const Error = ({ error }) => {
- const classes = useStyles();
+type ErrorProps = { error: ApolloError };
+const Error: React.FC<ErrorProps> = ({ error }: ErrorProps) => {
+ const classes = useStyles({});
return (
<div className={[classes.errorBox, classes.message].join(' ')}>
<ErrorOutline fontSize="large" />
@@ -194,7 +170,7 @@ function ListQuery() {
const classes = useStyles({ searching: !!input });
// TODO is this the right way to do it?
- const lastQuery = useRef();
+ const lastQuery = useRef<string | null>(null);
useEffect(() => {
if (query !== lastQuery.current) {
setInput(query);
@@ -202,9 +178,10 @@ function ListQuery() {
lastQuery.current = query;
}, [query, input, lastQuery]);
+ const num = (param: string | null) => (param ? parseInt(param) : null);
const page = {
- first: params.get('first'),
- last: params.get('last'),
+ first: num(params.get('first')),
+ last: num(params.get('last')),
after: params.get('after'),
before: params.get('before'),
};
@@ -214,9 +191,9 @@ function ListQuery() {
page.first = 10;
}
- const perPage = page.first || page.last;
+ const perPage = (page.first || page.last || 10).toString();
- const { loading, error, data } = useQuery(QUERY, {
+ const { loading, error, data } = useListBugsQuery({
variables: {
...page,
query,
@@ -225,34 +202,34 @@ function ListQuery() {
let nextPage = null;
let previousPage = null;
- let hasNextPage = false;
- let hasPreviousPage = false;
let count = 0;
- if (!loading && !error && data.defaultRepository.bugs) {
- const bugs = data.defaultRepository.bugs;
- hasNextPage = bugs.pageInfo.hasNextPage;
- hasPreviousPage = bugs.pageInfo.hasPreviousPage;
+ if (!loading && !error && data?.repository?.bugs) {
+ const bugs = data.repository.bugs;
count = bugs.totalCount;
// This computes the URL for the next page
- nextPage = {
- ...location,
- search: editParams(params, p => {
- p.delete('last');
- p.delete('before');
- p.set('first', perPage);
- p.set('after', bugs.pageInfo.endCursor);
- }).toString(),
- };
+ if (bugs.pageInfo.hasNextPage) {
+ nextPage = {
+ ...location,
+ search: editParams(params, p => {
+ p.delete('last');
+ p.delete('before');
+ p.set('first', perPage);
+ p.set('after', bugs.pageInfo.endCursor);
+ }).toString(),
+ };
+ }
// and this for the previous page
- previousPage = {
- ...location,
- search: editParams(params, p => {
- p.delete('first');
- p.delete('after');
- p.set('last', perPage);
- p.set('before', bugs.pageInfo.startCursor);
- }).toString(),
- };
+ if (bugs.pageInfo.hasPreviousPage) {
+ previousPage = {
+ ...location,
+ search: editParams(params, p => {
+ p.delete('first');
+ p.delete('after');
+ p.set('last', perPage);
+ p.set('before', bugs.pageInfo.startCursor);
+ }).toString(),
+ };
+ }
}
// Prepare params without paging for editing filters
@@ -263,7 +240,7 @@ function ListQuery() {
p.delete('after');
});
// Returns a new location with the `q` param edited
- const queryLocation = query => ({
+ const queryLocation = (query: string) => ({
...location,
search: editParams(paramsWithoutPaging, p => p.set('q', query)).toString(),
});
@@ -273,8 +250,8 @@ function ListQuery() {
content = <Placeholder count={10} />;
} else if (error) {
content = <Error error={error} />;
- } else {
- const bugs = data.defaultRepository.bugs;
+ } else if (data?.repository) {
+ const bugs = data.repository.bugs;
if (bugs.totalCount === 0) {
content = <NoBug />;
@@ -283,7 +260,7 @@ function ListQuery() {
}
}
- const formSubmit = e => {
+ const formSubmit = (e: React.FormEvent) => {
e.preventDefault();
history.push(queryLocation(input));
};
@@ -296,7 +273,7 @@ function ListQuery() {
<InputBase
placeholder="Filter"
value={input}
- onInput={e => setInput(e.target.value)}
+ onInput={(e: any) => setInput(e.target.value)}
classes={{
root: classes.search,
focused: classes.searchFocused,
@@ -310,21 +287,25 @@ function ListQuery() {
<FilterToolbar query={query} queryLocation={queryLocation} />
{content}
<div className={classes.pagination}>
- <IconButton
- component={hasPreviousPage ? Link : 'button'}
- to={previousPage}
- disabled={!hasPreviousPage}
- >
- <KeyboardArrowLeft />
- </IconButton>
+ {previousPage ? (
+ <IconButton component={Link} to={previousPage}>
+ <KeyboardArrowLeft />
+ </IconButton>
+ ) : (
+ <IconButton disabled>
+ <KeyboardArrowLeft />
+ </IconButton>
+ )}
<div>{loading ? 'Loading' : `Total: ${count}`}</div>
- <IconButton
- component={hasNextPage ? Link : 'button'}
- to={nextPage}
- disabled={!hasNextPage}
- >
- <KeyboardArrowRight />
- </IconButton>
+ {nextPage ? (
+ <IconButton component={Link} to={nextPage}>
+ <KeyboardArrowRight />
+ </IconButton>
+ ) : (
+ <IconButton disabled>
+ <KeyboardArrowRight />
+ </IconButton>
+ )}
</div>
</Paper>
);
@@ -0,0 +1 @@
+/// <reference types="react-scripts" />
@@ -1,5 +1,5 @@
-import React from 'react';
import { makeStyles } from '@material-ui/styles';
+import React from 'react';
const useStyles = makeStyles({
tag: {
@@ -7,7 +7,10 @@ const useStyles = makeStyles({
},
});
-const ImageTag = ({ alt, ...props }) => {
+const ImageTag = ({
+ alt,
+ ...props
+}: React.ImgHTMLAttributes<HTMLImageElement>) => {
const classes = useStyles();
return (
<a href={props.src} target="_blank" rel="noopener noreferrer nofollow">
@@ -1,5 +1,5 @@
-import React from 'react';
import { makeStyles } from '@material-ui/styles';
+import React from 'react';
const useStyles = makeStyles({
tag: {
@@ -8,7 +8,7 @@ const useStyles = makeStyles({
},
});
-const PreTag = props => {
+const PreTag = (props: React.HTMLProps<HTMLPreElement>) => {
const classes = useStyles();
return <pre className={classes.tag} {...props}></pre>;
};
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react",
+ "typeRoots": ["node_modules/@types/", "types/"]
+ },
+ "include": ["src"]
+}
@@ -0,0 +1,6 @@
+declare module 'remark-html' {
+ import { Plugin } from 'unified';
+
+ const plugin: Plugin;
+ export default plugin;
+}
@@ -0,0 +1,6 @@
+declare module 'remark-react' {
+ import { Plugin } from 'unified';
+
+ const plugin: Plugin;
+ export default plugin;
+}