~edwargix/git.sr.ht

e7995cb9a4cbea84b54d75a725ece43b7fa502c1 — Drew DeVault 5 years ago 4971772
API: Move cursor & filter models into gql.sr.ht
M api/go.mod => api/go.mod +1 -1
@@ 4,7 4,7 @@ go 1.14

require (
	git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3
	git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200522165442-58de263ab370
	git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200522185219-a42c4594e078
	github.com/99designs/gqlgen v0.11.4-0.20200512031635-40570d1b4d70
	github.com/Masterminds/squirrel v1.4.0
	github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect

M api/go.sum => api/go.sum +4 -0
@@ 12,6 12,8 @@ git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200519155752-5492494ccefa h1:yh3hxZcollhj
git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200519155752-5492494ccefa/go.mod h1:V38DHc2+k1GmbNT4pE6OH/2fOXYcZHn9o/PUAEXH1P0=
git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200522165442-58de263ab370 h1:0X9bkwmK7jnqCKAItGF1PIn3SJ2BzJNF1jXN0nq1rcI=
git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200522165442-58de263ab370/go.mod h1:V38DHc2+k1GmbNT4pE6OH/2fOXYcZHn9o/PUAEXH1P0=
git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200522185219-a42c4594e078 h1:sKc9M81LcnicZJ3tO3FZ0Y4a1kFgwHxjLSqm8mSoIj8=
git.sr.ht/~sircmpwn/gql.sr.ht v0.0.0-20200522185219-a42c4594e078/go.mod h1:V38DHc2+k1GmbNT4pE6OH/2fOXYcZHn9o/PUAEXH1P0=
git.sr.ht/~sircmpwn/gqlgen v0.0.0-20200412134447-57d7234737d4 h1:J/Sb88htNHzZaN6ZEF8BnRWj3LzYoTrOL4WRhZEEiQE=
git.sr.ht/~sircmpwn/gqlgen v0.0.0-20200412134447-57d7234737d4/go.mod h1:W1cijL2EqAyL1eo1WAJ3ijNVkZM2okpYyCF5TRu1VfI=
github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4=


@@ 221,6 223,7 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=


@@ 261,6 264,7 @@ golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef h1:RHORRhs540cYZYrzgU2CPUy
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 h1:DAuln/hGp+aJiHpID1Y1hYzMEPP5WLwtZHPb50mN0OE=
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200519015757-0d0afa43d58a h1:gILuVKC+ZPD6g/tj6zBOdnOH1ZHI0zZ86+KLMogc6/s=
golang.org/x/tools v0.0.0-20200519015757-0d0afa43d58a/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

M api/gqlgen.yml => api/gqlgen.yml +4 -1
@@ 56,4 56,7 @@ models:
      - github.com/99designs/gqlgen/graphql.Int32
  Cursor:
    model:
      - git.sr.ht/~sircmpwn/git.sr.ht/api/graph/model.Cursor
      - git.sr.ht/~sircmpwn/gql.sr.ht/model.Cursor
  Filter:
    model:
      - git.sr.ht/~sircmpwn/gql.sr.ht/model.Filter

M api/graph/api/generated.go => api/graph/api/generated.go +62 -61
@@ 13,6 13,7 @@ import (
	"time"

	"git.sr.ht/~sircmpwn/git.sr.ht/api/graph/model"
	model1 "git.sr.ht/~sircmpwn/gql.sr.ht/model"
	"github.com/99designs/gqlgen/graphql"
	"github.com/99designs/gqlgen/graphql/introspection"
	gqlparser "github.com/vektah/gqlparser/v2"


@@ 111,7 112,7 @@ type ComplexityRoot struct {

	Query struct {
		Me                func(childComplexity int) int
		Repositories      func(childComplexity int, cursor *model.Cursor, filter *model.Filter) int
		Repositories      func(childComplexity int, cursor *model1.Cursor, filter *model1.Filter) int
		Repository        func(childComplexity int, id int) int
		RepositoryByName  func(childComplexity int, name string) int
		RepositoryByOwner func(childComplexity int, owner string, repo string) int


@@ 131,17 132,17 @@ type ComplexityRoot struct {
	}

	Repository struct {
		AccessControlList func(childComplexity int, cursor *model.Cursor) int
		AccessControlList func(childComplexity int, cursor *model1.Cursor) int
		Created           func(childComplexity int) int
		Description       func(childComplexity int) int
		Head              func(childComplexity int) int
		ID                func(childComplexity int) int
		Log               func(childComplexity int, cursor *model.Cursor, from *string) int
		Log               func(childComplexity int, cursor *model1.Cursor, from *string) int
		Name              func(childComplexity int) int
		Objects           func(childComplexity int, ids []string) int
		Owner             func(childComplexity int) int
		Path              func(childComplexity int, revspec *string, path string) int
		References        func(childComplexity int, cursor *model.Cursor) int
		References        func(childComplexity int, cursor *model1.Cursor) int
		RevparseSingle    func(childComplexity int, revspec string) int
		Updated           func(childComplexity int) int
		UpstreamURL       func(childComplexity int) int


@@ 179,7 180,7 @@ type ComplexityRoot struct {
	}

	Tree struct {
		Entries func(childComplexity int, cursor *model.Cursor) int
		Entries func(childComplexity int, cursor *model1.Cursor) int
		Entry   func(childComplexity int, path string) int
		ID      func(childComplexity int) int
		Raw     func(childComplexity int) int


@@ 206,7 207,7 @@ type ComplexityRoot struct {
		Email         func(childComplexity int) int
		ID            func(childComplexity int) int
		Location      func(childComplexity int) int
		Repositories  func(childComplexity int, cursor *model.Cursor, filter *model.Filter) int
		Repositories  func(childComplexity int, cursor *model1.Cursor, filter *model1.Filter) int
		URL           func(childComplexity int) int
		Updated       func(childComplexity int) int
		Username      func(childComplexity int) int


@@ 240,7 241,7 @@ type QueryResolver interface {
	Version(ctx context.Context) (*model.Version, error)
	Me(ctx context.Context) (*model.User, error)
	User(ctx context.Context, username string) (*model.User, error)
	Repositories(ctx context.Context, cursor *model.Cursor, filter *model.Filter) (*model.RepositoryCursor, error)
	Repositories(ctx context.Context, cursor *model1.Cursor, filter *model1.Filter) (*model.RepositoryCursor, error)
	Repository(ctx context.Context, id int) (*model.Repository, error)
	RepositoryByName(ctx context.Context, name string) (*model.Repository, error)
	RepositoryByOwner(ctx context.Context, owner string, repo string) (*model.Repository, error)


@@ 248,19 249,19 @@ type QueryResolver interface {
type RepositoryResolver interface {
	Owner(ctx context.Context, obj *model.Repository) (model.Entity, error)

	AccessControlList(ctx context.Context, obj *model.Repository, cursor *model.Cursor) (*model.ACLCursor, error)
	AccessControlList(ctx context.Context, obj *model.Repository, cursor *model1.Cursor) (*model.ACLCursor, error)
	Objects(ctx context.Context, obj *model.Repository, ids []string) ([]model.Object, error)
	References(ctx context.Context, obj *model.Repository, cursor *model.Cursor) (*model.ReferenceCursor, error)
	References(ctx context.Context, obj *model.Repository, cursor *model1.Cursor) (*model.ReferenceCursor, error)

	Log(ctx context.Context, obj *model.Repository, cursor *model.Cursor, from *string) (*model.CommitCursor, error)
	Log(ctx context.Context, obj *model.Repository, cursor *model1.Cursor, from *string) (*model.CommitCursor, error)
	Path(ctx context.Context, obj *model.Repository, revspec *string, path string) (*model.TreeEntry, error)
	RevparseSingle(ctx context.Context, obj *model.Repository, revspec string) (*model.Commit, error)
}
type TreeResolver interface {
	Entries(ctx context.Context, obj *model.Tree, cursor *model.Cursor) (*model.TreeEntryCursor, error)
	Entries(ctx context.Context, obj *model.Tree, cursor *model1.Cursor) (*model.TreeEntryCursor, error)
}
type UserResolver interface {
	Repositories(ctx context.Context, obj *model.User, cursor *model.Cursor, filter *model.Filter) (*model.RepositoryCursor, error)
	Repositories(ctx context.Context, obj *model.User, cursor *model1.Cursor, filter *model1.Filter) (*model.RepositoryCursor, error)
}

type executableSchema struct {


@@ 596,7 597,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
			return 0, false
		}

		return e.complexity.Query.Repositories(childComplexity, args["cursor"].(*model.Cursor), args["filter"].(*model.Filter)), true
		return e.complexity.Query.Repositories(childComplexity, args["cursor"].(*model1.Cursor), args["filter"].(*model1.Filter)), true

	case "Query.repository":
		if e.complexity.Query.Repository == nil {


@@ 698,7 699,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
			return 0, false
		}

		return e.complexity.Repository.AccessControlList(childComplexity, args["cursor"].(*model.Cursor)), true
		return e.complexity.Repository.AccessControlList(childComplexity, args["cursor"].(*model1.Cursor)), true

	case "Repository.created":
		if e.complexity.Repository.Created == nil {


@@ 738,7 739,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
			return 0, false
		}

		return e.complexity.Repository.Log(childComplexity, args["cursor"].(*model.Cursor), args["from"].(*string)), true
		return e.complexity.Repository.Log(childComplexity, args["cursor"].(*model1.Cursor), args["from"].(*string)), true

	case "Repository.name":
		if e.complexity.Repository.Name == nil {


@@ 788,7 789,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
			return 0, false
		}

		return e.complexity.Repository.References(childComplexity, args["cursor"].(*model.Cursor)), true
		return e.complexity.Repository.References(childComplexity, args["cursor"].(*model1.Cursor)), true

	case "Repository.revparse_single":
		if e.complexity.Repository.RevparseSingle == nil {


@@ 959,7 960,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
			return 0, false
		}

		return e.complexity.Tree.Entries(childComplexity, args["cursor"].(*model.Cursor)), true
		return e.complexity.Tree.Entries(childComplexity, args["cursor"].(*model1.Cursor)), true

	case "Tree.entry":
		if e.complexity.Tree.Entry == nil {


@@ 1095,7 1096,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
			return 0, false
		}

		return e.complexity.User.Repositories(childComplexity, args["cursor"].(*model.Cursor), args["filter"].(*model.Filter)), true
		return e.complexity.User.Repositories(childComplexity, args["cursor"].(*model1.Cursor), args["filter"].(*model1.Filter)), true

	case "User.url":
		if e.complexity.User.URL == nil {


@@ 1698,17 1699,17 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs
func (ec *executionContext) field_Query_repositories_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
	var err error
	args := map[string]interface{}{}
	var arg0 *model.Cursor
	var arg0 *model1.Cursor
	if tmp, ok := rawArgs["cursor"]; ok {
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, tmp)
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, tmp)
		if err != nil {
			return nil, err
		}
	}
	args["cursor"] = arg0
	var arg1 *model.Filter
	var arg1 *model1.Filter
	if tmp, ok := rawArgs["filter"]; ok {
		arg1, err = ec.unmarshalOFilter2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐFilter(ctx, tmp)
		arg1, err = ec.unmarshalOFilter2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐFilter(ctx, tmp)
		if err != nil {
			return nil, err
		}


@@ 1784,9 1785,9 @@ func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs m
func (ec *executionContext) field_Repository_accessControlList_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
	var err error
	args := map[string]interface{}{}
	var arg0 *model.Cursor
	var arg0 *model1.Cursor
	if tmp, ok := rawArgs["cursor"]; ok {
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, tmp)
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, tmp)
		if err != nil {
			return nil, err
		}


@@ 1798,9 1799,9 @@ func (ec *executionContext) field_Repository_accessControlList_args(ctx context.
func (ec *executionContext) field_Repository_log_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
	var err error
	args := map[string]interface{}{}
	var arg0 *model.Cursor
	var arg0 *model1.Cursor
	if tmp, ok := rawArgs["cursor"]; ok {
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, tmp)
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, tmp)
		if err != nil {
			return nil, err
		}


@@ 1856,9 1857,9 @@ func (ec *executionContext) field_Repository_path_args(ctx context.Context, rawA
func (ec *executionContext) field_Repository_references_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
	var err error
	args := map[string]interface{}{}
	var arg0 *model.Cursor
	var arg0 *model1.Cursor
	if tmp, ok := rawArgs["cursor"]; ok {
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, tmp)
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, tmp)
		if err != nil {
			return nil, err
		}


@@ 1884,9 1885,9 @@ func (ec *executionContext) field_Repository_revparse_single_args(ctx context.Co
func (ec *executionContext) field_Tree_entries_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
	var err error
	args := map[string]interface{}{}
	var arg0 *model.Cursor
	var arg0 *model1.Cursor
	if tmp, ok := rawArgs["cursor"]; ok {
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, tmp)
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, tmp)
		if err != nil {
			return nil, err
		}


@@ 1912,17 1913,17 @@ func (ec *executionContext) field_Tree_entry_args(ctx context.Context, rawArgs m
func (ec *executionContext) field_User_repositories_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
	var err error
	args := map[string]interface{}{}
	var arg0 *model.Cursor
	var arg0 *model1.Cursor
	if tmp, ok := rawArgs["cursor"]; ok {
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, tmp)
		arg0, err = ec.unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, tmp)
		if err != nil {
			return nil, err
		}
	}
	args["cursor"] = arg0
	var arg1 *model.Filter
	var arg1 *model1.Filter
	if tmp, ok := rawArgs["filter"]; ok {
		arg1, err = ec.unmarshalOFilter2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐFilter(ctx, tmp)
		arg1, err = ec.unmarshalOFilter2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐFilter(ctx, tmp)
		if err != nil {
			return nil, err
		}


@@ 2194,9 2195,9 @@ func (ec *executionContext) _ACLCursor_cursor(ctx context.Context, field graphql
	if resTmp == nil {
		return graphql.Null
	}
	res := resTmp.(*model.Cursor)
	res := resTmp.(*model1.Cursor)
	fc.Result = res
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res)
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, field.Selections, res)
}

func (ec *executionContext) _Artifact_id(ctx context.Context, field graphql.CollectedField, obj *model.Artifact) (ret graphql.Marshaler) {


@@ 3007,9 3008,9 @@ func (ec *executionContext) _CommitCursor_cursor(ctx context.Context, field grap
	if resTmp == nil {
		return graphql.Null
	}
	res := resTmp.(*model.Cursor)
	res := resTmp.(*model1.Cursor)
	fc.Result = res
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res)
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, field.Selections, res)
}

func (ec *executionContext) _Mutation_createRepository(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {


@@ 3429,7 3430,7 @@ func (ec *executionContext) _Query_repositories(ctx context.Context, field graph
	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().Repositories(rctx, args["cursor"].(*model.Cursor), args["filter"].(*model.Filter))
		return ec.resolvers.Query().Repositories(rctx, args["cursor"].(*model1.Cursor), args["filter"].(*model1.Filter))
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 3785,9 3786,9 @@ func (ec *executionContext) _ReferenceCursor_cursor(ctx context.Context, field g
	if resTmp == nil {
		return graphql.Null
	}
	res := resTmp.(*model.Cursor)
	res := resTmp.(*model1.Cursor)
	fc.Result = res
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res)
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, field.Selections, res)
}

func (ec *executionContext) _Repository_id(ctx context.Context, field graphql.CollectedField, obj *model.Repository) (ret graphql.Marshaler) {


@@ 4080,7 4081,7 @@ func (ec *executionContext) _Repository_accessControlList(ctx context.Context, f
	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.Repository().AccessControlList(rctx, obj, args["cursor"].(*model.Cursor))
		return ec.resolvers.Repository().AccessControlList(rctx, obj, args["cursor"].(*model1.Cursor))
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 4162,7 4163,7 @@ func (ec *executionContext) _Repository_references(ctx context.Context, field gr
	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.Repository().References(rctx, obj, args["cursor"].(*model.Cursor))
		return ec.resolvers.Repository().References(rctx, obj, args["cursor"].(*model1.Cursor))
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 4234,7 4235,7 @@ func (ec *executionContext) _Repository_log(ctx context.Context, field graphql.C
	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.Repository().Log(rctx, obj, args["cursor"].(*model.Cursor), args["from"].(*string))
		return ec.resolvers.Repository().Log(rctx, obj, args["cursor"].(*model1.Cursor), args["from"].(*string))
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 4387,9 4388,9 @@ func (ec *executionContext) _RepositoryCursor_cursor(ctx context.Context, field 
	if resTmp == nil {
		return graphql.Null
	}
	res := resTmp.(*model.Cursor)
	res := resTmp.(*model1.Cursor)
	fc.Result = res
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res)
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, field.Selections, res)
}

func (ec *executionContext) _Signature_name(ctx context.Context, field graphql.CollectedField, obj *model.Signature) (ret graphql.Marshaler) {


@@ 5093,7 5094,7 @@ func (ec *executionContext) _Tree_entries(ctx context.Context, field graphql.Col
	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.Tree().Entries(rctx, obj, args["cursor"].(*model.Cursor))
		return ec.resolvers.Tree().Entries(rctx, obj, args["cursor"].(*model1.Cursor))
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 5344,9 5345,9 @@ func (ec *executionContext) _TreeEntryCursor_cursor(ctx context.Context, field g
	if resTmp == nil {
		return graphql.Null
	}
	res := resTmp.(*model.Cursor)
	res := resTmp.(*model1.Cursor)
	fc.Result = res
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res)
	return ec.marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, field.Selections, res)
}

func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) {


@@ 5670,7 5671,7 @@ func (ec *executionContext) _User_repositories(ctx context.Context, field graphq
	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.User().Repositories(rctx, obj, args["cursor"].(*model.Cursor), args["filter"].(*model.Filter))
		return ec.resolvers.User().Repositories(rctx, obj, args["cursor"].(*model1.Cursor), args["filter"].(*model1.Filter))
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 6875,8 6876,8 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co

// region    **************************** input.gotpl *****************************

func (ec *executionContext) unmarshalInputFilter(ctx context.Context, obj interface{}) (model.Filter, error) {
	var it model.Filter
func (ec *executionContext) unmarshalInputFilter(ctx context.Context, obj interface{}) (model1.Filter, error) {
	var it model1.Filter
	var asMap = obj.(map[string]interface{})

	if _, present := asMap["count"]; !present {


@@ 9235,39 9236,39 @@ func (ec *executionContext) marshalOCommit2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgit
	return ec._Commit(ctx, sel, v)
}

func (ec *executionContext) unmarshalOCursor2gitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx context.Context, v interface{}) (model.Cursor, error) {
	var res model.Cursor
func (ec *executionContext) unmarshalOCursor2gitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx context.Context, v interface{}) (model1.Cursor, error) {
	var res model1.Cursor
	return res, res.UnmarshalGQL(v)
}

func (ec *executionContext) marshalOCursor2gitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx context.Context, sel ast.SelectionSet, v model.Cursor) graphql.Marshaler {
func (ec *executionContext) marshalOCursor2gitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx context.Context, sel ast.SelectionSet, v model1.Cursor) graphql.Marshaler {
	return v
}

func (ec *executionContext) unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx context.Context, v interface{}) (*model.Cursor, error) {
func (ec *executionContext) unmarshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx context.Context, v interface{}) (*model1.Cursor, error) {
	if v == nil {
		return nil, nil
	}
	res, err := ec.unmarshalOCursor2gitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx, v)
	res, err := ec.unmarshalOCursor2gitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx, v)
	return &res, err
}

func (ec *executionContext) marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐCursor(ctx context.Context, sel ast.SelectionSet, v *model.Cursor) graphql.Marshaler {
func (ec *executionContext) marshalOCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐCursor(ctx context.Context, sel ast.SelectionSet, v *model1.Cursor) graphql.Marshaler {
	if v == nil {
		return graphql.Null
	}
	return v
}

func (ec *executionContext) unmarshalOFilter2gitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐFilter(ctx context.Context, v interface{}) (model.Filter, error) {
func (ec *executionContext) unmarshalOFilter2gitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐFilter(ctx context.Context, v interface{}) (model1.Filter, error) {
	return ec.unmarshalInputFilter(ctx, v)
}

func (ec *executionContext) unmarshalOFilter2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐFilter(ctx context.Context, v interface{}) (*model.Filter, error) {
func (ec *executionContext) unmarshalOFilter2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐFilter(ctx context.Context, v interface{}) (*model1.Filter, error) {
	if v == nil {
		return nil, nil
	}
	res, err := ec.unmarshalOFilter2gitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐFilter(ctx, v)
	res, err := ec.unmarshalOFilter2gitᚗsrᚗhtᚋאsircmpwnᚋgqlᚗsrᚗhtᚋmodelᚐFilter(ctx, v)
	return &res, err
}


M api/graph/complexity.go => api/graph/complexity.go +9 -8
@@ 1,11 1,12 @@
package graph

import (
	gqlmodel "git.sr.ht/~sircmpwn/gql.sr.ht/model"

	"git.sr.ht/~sircmpwn/git.sr.ht/api/graph/api"
	"git.sr.ht/~sircmpwn/git.sr.ht/api/graph/model"
)

func cursorComplexity(c int, cursor *model.Cursor) int {
func cursorComplexity(c int, cursor *gqlmodel.Cursor) int {
	if cursor != nil {
		return c * cursor.Count
	}


@@ 13,29 14,29 @@ func cursorComplexity(c int, cursor *model.Cursor) int {
}

func ApplyComplexity(conf *api.Config) {
	conf.Complexity.Query.Repositories = func(c int, cursor *model.Cursor, filter *model.Filter) int {
	conf.Complexity.Query.Repositories = func(c int, cursor *gqlmodel.Cursor, filter *gqlmodel.Filter) int {
		c = cursorComplexity(c, cursor)
		if filter != nil && filter.Count != nil {
			c *= *filter.Count
		}
		return c
	}
	conf.Complexity.Repository.AccessControlList = func(c int, cursor *model.Cursor) int {
	conf.Complexity.Repository.AccessControlList = func(c int, cursor *gqlmodel.Cursor) int {
		return cursorComplexity(c, cursor)
	}
	conf.Complexity.Repository.Log = func(c int, cursor *model.Cursor, from *string) int {
	conf.Complexity.Repository.Log = func(c int, cursor *gqlmodel.Cursor, from *string) int {
		return cursorComplexity(c, cursor)
	}
	conf.Complexity.Repository.Objects = func(c int, ids []string) int {
		return c * len(ids)
	}
	conf.Complexity.Repository.References = func(c int, cursor *model.Cursor) int {
	conf.Complexity.Repository.References = func(c int, cursor *gqlmodel.Cursor) int {
		return cursorComplexity(c, cursor)
	}
	conf.Complexity.Tree.Entries = func(c int, cursor *model.Cursor) int {
	conf.Complexity.Tree.Entries = func(c int, cursor *gqlmodel.Cursor) int {
		return cursorComplexity(c, cursor)
	}
	conf.Complexity.User.Repositories = func(c int, cursor *model.Cursor, filter *model.Filter) int {
	conf.Complexity.User.Repositories = func(c int, cursor *gqlmodel.Cursor, filter *gqlmodel.Filter) int {
		c = cursorComplexity(c, cursor)
		if filter != nil && filter.Count != nil {
			c *= *filter.Count

M api/graph/model/acl.go => api/graph/model/acl.go +3 -2
@@ 9,6 9,7 @@ import (
	sq "github.com/Masterminds/squirrel"

	"git.sr.ht/~sircmpwn/gql.sr.ht/database"
	"git.sr.ht/~sircmpwn/gql.sr.ht/model"
)

// TODO: Drop updated column from database


@@ 50,7 51,7 @@ func (acl *ACL) Fields(ctx context.Context) []interface{} {
}

func (acl *ACL) QueryWithCursor(ctx context.Context,
	db *sql.DB, q sq.SelectBuilder, cur *Cursor) ([]*ACL, *Cursor) {
	db *sql.DB, q sq.SelectBuilder, cur *model.Cursor) ([]*ACL, *model.Cursor) {
	var (
		err  error
		rows *sql.Rows


@@ 79,7 80,7 @@ func (acl *ACL) QueryWithCursor(ctx context.Context,
	}

	if len(acls) > cur.Count {
		cur = &Cursor{
		cur = &model.Cursor{
			Count:  cur.Count,
			Next:   strconv.Itoa(acls[len(acls)-1].ID),
			Search: cur.Search,

D api/graph/model/cursor.go => api/graph/model/cursor.go +0 -69
@@ 1,69 0,0 @@
package model

import (
	"encoding/json"
	"fmt"
	"io"

	"git.sr.ht/~sircmpwn/gql.sr.ht/crypto"
)

// TODO: Add a field for the resource this is intended to be used with
type Cursor struct {
	Count   int    `json:"count"`
	Next    string `json:"next"`
	Search  string `json:"search"`
}

func (cur *Cursor) UnmarshalGQL(v interface{}) error {
	enc, ok := v.(string)
	if !ok {
		return fmt.Errorf("cursor must be strings")
	}
	plain := crypto.Decrypt([]byte(enc))
	if plain == nil {
		return fmt.Errorf("Invalid cursor")
	}
	err := json.Unmarshal(plain, cur)
	if err != nil {
		// This is guaranteed to be a programming error
		panic(err)
	}
	return nil
}

func (cur Cursor) MarshalGQL(w io.Writer) {
	data, err := json.Marshal(cur)
	if err != nil {
		panic(err)
	}
	w.Write([]byte("\""))
	w.Write(crypto.Encrypt(data))
	w.Write([]byte("\""))
}

func derefOrInt(i *int, d int) int {
	if i != nil {
		return *i
	}
	return d
}

func NewCursor(filter *Filter) *Cursor {
	if filter != nil {
		count := derefOrInt(filter.Count, 25)
		if count <= 0 {
			count = 25
		}
		return &Cursor{
			Next:   "",
			Count:  count,
			Search: "", // TODO
		}
	}
	return &Cursor{
		Count:   25,
		Next:    "",
		Search:  "",
	}
}

M api/graph/model/models_gen.go => api/graph/model/models_gen.go +11 -14
@@ 7,6 7,8 @@ import (
	"io"
	"strconv"
	"time"

	"git.sr.ht/~sircmpwn/gql.sr.ht/model"
)

type Blob interface {


@@ 18,8 20,8 @@ type Entity interface {
}

type ACLCursor struct {
	Results []*ACL  `json:"results"`
	Cursor  *Cursor `json:"cursor"`
	Results []*ACL        `json:"results"`
	Cursor  *model.Cursor `json:"cursor"`
}

type Artifact struct {


@@ 33,18 35,13 @@ type Artifact struct {
}

type CommitCursor struct {
	Results []*Commit `json:"results"`
	Cursor  *Cursor   `json:"cursor"`
}

type Filter struct {
	Count  *int    `json:"count"`
	Search *string `json:"search"`
	Results []*Commit     `json:"results"`
	Cursor  *model.Cursor `json:"cursor"`
}

type ReferenceCursor struct {
	Results []*Reference `json:"results"`
	Cursor  *Cursor      `json:"cursor"`
	Results []*Reference  `json:"results"`
	Cursor  *model.Cursor `json:"cursor"`
}

type RepoInput struct {


@@ 55,7 52,7 @@ type RepoInput struct {

type RepositoryCursor struct {
	Results []*Repository `json:"results"`
	Cursor  *Cursor       `json:"cursor"`
	Cursor  *model.Cursor `json:"cursor"`
}

type Signature struct {


@@ 78,8 75,8 @@ type Tag struct {
func (Tag) IsObject() {}

type TreeEntryCursor struct {
	Results []*TreeEntry `json:"results"`
	Cursor  *Cursor      `json:"cursor"`
	Results []*TreeEntry  `json:"results"`
	Cursor  *model.Cursor `json:"cursor"`
}

type Version struct {

M api/graph/model/repository.go => api/graph/model/repository.go +4 -4
@@ 11,6 11,7 @@ import (
	sq "github.com/Masterminds/squirrel"

	"git.sr.ht/~sircmpwn/gql.sr.ht/database"
	"git.sr.ht/~sircmpwn/gql.sr.ht/model"
)

type Repository struct {


@@ 20,7 21,6 @@ type Repository struct {
	Name           string     `json:"name"`
	Description    *string    `json:"description"`
	Visibility     Visibility `json:"visibility"`
	Cursor         *Cursor    `json:"cursor"`
	UpstreamURL    *string    `json:"upstreamUrl"`

	Path    string


@@ 87,8 87,8 @@ func (r *Repository) Fields(ctx context.Context) []interface{} {
	return append(fields, &r.Path, &r.OwnerID, &r.Updated)
}

func (r *Repository) QueryWithCursor(ctx context.Context,
	db *sql.DB, q sq.SelectBuilder, cur *Cursor) ([]*Repository, *Cursor) {
func (r *Repository) QueryWithCursor(ctx context.Context, db *sql.DB,
	q sq.SelectBuilder, cur *model.Cursor) ([]*Repository, *model.Cursor) {
	var (
		err  error
		rows *sql.Rows


@@ 118,7 118,7 @@ func (r *Repository) QueryWithCursor(ctx context.Context,
	}

	if len(repos) > cur.Count {
		cur = &Cursor{
		cur = &model.Cursor{
			Count:  cur.Count,
			Next:   strconv.FormatInt(repos[len(repos)-1].Updated.Unix(), 10),
			Search: cur.Search,

M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +18 -17
@@ 9,11 9,12 @@ import (
	"sort"
	"strings"

	"git.sr.ht/~sircmpwn/gql.sr.ht/auth"
	"git.sr.ht/~sircmpwn/gql.sr.ht/database"
	"git.sr.ht/~sircmpwn/git.sr.ht/api/graph/api"
	"git.sr.ht/~sircmpwn/git.sr.ht/api/graph/model"
	"git.sr.ht/~sircmpwn/git.sr.ht/api/loaders"
	"git.sr.ht/~sircmpwn/gql.sr.ht/auth"
	"git.sr.ht/~sircmpwn/gql.sr.ht/database"
	gqlmodel "git.sr.ht/~sircmpwn/gql.sr.ht/model"
	"github.com/99designs/gqlgen/graphql"
	git "github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/plumbing"


@@ 114,9 115,9 @@ func (r *queryResolver) User(ctx context.Context, username string) (*model.User,
	return loaders.ForContext(ctx).UsersByName.Load(username)
}

func (r *queryResolver) Repositories(ctx context.Context, cursor *model.Cursor, filter *model.Filter) (*model.RepositoryCursor, error) {
func (r *queryResolver) Repositories(ctx context.Context, cursor *gqlmodel.Cursor, filter *gqlmodel.Filter) (*model.RepositoryCursor, error) {
	if cursor == nil {
		cursor = model.NewCursor(filter)
		cursor = gqlmodel.NewCursor(filter)
	}

	repo := (&model.Repository{}).As(`repo`)


@@ 151,9 152,9 @@ func (r *repositoryResolver) Owner(ctx context.Context, obj *model.Repository) (
	return loaders.ForContext(ctx).UsersByID.Load(obj.OwnerID)
}

func (r *repositoryResolver) AccessControlList(ctx context.Context, obj *model.Repository, cursor *model.Cursor) (*model.ACLCursor, error) {
func (r *repositoryResolver) AccessControlList(ctx context.Context, obj *model.Repository, cursor *gqlmodel.Cursor) (*model.ACLCursor, error) {
	if cursor == nil {
		cursor = model.NewCursor(nil)
		cursor = gqlmodel.NewCursor(nil)
	}

	acl := (&model.ACL{}).As(`acl`)


@@ 181,7 182,7 @@ func (r *repositoryResolver) Objects(ctx context.Context, obj *model.Repository,
	return objects, nil
}

func (r *repositoryResolver) References(ctx context.Context, obj *model.Repository, cursor *model.Cursor) (*model.ReferenceCursor, error) {
func (r *repositoryResolver) References(ctx context.Context, obj *model.Repository, cursor *gqlmodel.Cursor) (*model.ReferenceCursor, error) {
	iter, err := obj.Repo().References()
	if err != nil {
		return nil, err


@@ 189,7 190,7 @@ func (r *repositoryResolver) References(ctx context.Context, obj *model.Reposito
	defer iter.Close()

	if cursor == nil {
		cursor = model.NewCursor(nil)
		cursor = gqlmodel.NewCursor(nil)
	}

	var refs []*model.Reference


@@ 214,7 215,7 @@ func (r *repositoryResolver) References(ctx context.Context, obj *model.Reposito
	}

	if len(refs) > cursor.Count {
		cursor = &model.Cursor{
		cursor = &gqlmodel.Cursor{
			Count:  cursor.Count,
			Next:   refs[cursor.Count].Name(),
			Search: cursor.Search,


@@ 227,9 228,9 @@ func (r *repositoryResolver) References(ctx context.Context, obj *model.Reposito
	return &model.ReferenceCursor{refs, cursor}, nil
}

func (r *repositoryResolver) Log(ctx context.Context, obj *model.Repository, cursor *model.Cursor, from *string) (*model.CommitCursor, error) {
func (r *repositoryResolver) Log(ctx context.Context, obj *model.Repository, cursor *gqlmodel.Cursor, from *string) (*model.CommitCursor, error) {
	if cursor == nil {
		cursor = model.NewCursor(nil)
		cursor = gqlmodel.NewCursor(nil)
		if from != nil {
			cursor.Next = *from
		}


@@ 264,7 265,7 @@ func (r *repositoryResolver) Log(ctx context.Context, obj *model.Repository, cur
	})

	if len(commits) > cursor.Count {
		cursor = &model.Cursor{
		cursor = &gqlmodel.Cursor{
			Count:  cursor.Count,
			Next:   commits[cursor.Count].ID,
			Search: "",


@@ 323,10 324,10 @@ func (r *repositoryResolver) RevparseSingle(ctx context.Context, obj *model.Repo
	return commit, nil
}

func (r *treeResolver) Entries(ctx context.Context, obj *model.Tree, cursor *model.Cursor) (*model.TreeEntryCursor, error) {
func (r *treeResolver) Entries(ctx context.Context, obj *model.Tree, cursor *gqlmodel.Cursor) (*model.TreeEntryCursor, error) {
	if cursor == nil {
		// TODO: Filter?
		cursor = model.NewCursor(nil)
		cursor = gqlmodel.NewCursor(nil)
	}

	entries := obj.GetEntries()


@@ 343,7 344,7 @@ func (r *treeResolver) Entries(ctx context.Context, obj *model.Tree, cursor *mod
	}

	if len(entries) > cursor.Count {
		cursor = &model.Cursor{
		cursor = &gqlmodel.Cursor{
			Count:  cursor.Count,
			Next:   entries[cursor.Count].Name,
			Search: cursor.Search,


@@ 356,9 357,9 @@ func (r *treeResolver) Entries(ctx context.Context, obj *model.Tree, cursor *mod
	return &model.TreeEntryCursor{entries, cursor}, nil
}

func (r *userResolver) Repositories(ctx context.Context, obj *model.User, cursor *model.Cursor, filter *model.Filter) (*model.RepositoryCursor, error) {
func (r *userResolver) Repositories(ctx context.Context, obj *model.User, cursor *gqlmodel.Cursor, filter *gqlmodel.Filter) (*model.RepositoryCursor, error) {
	if cursor == nil {
		cursor = model.NewCursor(filter)
		cursor = gqlmodel.NewCursor(filter)
	}

	repo := (&model.Repository{}).As(`repo`)