diff --git a/.gitignore b/.gitignore index 665da45..475c37f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env .env.* +.idea \ No newline at end of file diff --git a/asset/domain/builder/asset.go b/asset/domain/builder/asset.go new file mode 100644 index 0000000..60fcf00 --- /dev/null +++ b/asset/domain/builder/asset.go @@ -0,0 +1,114 @@ +package builder + +import ( + "time" + + "github.com/reearth/reearthx/asset/domain" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" +) + +type AssetBuilder struct { + a *entity.Asset +} + +func NewAssetBuilder() *AssetBuilder { + return &AssetBuilder{a: &entity.Asset{}} +} + +func (b *AssetBuilder) Build() (*entity.Asset, error) { + if b.a.ID() == (id.ID{}) { + return nil, id.ErrInvalidID + } + if b.a.WorkspaceID() == (id.WorkspaceID{}) { + return nil, domain.ErrEmptyWorkspaceID + } + if b.a.URL() == "" { + return nil, domain.ErrEmptyURL + } + if b.a.Size() <= 0 { + return nil, domain.ErrEmptySize + } + if b.a.CreatedAt().IsZero() { + now := time.Now() + b.a.SetCreatedAt(now) + b.a.SetUpdatedAt(now) + } + if b.a.Status() == "" { + b.a.UpdateStatus(entity.StatusPending, b.a.Error()) + } + return b.a, nil +} + +func (b *AssetBuilder) MustBuild() *entity.Asset { + r, err := b.Build() + if err != nil { + panic(err) + } + return r +} + +func (b *AssetBuilder) ID(id id.ID) *AssetBuilder { + b.a = entity.NewAsset(id, b.a.Name(), b.a.Size(), b.a.ContentType()) + return b +} + +func (b *AssetBuilder) NewID() *AssetBuilder { + return b.ID(id.NewID()) +} + +func (b *AssetBuilder) GroupID(groupID id.GroupID) *AssetBuilder { + b.a.MoveToGroup(groupID) + return b +} + +func (b *AssetBuilder) ProjectID(projectID id.ProjectID) *AssetBuilder { + b.a.MoveToProject(projectID) + return b +} + +func (b *AssetBuilder) WorkspaceID(workspaceID id.WorkspaceID) *AssetBuilder { + b.a.MoveToWorkspace(workspaceID) + return b +} + +func (b *AssetBuilder) Name(name string) *AssetBuilder { + b.a.UpdateMetadata(name, b.a.URL(), b.a.ContentType()) + return b +} + +func (b *AssetBuilder) Size(size int64) *AssetBuilder { + b.a.SetSize(size) + return b +} + +func (b *AssetBuilder) URL(url string) *AssetBuilder { + b.a.UpdateMetadata(b.a.Name(), url, b.a.ContentType()) + return b +} + +func (b *AssetBuilder) ContentType(contentType string) *AssetBuilder { + b.a.UpdateMetadata(b.a.Name(), b.a.URL(), contentType) + return b +} + +func (b *AssetBuilder) Status(status entity.Status) *AssetBuilder { + b.a.UpdateStatus(status, b.a.Error()) + return b +} + +func (b *AssetBuilder) Error(err string) *AssetBuilder { + b.a.UpdateStatus(b.a.Status(), err) + return b +} + +// CreatedAt sets the creation time of the asset +func (b *AssetBuilder) CreatedAt(createdAt time.Time) *AssetBuilder { + b.a.SetCreatedAt(createdAt) + return b +} + +func (b *AssetBuilder) UpdatedAt(updatedAt time.Time) *AssetBuilder { + b.a.SetUpdatedAt(updatedAt) + return b +} diff --git a/asset/domain/builder/group.go b/asset/domain/builder/group.go new file mode 100644 index 0000000..13043a0 --- /dev/null +++ b/asset/domain/builder/group.go @@ -0,0 +1,79 @@ +package builder + +import ( + "time" + + "github.com/reearth/reearthx/asset/domain" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" +) + +type GroupBuilder struct { + g *entity.Group +} + +func NewGroupBuilder() *GroupBuilder { + return &GroupBuilder{g: &entity.Group{}} +} + +func (b *GroupBuilder) Build() (*entity.Group, error) { + if b.g.ID() == (id.GroupID{}) { + return nil, id.ErrInvalidID + } + if b.g.Name() == "" { + return nil, domain.ErrEmptyGroupName + } + if b.g.CreatedAt().IsZero() { + now := time.Now() + b.CreatedAt(now) + } + return b.g, nil +} + +func (b *GroupBuilder) MustBuild() *entity.Group { + r, err := b.Build() + if err != nil { + panic(err) + } + return r +} + +func (b *GroupBuilder) ID(id id.GroupID) *GroupBuilder { + b.g = entity.NewGroup(id, b.g.Name()) + return b +} + +func (b *GroupBuilder) NewID() *GroupBuilder { + return b.ID(id.NewGroupID()) +} + +func (b *GroupBuilder) Name(name string) *GroupBuilder { + if err := b.g.UpdateName(name); err != nil { + return b + } + return b +} + +func (b *GroupBuilder) Policy(policy string) *GroupBuilder { + if err := b.g.UpdatePolicy(policy); err != nil { + return b + } + return b +} + +func (b *GroupBuilder) Description(description string) *GroupBuilder { + if err := b.g.UpdateDescription(description); err != nil { + return b + } + return b +} + +// CreatedAt sets the creation time of the group +func (b *GroupBuilder) CreatedAt(createdAt time.Time) *GroupBuilder { + b.g.SetCreatedAt(createdAt) + return b +} + +func (b *GroupBuilder) UpdatedAt(updatedAt time.Time) *GroupBuilder { + return b +} diff --git a/asset/domain/builder/tests/asset_test.go b/asset/domain/builder/tests/asset_test.go new file mode 100644 index 0000000..3869914 --- /dev/null +++ b/asset/domain/builder/tests/asset_test.go @@ -0,0 +1,190 @@ +package builder_test + +import ( + "testing" + "time" + + "github.com/reearth/reearthx/asset/domain" + "github.com/reearth/reearthx/asset/domain/builder" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/stretchr/testify/assert" +) + +func TestAssetBuilder_Build(t *testing.T) { + assetID := id.NewID() + workspaceID := id.NewWorkspaceID() + + tests := []struct { + name string + builder func() *builder.AssetBuilder + want *entity.Asset + wantErr error + }{ + { + name: "success", + builder: func() *builder.AssetBuilder { + return builder.NewAssetBuilder(). + ID(assetID). + Name("test.jpg"). + Size(1024). + ContentType("image/jpeg"). + WorkspaceID(workspaceID). + URL("https://example.com/test.jpg") + }, + want: func() *entity.Asset { + asset := entity.NewAsset(assetID, "test.jpg", 1024, "image/jpeg") + asset.MoveToWorkspace(workspaceID) + asset.UpdateMetadata("test.jpg", "https://example.com/test.jpg", "image/jpeg") + return asset + }(), + wantErr: nil, + }, + { + name: "missing ID", + builder: func() *builder.AssetBuilder { + return builder.NewAssetBuilder(). + Name("test.jpg"). + Size(1024). + ContentType("image/jpeg"). + WorkspaceID(workspaceID). + URL("https://example.com/test.jpg") + }, + wantErr: id.ErrInvalidID, + }, + { + name: "missing workspace ID", + builder: func() *builder.AssetBuilder { + return builder.NewAssetBuilder(). + ID(assetID). + Name("test.jpg"). + Size(1024). + ContentType("image/jpeg"). + URL("https://example.com/test.jpg") + }, + wantErr: domain.ErrEmptyWorkspaceID, + }, + { + name: "missing URL", + builder: func() *builder.AssetBuilder { + return builder.NewAssetBuilder(). + ID(assetID). + Name("test.jpg"). + Size(1024). + ContentType("image/jpeg"). + WorkspaceID(workspaceID) + }, + wantErr: domain.ErrEmptyURL, + }, + { + name: "invalid size", + builder: func() *builder.AssetBuilder { + return builder.NewAssetBuilder(). + ID(assetID). + Name("test.jpg"). + Size(0). + ContentType("image/jpeg"). + WorkspaceID(workspaceID). + URL("https://example.com/test.jpg") + }, + wantErr: domain.ErrEmptySize, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.builder().Build() + if tt.wantErr != nil { + assert.Equal(t, tt.wantErr, err) + assert.Nil(t, got) + return + } + assert.NoError(t, err) + assert.NotNil(t, got) + if tt.want != nil { + assert.Equal(t, tt.want.ID(), got.ID()) + assert.Equal(t, tt.want.Name(), got.Name()) + assert.Equal(t, tt.want.Size(), got.Size()) + assert.Equal(t, tt.want.ContentType(), got.ContentType()) + assert.Equal(t, tt.want.URL(), got.URL()) + assert.Equal(t, tt.want.WorkspaceID(), got.WorkspaceID()) + } + }) + } +} + +func TestAssetBuilder_MustBuild(t *testing.T) { + assetID := id.NewID() + workspaceID := id.NewWorkspaceID() + + // Test successful build + assert.NotPanics(t, func() { + asset := builder.NewAssetBuilder(). + ID(assetID). + Name("test.jpg"). + Size(1024). + ContentType("image/jpeg"). + WorkspaceID(workspaceID). + URL("https://example.com/test.jpg"). + MustBuild() + assert.NotNil(t, asset) + }) + + // Test panic on invalid build + assert.Panics(t, func() { + _ = builder.NewAssetBuilder().MustBuild() + }) +} + +func TestAssetBuilder_Setters(t *testing.T) { + assetID := id.NewID() + workspaceID := id.NewWorkspaceID() + projectID := id.NewProjectID() + groupID := id.NewGroupID() + now := time.Now() + + b := builder.NewAssetBuilder(). + CreatedAt(now). + ID(assetID). + Name("test.jpg"). + Size(1024). + ContentType("image/jpeg"). + WorkspaceID(workspaceID). + ProjectID(projectID). + GroupID(groupID). + URL("https://example.com/test.jpg"). + Status(entity.StatusActive). + Error("test error") + + asset, err := b.Build() + assert.NoError(t, err) + assert.NotNil(t, asset) + + assert.Equal(t, assetID, asset.ID()) + assert.Equal(t, workspaceID, asset.WorkspaceID()) + assert.Equal(t, projectID, asset.ProjectID()) + assert.Equal(t, groupID, asset.GroupID()) + assert.Equal(t, "test.jpg", asset.Name()) + assert.Equal(t, int64(1024), asset.Size()) + assert.Equal(t, "https://example.com/test.jpg", asset.URL()) + assert.Equal(t, "image/jpeg", asset.ContentType()) + assert.Equal(t, entity.StatusActive, asset.Status()) + assert.Equal(t, "test error", asset.Error()) + assert.Equal(t, now.Unix(), asset.CreatedAt().Unix()) +} + +func TestAssetBuilder_NewID(t *testing.T) { + b := builder.NewAssetBuilder().NewID() + // Add required fields to make the build succeed + b = b. + Name("test.jpg"). + Size(1024). + ContentType("image/jpeg"). + WorkspaceID(id.NewWorkspaceID()). + URL("https://example.com/test.jpg") + + asset, err := b.Build() + assert.NoError(t, err) + assert.NotNil(t, asset) + assert.NotEqual(t, id.ID{}, asset.ID()) // ID should be set +} diff --git a/asset/domain/builder/tests/group_test.go b/asset/domain/builder/tests/group_test.go new file mode 100644 index 0000000..117ef99 --- /dev/null +++ b/asset/domain/builder/tests/group_test.go @@ -0,0 +1,161 @@ +package builder_test + +import ( + "testing" + "time" + + "github.com/reearth/reearthx/asset/domain" + "github.com/reearth/reearthx/asset/domain/builder" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/stretchr/testify/assert" +) + +func TestGroupBuilder_Build(t *testing.T) { + now := time.Now() + groupID := id.NewGroupID() + + tests := []struct { + name string + builder func() *builder.GroupBuilder + want *entity.Group + wantErr error + }{ + { + name: "success", + builder: func() *builder.GroupBuilder { + return builder.NewGroupBuilder(). + CreatedAt(now). + ID(groupID). + Name("test-group"). + Policy("test-policy"). + Description("test description") + }, + want: func() *entity.Group { + group := entity.NewGroup(groupID, "test-group") + err := group.UpdatePolicy("test-policy") + if err != nil { + panic(err) + } + err = group.UpdateDescription("test description") + if err != nil { + panic(err) + } + return group + }(), + wantErr: nil, + }, + { + name: "missing ID", + builder: func() *builder.GroupBuilder { + return builder.NewGroupBuilder(). + Name("test-group"). + Policy("test-policy") + }, + wantErr: id.ErrInvalidID, + }, + { + name: "missing name", + builder: func() *builder.GroupBuilder { + return builder.NewGroupBuilder(). + ID(groupID). + Policy("test-policy") + }, + wantErr: domain.ErrEmptyGroupName, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.builder().Build() + if tt.wantErr != nil { + assert.Equal(t, tt.wantErr, err) + assert.Nil(t, got) + return + } + assert.NoError(t, err) + assert.NotNil(t, got) + if tt.want != nil { + assert.Equal(t, tt.want.ID(), got.ID()) + assert.Equal(t, tt.want.Name(), got.Name()) + assert.Equal(t, tt.want.Policy(), got.Policy()) + assert.Equal(t, tt.want.Description(), got.Description()) + } + }) + } +} + +func TestGroupBuilder_MustBuild(t *testing.T) { + groupID := id.NewGroupID() + + // Test successful build + assert.NotPanics(t, func() { + group := builder.NewGroupBuilder(). + CreatedAt(time.Now()). + ID(groupID). + Name("test-group"). + Policy("test-policy"). + Description("test description"). + MustBuild() + assert.NotNil(t, group) + }) + + // Test panic on invalid build + assert.Panics(t, func() { + builder.NewGroupBuilder().MustBuild() + }) +} + +func TestGroupBuilder_Setters(t *testing.T) { + groupID := id.NewGroupID() + now := time.Now() + + b := builder.NewGroupBuilder(). + CreatedAt(now). + ID(groupID). + Name("test-group"). + Policy("test-policy"). + Description("test description") + + group, err := b.Build() + assert.NoError(t, err) + assert.NotNil(t, group) + + assert.Equal(t, groupID, group.ID()) + assert.Equal(t, "test-group", group.Name()) + assert.Equal(t, "test-policy", group.Policy()) + assert.Equal(t, "test description", group.Description()) + assert.Equal(t, now.Unix(), group.CreatedAt().Unix()) +} + +func TestGroupBuilder_NewID(t *testing.T) { + b := builder.NewGroupBuilder().NewID() + // Add required fields to make the build succeed + b = b.Name("test-group") + + group, err := b.Build() + assert.NoError(t, err) + assert.NotNil(t, group) + assert.NotEqual(t, id.GroupID{}, group.ID()) // ID should be set +} + +func TestGroupBuilder_InvalidSetters(t *testing.T) { + groupID := id.NewGroupID() + + // Test setting empty name + b := builder.NewGroupBuilder(). + ID(groupID). + Name("") + group, err := b.Build() + assert.Equal(t, domain.ErrEmptyGroupName, err) + assert.Nil(t, group) + + // Test setting empty policy + b = builder.NewGroupBuilder(). + ID(groupID). + Name("test-group"). + Policy("") + group, err = b.Build() + assert.NoError(t, err) + assert.NotNil(t, group) +} diff --git a/asset/domain/entity/asset.go b/asset/domain/entity/asset.go new file mode 100644 index 0000000..77c90c4 --- /dev/null +++ b/asset/domain/entity/asset.go @@ -0,0 +1,130 @@ +package entity + +import ( + "context" + "time" + + "github.com/reearth/reearthx/asset/domain/id" + "github.com/reearth/reearthx/asset/domain/validation" +) + +type Status string + +const ( + StatusPending Status = "PENDING" + StatusActive Status = "ACTIVE" + StatusExtracting Status = "EXTRACTING" + StatusError Status = "ERROR" +) + +type Asset struct { + id id.ID + groupID id.GroupID + projectID id.ProjectID + workspaceID id.WorkspaceID + name string + size int64 + url string + contentType string + status Status + error string + createdAt time.Time + updatedAt time.Time +} + +func NewAsset(id id.ID, name string, size int64, contentType string) *Asset { + now := time.Now() + return &Asset{ + id: id, + name: name, + size: size, + contentType: contentType, + status: StatusPending, + createdAt: now, + updatedAt: now, + } +} + +// Validate implements the Validator interface +func (a *Asset) Validate(ctx context.Context) validation.Result { + validationCtx := validation.NewValidationContext( + &validation.RequiredRule{Field: "id"}, + &validation.RequiredRule{Field: "name"}, + &validation.MaxLengthRule{Field: "name", MaxLength: 255}, + &validation.RequiredRule{Field: "url"}, + &validation.RequiredRule{Field: "contentType"}, + ) + + // Create a map of fields to validate + fields := map[string]interface{}{ + "id": a.id, + "name": a.name, + "url": a.url, + "contentType": a.contentType, + } + + return validationCtx.Validate(ctx, fields) +} + +// ID Getters +func (a *Asset) ID() id.ID { return a.id } +func (a *Asset) GroupID() id.GroupID { return a.groupID } +func (a *Asset) ProjectID() id.ProjectID { return a.projectID } +func (a *Asset) WorkspaceID() id.WorkspaceID { return a.workspaceID } +func (a *Asset) Name() string { return a.name } +func (a *Asset) Size() int64 { return a.size } +func (a *Asset) URL() string { return a.url } +func (a *Asset) ContentType() string { return a.contentType } +func (a *Asset) Status() Status { return a.status } +func (a *Asset) Error() string { return a.error } +func (a *Asset) CreatedAt() time.Time { return a.createdAt } +func (a *Asset) UpdatedAt() time.Time { return a.updatedAt } + +func (a *Asset) UpdateStatus(status Status, err string) { + a.status = status + a.error = err + a.updatedAt = time.Now() +} + +func (a *Asset) UpdateMetadata(name, url, contentType string) { + if name != "" { + a.name = name + } + if url != "" { + a.url = url + } + if contentType != "" { + a.contentType = contentType + } + a.updatedAt = time.Now() +} + +func (a *Asset) MoveToWorkspace(workspaceID id.WorkspaceID) { + a.workspaceID = workspaceID + a.updatedAt = time.Now() +} + +func (a *Asset) MoveToProject(projectID id.ProjectID) { + a.projectID = projectID + a.updatedAt = time.Now() +} + +func (a *Asset) MoveToGroup(groupID id.GroupID) { + a.groupID = groupID + a.updatedAt = time.Now() +} + +func (a *Asset) SetSize(size int64) { + a.size = size + a.updatedAt = time.Now() +} + +// SetCreatedAt is an internal setter for createdAt, only used by builder +func (a *Asset) SetCreatedAt(createdAt time.Time) { + a.createdAt = createdAt +} + +// SetUpdatedAt is an internal setter for updatedAt, only used by builder +func (a *Asset) SetUpdatedAt(updatedAt time.Time) { + a.updatedAt = updatedAt +} diff --git a/asset/domain/entity/group.go b/asset/domain/entity/group.go new file mode 100644 index 0000000..31b6f50 --- /dev/null +++ b/asset/domain/entity/group.go @@ -0,0 +1,88 @@ +package entity + +import ( + "context" + "time" + + "github.com/reearth/reearthx/asset/domain" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/reearth/reearthx/asset/domain/validation" +) + +type Group struct { + id id.GroupID + name string + policy string + description string + createdAt time.Time + updatedAt time.Time +} + +func NewGroup(id id.GroupID, name string) *Group { + now := time.Now() + return &Group{ + id: id, + name: name, + createdAt: now, + updatedAt: now, + } +} + +// Validate implements the Validator interface +func (g *Group) Validate(ctx context.Context) validation.Result { + validationCtx := validation.NewValidationContext( + &validation.RequiredRule{Field: "id"}, + &validation.RequiredRule{Field: "name"}, + &validation.MaxLengthRule{Field: "name", MaxLength: 100}, + &validation.RequiredRule{Field: "policy"}, + &validation.MaxLengthRule{Field: "description", MaxLength: 500}, + ) + + // Create a map of fields to validate + fields := map[string]interface{}{ + "id": g.id, + "name": g.name, + "policy": g.policy, + "description": g.description, + } + + return validationCtx.Validate(ctx, fields) +} + +// ID Getters +func (g *Group) ID() id.GroupID { return g.id } +func (g *Group) Name() string { return g.name } +func (g *Group) Policy() string { return g.policy } +func (g *Group) Description() string { return g.description } +func (g *Group) CreatedAt() time.Time { return g.createdAt } +func (g *Group) UpdatedAt() time.Time { return g.updatedAt } + +// UpdateName Setters +func (g *Group) UpdateName(name string) error { + if name == "" { + return domain.ErrEmptyGroupName + } + g.name = name + g.updatedAt = time.Now() + return nil +} + +func (g *Group) UpdatePolicy(policy string) error { + if policy == "" { + return domain.ErrEmptyPolicy + } + g.policy = policy + g.updatedAt = time.Now() + return nil +} + +func (g *Group) UpdateDescription(description string) error { + g.description = description + g.updatedAt = time.Now() + return nil +} + +// SetCreatedAt is an internal setter for createdAt, only used by builder +func (g *Group) SetCreatedAt(createdAt time.Time) { + g.createdAt = createdAt +} diff --git a/asset/domain/entity/tests/asset_test.go b/asset/domain/entity/tests/asset_test.go new file mode 100644 index 0000000..45c4df2 --- /dev/null +++ b/asset/domain/entity/tests/asset_test.go @@ -0,0 +1,112 @@ +package entity_test + +import ( + "testing" + "time" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/stretchr/testify/assert" +) + +func TestNewAsset(t *testing.T) { + assetID := id.NewID() + name := "test.jpg" + size := int64(1024) + contentType := "image/jpeg" + + asset := entity.NewAsset(assetID, name, size, contentType) + + assert.Equal(t, assetID, asset.ID()) + assert.Equal(t, name, asset.Name()) + assert.Equal(t, size, asset.Size()) + assert.Equal(t, contentType, asset.ContentType()) + assert.Equal(t, entity.StatusPending, asset.Status()) + assert.Empty(t, asset.Error()) + assert.NotZero(t, asset.CreatedAt()) + assert.NotZero(t, asset.UpdatedAt()) + assert.Equal(t, asset.CreatedAt(), asset.UpdatedAt()) +} + +func TestAsset_UpdateStatus(t *testing.T) { + asset := entity.NewAsset(id.NewID(), "test.jpg", 1024, "image/jpeg") + initialUpdatedAt := asset.UpdatedAt() + time.Sleep(time.Millisecond) // Ensure time difference + + asset.UpdateStatus(entity.StatusError, "test error") + + assert.Equal(t, entity.StatusError, asset.Status()) + assert.Equal(t, "test error", asset.Error()) + assert.True(t, asset.UpdatedAt().After(initialUpdatedAt)) +} + +func TestAsset_UpdateMetadata(t *testing.T) { + asset := entity.NewAsset(id.NewID(), "test.jpg", 1024, "image/jpeg") + initialUpdatedAt := asset.UpdatedAt() + time.Sleep(time.Millisecond) + + newName := "new.jpg" + newURL := "https://example.com/new.jpg" + newContentType := "image/png" + + asset.UpdateMetadata(newName, newURL, newContentType) + + assert.Equal(t, newName, asset.Name()) + assert.Equal(t, newURL, asset.URL()) + assert.Equal(t, newContentType, asset.ContentType()) + assert.True(t, asset.UpdatedAt().After(initialUpdatedAt)) + + // Test partial update + asset.UpdateMetadata("", "new-url", "") + assert.Equal(t, newName, asset.Name()) + assert.Equal(t, "new-url", asset.URL()) + assert.Equal(t, newContentType, asset.ContentType()) +} + +func TestAsset_MoveToWorkspace(t *testing.T) { + asset := entity.NewAsset(id.NewID(), "test.jpg", 1024, "image/jpeg") + initialUpdatedAt := asset.UpdatedAt() + time.Sleep(time.Millisecond) + + workspaceID := id.NewWorkspaceID() + asset.MoveToWorkspace(workspaceID) + + assert.Equal(t, workspaceID, asset.WorkspaceID()) + assert.True(t, asset.UpdatedAt().After(initialUpdatedAt)) +} + +func TestAsset_MoveToProject(t *testing.T) { + asset := entity.NewAsset(id.NewID(), "test.jpg", 1024, "image/jpeg") + initialUpdatedAt := asset.UpdatedAt() + time.Sleep(time.Millisecond) + + projectID := id.NewProjectID() + asset.MoveToProject(projectID) + + assert.Equal(t, projectID, asset.ProjectID()) + assert.True(t, asset.UpdatedAt().After(initialUpdatedAt)) +} + +func TestAsset_MoveToGroup(t *testing.T) { + asset := entity.NewAsset(id.NewID(), "test.jpg", 1024, "image/jpeg") + initialUpdatedAt := asset.UpdatedAt() + time.Sleep(time.Millisecond) + + groupID := id.NewGroupID() + asset.MoveToGroup(groupID) + + assert.Equal(t, groupID, asset.GroupID()) + assert.True(t, asset.UpdatedAt().After(initialUpdatedAt)) +} + +func TestAsset_SetSize(t *testing.T) { + asset := entity.NewAsset(id.NewID(), "test.jpg", 1024, "image/jpeg") + initialUpdatedAt := asset.UpdatedAt() + time.Sleep(time.Millisecond) + + newSize := int64(2048) + asset.SetSize(newSize) + + assert.Equal(t, newSize, asset.Size()) + assert.True(t, asset.UpdatedAt().After(initialUpdatedAt)) +} diff --git a/asset/domain/entity/tests/group_test.go b/asset/domain/entity/tests/group_test.go new file mode 100644 index 0000000..06e1beb --- /dev/null +++ b/asset/domain/entity/tests/group_test.go @@ -0,0 +1,77 @@ +package entity_test + +import ( + "testing" + "time" + + "github.com/reearth/reearthx/asset/domain" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/stretchr/testify/assert" +) + +func TestNewGroup(t *testing.T) { + groupID := id.NewGroupID() + name := "test-group" + + group := entity.NewGroup(groupID, name) + + assert.Equal(t, groupID, group.ID()) + assert.Equal(t, name, group.Name()) + assert.Empty(t, group.Policy()) + assert.Empty(t, group.Description()) + assert.NotZero(t, group.CreatedAt()) + assert.NotZero(t, group.UpdatedAt()) + assert.Equal(t, group.CreatedAt(), group.UpdatedAt()) +} + +func TestGroup_UpdateName(t *testing.T) { + group := entity.NewGroup(id.NewGroupID(), "test-group") + initialUpdatedAt := group.UpdatedAt() + time.Sleep(time.Millisecond) + + // Test valid name update + err := group.UpdateName("new-name") + assert.NoError(t, err) + assert.Equal(t, "new-name", group.Name()) + assert.True(t, group.UpdatedAt().After(initialUpdatedAt)) + + // Test empty name + err = group.UpdateName("") + assert.Equal(t, domain.ErrEmptyGroupName, err) + assert.Equal(t, "new-name", group.Name()) // Name should not change +} + +func TestGroup_UpdatePolicy(t *testing.T) { + group := entity.NewGroup(id.NewGroupID(), "test-group") + initialUpdatedAt := group.UpdatedAt() + time.Sleep(time.Millisecond) + + // Test valid policy update + err := group.UpdatePolicy("new-policy") + assert.NoError(t, err) + assert.Equal(t, "new-policy", group.Policy()) + assert.True(t, group.UpdatedAt().After(initialUpdatedAt)) + + // Test empty policy + err = group.UpdatePolicy("") + assert.Equal(t, domain.ErrEmptyPolicy, err) + assert.Equal(t, "new-policy", group.Policy()) // Policy should not change +} + +func TestGroup_UpdateDescription(t *testing.T) { + group := entity.NewGroup(id.NewGroupID(), "test-group") + initialUpdatedAt := group.UpdatedAt() + time.Sleep(time.Millisecond) + + // Test description update + err := group.UpdateDescription("new description") + assert.NoError(t, err) + assert.Equal(t, "new description", group.Description()) + assert.True(t, group.UpdatedAt().After(initialUpdatedAt)) + + // Test empty description (should be allowed) + err = group.UpdateDescription("") + assert.NoError(t, err) + assert.Empty(t, group.Description()) +} diff --git a/asset/domain/errors.go b/asset/domain/errors.go new file mode 100644 index 0000000..ee6e27b --- /dev/null +++ b/asset/domain/errors.go @@ -0,0 +1,27 @@ +package domain + +import "errors" + +var ( + // ErrEmptyWorkspaceID Asset errors + ErrEmptyWorkspaceID = errors.New("workspace id is required") + ErrEmptyURL = errors.New("url is required") + ErrEmptySize = errors.New("size must be greater than 0") + ErrAssetNotFound = errors.New("asset not found") + ErrInvalidAsset = errors.New("invalid asset") + + // ErrEmptyGroupName Group errors + ErrEmptyGroupName = errors.New("group name is required") + ErrEmptyPolicy = errors.New("policy is required") + ErrGroupNotFound = errors.New("group not found") + ErrInvalidGroup = errors.New("invalid group") + + // ErrUploadFailed Storage errors + ErrUploadFailed = errors.New("failed to upload asset") + ErrDownloadFailed = errors.New("failed to download asset") + ErrDeleteFailed = errors.New("failed to delete asset") + + // ErrExtractionFailed Extraction errors + ErrExtractionFailed = errors.New("failed to extract asset") + ErrNotExtractable = errors.New("asset is not extractable") +) diff --git a/asset/domain/id/id.go b/asset/domain/id/id.go new file mode 100644 index 0000000..cde6b1e --- /dev/null +++ b/asset/domain/id/id.go @@ -0,0 +1,42 @@ +package id + +import "github.com/reearth/reearthx/idx" + +type idAsset struct{} +type idGroup struct{} +type idProject struct{} +type idWorkspace struct{} + +func (idAsset) Type() string { return "asset" } +func (idGroup) Type() string { return "group" } +func (idProject) Type() string { return "project" } +func (idWorkspace) Type() string { return "workspace" } + +type ID = idx.ID[idAsset] +type GroupID = idx.ID[idGroup] +type ProjectID = idx.ID[idProject] +type WorkspaceID = idx.ID[idWorkspace] + +var ( + NewID = idx.New[idAsset] + NewGroupID = idx.New[idGroup] + NewProjectID = idx.New[idProject] + NewWorkspaceID = idx.New[idWorkspace] + + MustID = idx.Must[idAsset] + MustGroupID = idx.Must[idGroup] + MustProjectID = idx.Must[idProject] + MustWorkspaceID = idx.Must[idWorkspace] + + From = idx.From[idAsset] + GroupIDFrom = idx.From[idGroup] + ProjectIDFrom = idx.From[idProject] + WorkspaceIDFrom = idx.From[idWorkspace] + + FromRef = idx.FromRef[idAsset] + GroupIDFromRef = idx.FromRef[idGroup] + ProjectIDFromRef = idx.FromRef[idProject] + WorkspaceIDFromRef = idx.FromRef[idWorkspace] + + ErrInvalidID = idx.ErrInvalidID +) diff --git a/asset/domain/tests/errors_test.go b/asset/domain/tests/errors_test.go new file mode 100644 index 0000000..d3de8e0 --- /dev/null +++ b/asset/domain/tests/errors_test.go @@ -0,0 +1,93 @@ +package domain_test + +import ( + "testing" + + "github.com/reearth/reearthx/asset/domain" + "github.com/stretchr/testify/assert" +) + +func TestErrors(t *testing.T) { + tests := []struct { + name string + err error + want string + }{ + { + name: "ErrEmptyWorkspaceID", + err: domain.ErrEmptyWorkspaceID, + want: "workspace id is required", + }, + { + name: "ErrEmptyURL", + err: domain.ErrEmptyURL, + want: "url is required", + }, + { + name: "ErrEmptySize", + err: domain.ErrEmptySize, + want: "size must be greater than 0", + }, + { + name: "ErrAssetNotFound", + err: domain.ErrAssetNotFound, + want: "asset not found", + }, + { + name: "ErrInvalidAsset", + err: domain.ErrInvalidAsset, + want: "invalid asset", + }, + { + name: "ErrEmptyGroupName", + err: domain.ErrEmptyGroupName, + want: "group name is required", + }, + { + name: "ErrEmptyPolicy", + err: domain.ErrEmptyPolicy, + want: "policy is required", + }, + { + name: "ErrGroupNotFound", + err: domain.ErrGroupNotFound, + want: "group not found", + }, + { + name: "ErrInvalidGroup", + err: domain.ErrInvalidGroup, + want: "invalid group", + }, + { + name: "ErrUploadFailed", + err: domain.ErrUploadFailed, + want: "failed to upload asset", + }, + { + name: "ErrDownloadFailed", + err: domain.ErrDownloadFailed, + want: "failed to download asset", + }, + { + name: "ErrDeleteFailed", + err: domain.ErrDeleteFailed, + want: "failed to delete asset", + }, + { + name: "ErrExtractionFailed", + err: domain.ErrExtractionFailed, + want: "failed to extract asset", + }, + { + name: "ErrNotExtractable", + err: domain.ErrNotExtractable, + want: "asset is not extractable", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, tt.err.Error()) + }) + } +} diff --git a/asset/domain/tests/types_test.go b/asset/domain/tests/types_test.go new file mode 100644 index 0000000..54a7ea0 --- /dev/null +++ b/asset/domain/tests/types_test.go @@ -0,0 +1,63 @@ +package domain_test + +import ( + "errors" + "testing" + + "github.com/reearth/reearthx/asset/domain" + "github.com/stretchr/testify/assert" +) + +func TestNewValidationResult(t *testing.T) { + tests := []struct { + name string + isValid bool + errors []error + want domain.ValidationResult + }{ + { + name: "valid result without errors", + isValid: true, + errors: nil, + want: domain.ValidationResult{ + IsValid: true, + Errors: nil, + }, + }, + { + name: "invalid result with errors", + isValid: false, + errors: []error{errors.New("test error")}, + want: domain.ValidationResult{ + IsValid: false, + Errors: []error{errors.New("test error")}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := domain.NewValidationResult(tt.isValid, tt.errors...) + assert.Equal(t, tt.want.IsValid, got.IsValid) + if tt.errors == nil { + assert.Empty(t, got.Errors) + } else { + assert.Equal(t, tt.want.Errors[0].Error(), got.Errors[0].Error()) + } + }) + } +} + +func TestValid(t *testing.T) { + result := domain.Valid() + assert.True(t, result.IsValid) + assert.Empty(t, result.Errors) +} + +func TestInvalid(t *testing.T) { + err := errors.New("test error") + result := domain.Invalid(err) + assert.False(t, result.IsValid) + assert.Len(t, result.Errors, 1) + assert.Equal(t, err.Error(), result.Errors[0].Error()) +} diff --git a/asset/domain/types.go b/asset/domain/types.go new file mode 100644 index 0000000..3f93fe4 --- /dev/null +++ b/asset/domain/types.go @@ -0,0 +1,28 @@ +package domain + +// ValidationResult represents the result of a domain validation +type ValidationResult struct { + IsValid bool + Errors []error +} + +// NewValidationResult creates a new validation result +func NewValidationResult(isValid bool, errors ...error) ValidationResult { + return ValidationResult{ + IsValid: isValid, + Errors: errors, + } +} + +// Valid creates a valid validation result +func Valid() ValidationResult { + return ValidationResult{IsValid: true} +} + +// Invalid creates an invalid validation result with errors +func Invalid(errors ...error) ValidationResult { + return ValidationResult{ + IsValid: false, + Errors: errors, + } +} diff --git a/asset/domain/validation/validator.go b/asset/domain/validation/validator.go new file mode 100644 index 0000000..ee62d2e --- /dev/null +++ b/asset/domain/validation/validator.go @@ -0,0 +1,166 @@ +package validation + +import ( + "context" + "errors" + "fmt" +) + +// Error ValidationError represents a validation error +type Error struct { + Field string + Message string +} + +func (e *Error) Error() string { + return fmt.Sprintf("%s: %s", e.Field, e.Message) +} + +// Result ValidationResult represents the result of a validation +type Result struct { + IsValid bool + Errors []*Error +} + +// Valid creates a valid validation result +func Valid() Result { + return Result{IsValid: true} +} + +// Invalid creates an invalid validation result with errors +func Invalid(errors ...*Error) Result { + return Result{ + IsValid: false, + Errors: errors, + } +} + +// ValidationRule defines a single validation rule +type ValidationRule interface { + // Validate performs the validation and returns any errors + Validate(ctx context.Context, value interface{}) error +} + +// Validator defines the interface for entities that can be validated +type Validator interface { + // Validate performs all validation rules and returns the result + Validate(ctx context.Context) Result +} + +// ValidationContext holds the context for validation +type ValidationContext struct { + Rules []ValidationRule +} + +// NewValidationContext creates a new validation context +func NewValidationContext(rules ...ValidationRule) *ValidationContext { + return &ValidationContext{ + Rules: rules, + } +} + +// Validate executes all validation rules in the context +func (c *ValidationContext) Validate(ctx context.Context, value interface{}) Result { + var validationErrors []*Error + + // If value is a map, validate each field with its corresponding rules + if fields, ok := value.(map[string]interface{}); ok { + for _, rule := range c.Rules { + if r, ok := rule.(*RequiredRule); ok { + if fieldValue, exists := fields[r.Field]; exists { + if err := rule.Validate(ctx, fieldValue); err != nil { + var verr *Error + if errors.As(err, &verr) { + validationErrors = append(validationErrors, verr) + } else { + validationErrors = append(validationErrors, &Error{ + Field: r.Field, + Message: err.Error(), + }) + } + } + } else { + validationErrors = append(validationErrors, NewValidationError(r.Field, "field is required")) + } + } else if r, ok := rule.(*MaxLengthRule); ok { + if fieldValue, exists := fields[r.Field]; exists { + if err := rule.Validate(ctx, fieldValue); err != nil { + var verr *Error + if errors.As(err, &verr) { + validationErrors = append(validationErrors, verr) + } else { + validationErrors = append(validationErrors, &Error{ + Field: r.Field, + Message: err.Error(), + }) + } + } + } + } + } + } else { + // If value is not a map, validate directly + for _, rule := range c.Rules { + if err := rule.Validate(ctx, value); err != nil { + var verr *Error + if errors.As(err, &verr) { + validationErrors = append(validationErrors, verr) + } else { + validationErrors = append(validationErrors, &Error{ + Message: err.Error(), + }) + } + } + } + } + + if len(validationErrors) > 0 { + return Invalid(validationErrors...) + } + return Valid() +} + +// NewValidationError ValidationError creates a new validation error +func NewValidationError(field, message string) *Error { + return &Error{ + Field: field, + Message: message, + } +} + +// Common validation rules + +// RequiredRule validates that a value is not empty +type RequiredRule struct { + Field string +} + +func (r *RequiredRule) Validate(ctx context.Context, value interface{}) error { + if value == nil { + return NewValidationError(r.Field, "field is required") + } + + switch v := value.(type) { + case string: + if v == "" { + return NewValidationError(r.Field, "field is required") + } + } + + return nil +} + +// MaxLengthRule validates that a string value does not exceed a maximum length +type MaxLengthRule struct { + Field string + MaxLength int +} + +func (r *MaxLengthRule) Validate(ctx context.Context, value interface{}) error { + if str, ok := value.(string); ok { + if len(str) > r.MaxLength { + return NewValidationError(r.Field, fmt.Sprintf("length must not exceed %d characters", r.MaxLength)) + } + } + return nil +} diff --git a/asset/domain/validation/validator_test.go b/asset/domain/validation/validator_test.go new file mode 100644 index 0000000..053c3e9 --- /dev/null +++ b/asset/domain/validation/validator_test.go @@ -0,0 +1,105 @@ +package validation + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestValidationError(t *testing.T) { + err := NewValidationError("name", "field is required") + assert.Equal(t, "name: field is required", err.Error()) +} + +func TestValidationResult(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + result := Valid() + assert.True(t, result.IsValid) + assert.Empty(t, result.Errors) + }) + + t.Run("Invalid", func(t *testing.T) { + err := NewValidationError("name", "field is required") + result := Invalid(err) + assert.False(t, result.IsValid) + assert.Len(t, result.Errors, 1) + assert.Equal(t, err, result.Errors[0]) + }) +} + +func TestRequiredRule(t *testing.T) { + ctx := context.Background() + rule := &RequiredRule{Field: "test"} + + t.Run("nil value", func(t *testing.T) { + err := rule.Validate(ctx, nil) + assert.Error(t, err) + assert.Equal(t, "test: field is required", err.Error()) + }) + + t.Run("empty string", func(t *testing.T) { + err := rule.Validate(ctx, "") + assert.Error(t, err) + assert.Equal(t, "test: field is required", err.Error()) + }) + + t.Run("non-empty string", func(t *testing.T) { + err := rule.Validate(ctx, "value") + assert.NoError(t, err) + }) +} + +func TestMaxLengthRule(t *testing.T) { + ctx := context.Background() + rule := &MaxLengthRule{Field: "test", MaxLength: 5} + + t.Run("string within limit", func(t *testing.T) { + err := rule.Validate(ctx, "12345") + assert.NoError(t, err) + }) + + t.Run("string exceeding limit", func(t *testing.T) { + err := rule.Validate(ctx, "123456") + assert.Error(t, err) + assert.Equal(t, "test: length must not exceed 5 characters", err.Error()) + }) + + t.Run("non-string value", func(t *testing.T) { + err := rule.Validate(ctx, 123) + assert.NoError(t, err) + }) +} + +func TestValidationContext(t *testing.T) { + ctx := context.Background() + + t.Run("multiple rules passing", func(t *testing.T) { + validationCtx := NewValidationContext( + &RequiredRule{Field: "name"}, + &MaxLengthRule{Field: "name", MaxLength: 10}, + ) + + result := validationCtx.Validate(ctx, map[string]interface{}{ + "name": "test", + }) + + assert.True(t, result.IsValid) + assert.Empty(t, result.Errors) + }) + + t.Run("multiple rules failing", func(t *testing.T) { + validationCtx := NewValidationContext( + &RequiredRule{Field: "name"}, + &MaxLengthRule{Field: "name", MaxLength: 5}, + ) + + result := validationCtx.Validate(ctx, map[string]interface{}{ + "name": "too long name", + }) + + assert.False(t, result.IsValid) + assert.Len(t, result.Errors, 1) + assert.Equal(t, "name: length must not exceed 5 characters", result.Errors[0].Error()) + }) +} diff --git a/asset/graphql/generated.go b/asset/graphql/generated.go new file mode 100644 index 0000000..b038dd8 --- /dev/null +++ b/asset/graphql/generated.go @@ -0,0 +1,5802 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package graphql + +import ( + "bytes" + "context" + "embed" + "errors" + "fmt" + "strconv" + "sync" + "sync/atomic" + "time" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser/v2" + "github.com/vektah/gqlparser/v2/ast" +) + +// region ************************** generated!.gotpl ************************** + +// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. +func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { + return &executableSchema{ + schema: cfg.Schema, + resolvers: cfg.Resolvers, + directives: cfg.Directives, + complexity: cfg.Complexity, + } +} + +type Config struct { + Schema *ast.Schema + Resolvers ResolverRoot + Directives DirectiveRoot + Complexity ComplexityRoot +} + +type ResolverRoot interface { + Mutation() MutationResolver + Query() QueryResolver +} + +type DirectiveRoot struct { +} + +type ComplexityRoot struct { + Asset struct { + ContentType func(childComplexity int) int + CreatedAt func(childComplexity int) int + Error func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + Size func(childComplexity int) int + Status func(childComplexity int) int + URL func(childComplexity int) int + UpdatedAt func(childComplexity int) int + } + + DeleteAssetPayload struct { + AssetID func(childComplexity int) int + } + + DeleteAssetsInGroupPayload struct { + GroupID func(childComplexity int) int + } + + DeleteAssetsPayload struct { + AssetIds func(childComplexity int) int + } + + GetAssetUploadURLPayload struct { + UploadURL func(childComplexity int) int + } + + MoveAssetPayload struct { + Asset func(childComplexity int) int + } + + Mutation struct { + DeleteAsset func(childComplexity int, input DeleteAssetInput) int + DeleteAssets func(childComplexity int, input DeleteAssetsInput) int + DeleteAssetsInGroup func(childComplexity int, input DeleteAssetsInGroupInput) int + GetAssetUploadURL func(childComplexity int, input GetAssetUploadURLInput) int + MoveAsset func(childComplexity int, input MoveAssetInput) int + UpdateAssetMetadata func(childComplexity int, input UpdateAssetMetadataInput) int + UploadAsset func(childComplexity int, input UploadAssetInput) int + } + + Query struct { + Asset func(childComplexity int, id string) int + Assets func(childComplexity int) int + } + + UpdateAssetMetadataPayload struct { + Asset func(childComplexity int) int + } + + UploadAssetPayload struct { + Asset func(childComplexity int) int + } +} + +type MutationResolver interface { + UploadAsset(ctx context.Context, input UploadAssetInput) (*UploadAssetPayload, error) + GetAssetUploadURL(ctx context.Context, input GetAssetUploadURLInput) (*GetAssetUploadURLPayload, error) + UpdateAssetMetadata(ctx context.Context, input UpdateAssetMetadataInput) (*UpdateAssetMetadataPayload, error) + DeleteAsset(ctx context.Context, input DeleteAssetInput) (*DeleteAssetPayload, error) + DeleteAssets(ctx context.Context, input DeleteAssetsInput) (*DeleteAssetsPayload, error) + MoveAsset(ctx context.Context, input MoveAssetInput) (*MoveAssetPayload, error) + DeleteAssetsInGroup(ctx context.Context, input DeleteAssetsInGroupInput) (*DeleteAssetsInGroupPayload, error) +} +type QueryResolver interface { + Asset(ctx context.Context, id string) (*Asset, error) + Assets(ctx context.Context) ([]*Asset, error) +} + +type executableSchema struct { + schema *ast.Schema + resolvers ResolverRoot + directives DirectiveRoot + complexity ComplexityRoot +} + +func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } + return parsedSchema +} + +func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) { + ec := executionContext{nil, e, 0, 0, nil} + _ = ec + switch typeName + "." + field { + + case "Asset.contentType": + if e.complexity.Asset.ContentType == nil { + break + } + + return e.complexity.Asset.ContentType(childComplexity), true + + case "Asset.createdAt": + if e.complexity.Asset.CreatedAt == nil { + break + } + + return e.complexity.Asset.CreatedAt(childComplexity), true + + case "Asset.error": + if e.complexity.Asset.Error == nil { + break + } + + return e.complexity.Asset.Error(childComplexity), true + + case "Asset.id": + if e.complexity.Asset.ID == nil { + break + } + + return e.complexity.Asset.ID(childComplexity), true + + case "Asset.name": + if e.complexity.Asset.Name == nil { + break + } + + return e.complexity.Asset.Name(childComplexity), true + + case "Asset.size": + if e.complexity.Asset.Size == nil { + break + } + + return e.complexity.Asset.Size(childComplexity), true + + case "Asset.status": + if e.complexity.Asset.Status == nil { + break + } + + return e.complexity.Asset.Status(childComplexity), true + + case "Asset.url": + if e.complexity.Asset.URL == nil { + break + } + + return e.complexity.Asset.URL(childComplexity), true + + case "Asset.updatedAt": + if e.complexity.Asset.UpdatedAt == nil { + break + } + + return e.complexity.Asset.UpdatedAt(childComplexity), true + + case "DeleteAssetPayload.assetId": + if e.complexity.DeleteAssetPayload.AssetID == nil { + break + } + + return e.complexity.DeleteAssetPayload.AssetID(childComplexity), true + + case "DeleteAssetsInGroupPayload.groupId": + if e.complexity.DeleteAssetsInGroupPayload.GroupID == nil { + break + } + + return e.complexity.DeleteAssetsInGroupPayload.GroupID(childComplexity), true + + case "DeleteAssetsPayload.assetIds": + if e.complexity.DeleteAssetsPayload.AssetIds == nil { + break + } + + return e.complexity.DeleteAssetsPayload.AssetIds(childComplexity), true + + case "GetAssetUploadURLPayload.uploadURL": + if e.complexity.GetAssetUploadURLPayload.UploadURL == nil { + break + } + + return e.complexity.GetAssetUploadURLPayload.UploadURL(childComplexity), true + + case "MoveAssetPayload.asset": + if e.complexity.MoveAssetPayload.Asset == nil { + break + } + + return e.complexity.MoveAssetPayload.Asset(childComplexity), true + + case "Mutation.deleteAsset": + if e.complexity.Mutation.DeleteAsset == nil { + break + } + + args, err := ec.field_Mutation_deleteAsset_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.DeleteAsset(childComplexity, args["input"].(DeleteAssetInput)), true + + case "Mutation.deleteAssets": + if e.complexity.Mutation.DeleteAssets == nil { + break + } + + args, err := ec.field_Mutation_deleteAssets_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.DeleteAssets(childComplexity, args["input"].(DeleteAssetsInput)), true + + case "Mutation.deleteAssetsInGroup": + if e.complexity.Mutation.DeleteAssetsInGroup == nil { + break + } + + args, err := ec.field_Mutation_deleteAssetsInGroup_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.DeleteAssetsInGroup(childComplexity, args["input"].(DeleteAssetsInGroupInput)), true + + case "Mutation.getAssetUploadURL": + if e.complexity.Mutation.GetAssetUploadURL == nil { + break + } + + args, err := ec.field_Mutation_getAssetUploadURL_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.GetAssetUploadURL(childComplexity, args["input"].(GetAssetUploadURLInput)), true + + case "Mutation.moveAsset": + if e.complexity.Mutation.MoveAsset == nil { + break + } + + args, err := ec.field_Mutation_moveAsset_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.MoveAsset(childComplexity, args["input"].(MoveAssetInput)), true + + case "Mutation.updateAssetMetadata": + if e.complexity.Mutation.UpdateAssetMetadata == nil { + break + } + + args, err := ec.field_Mutation_updateAssetMetadata_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.UpdateAssetMetadata(childComplexity, args["input"].(UpdateAssetMetadataInput)), true + + case "Mutation.uploadAsset": + if e.complexity.Mutation.UploadAsset == nil { + break + } + + args, err := ec.field_Mutation_uploadAsset_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.UploadAsset(childComplexity, args["input"].(UploadAssetInput)), true + + case "Query.asset": + if e.complexity.Query.Asset == nil { + break + } + + args, err := ec.field_Query_asset_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Asset(childComplexity, args["id"].(string)), true + + case "Query.assets": + if e.complexity.Query.Assets == nil { + break + } + + return e.complexity.Query.Assets(childComplexity), true + + case "UpdateAssetMetadataPayload.asset": + if e.complexity.UpdateAssetMetadataPayload.Asset == nil { + break + } + + return e.complexity.UpdateAssetMetadataPayload.Asset(childComplexity), true + + case "UploadAssetPayload.asset": + if e.complexity.UploadAssetPayload.Asset == nil { + break + } + + return e.complexity.UploadAssetPayload.Asset(childComplexity), true + + } + return 0, false +} + +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + rc := graphql.GetOperationContext(ctx) + ec := executionContext{rc, e, 0, 0, make(chan graphql.DeferredResult)} + inputUnmarshalMap := graphql.BuildUnmarshalerMap( + ec.unmarshalInputDeleteAssetInput, + ec.unmarshalInputDeleteAssetsInGroupInput, + ec.unmarshalInputDeleteAssetsInput, + ec.unmarshalInputGetAssetUploadURLInput, + ec.unmarshalInputMoveAssetInput, + ec.unmarshalInputUpdateAssetMetadataInput, + ec.unmarshalInputUploadAssetInput, + ) + first := true + + switch rc.Operation.Operation { + case ast.Query: + return func(ctx context.Context) *graphql.Response { + var response graphql.Response + var data graphql.Marshaler + if first { + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data = ec._Query(ctx, rc.Operation.SelectionSet) + } else { + if atomic.LoadInt32(&ec.pendingDeferred) > 0 { + result := <-ec.deferredResults + atomic.AddInt32(&ec.pendingDeferred, -1) + data = result.Result + response.Path = result.Path + response.Label = result.Label + response.Errors = result.Errors + } else { + return nil + } + } + var buf bytes.Buffer + data.MarshalGQL(&buf) + response.Data = buf.Bytes() + if atomic.LoadInt32(&ec.deferred) > 0 { + hasNext := atomic.LoadInt32(&ec.pendingDeferred) > 0 + response.HasNext = &hasNext + } + + return &response + } + case ast.Mutation: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data := ec._Mutation(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + + default: + return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) + } +} + +type executionContext struct { + *graphql.OperationContext + *executableSchema + deferred int32 + pendingDeferred int32 + deferredResults chan graphql.DeferredResult +} + +func (ec *executionContext) processDeferredGroup(dg graphql.DeferredGroup) { + atomic.AddInt32(&ec.pendingDeferred, 1) + go func() { + ctx := graphql.WithFreshResponseContext(dg.Context) + dg.FieldSet.Dispatch(ctx) + ds := graphql.DeferredResult{ + Path: dg.Path, + Label: dg.Label, + Result: dg.FieldSet, + Errors: graphql.GetErrors(ctx), + } + // null fields should bubble up + if dg.FieldSet.Invalids > 0 { + ds.Result = graphql.Null + } + ec.deferredResults <- ds + }() +} + +func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapSchema(ec.Schema()), nil +} + +func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil +} + +//go:embed "schema.graphql" +var sourcesFS embed.FS + +func sourceData(filename string) string { + data, err := sourcesFS.ReadFile(filename) + if err != nil { + panic(fmt.Sprintf("codegen problem: %s not available", filename)) + } + return string(data) +} + +var sources = []*ast.Source{ + {Name: "schema.graphql", Input: sourceData("schema.graphql"), BuiltIn: false}, +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) + +// endregion ************************** generated!.gotpl ************************** + +// region ***************************** args.gotpl ***************************** + +func (ec *executionContext) field_Mutation_deleteAsset_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 DeleteAssetInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNDeleteAssetInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_deleteAssetsInGroup_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 DeleteAssetsInGroupInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNDeleteAssetsInGroupInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsInGroupInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_deleteAssets_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 DeleteAssetsInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNDeleteAssetsInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_getAssetUploadURL_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 GetAssetUploadURLInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNGetAssetUploadURLInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐGetAssetUploadURLInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_moveAsset_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 MoveAssetInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNMoveAssetInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐMoveAssetInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_updateAssetMetadata_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 UpdateAssetMetadataInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNUpdateAssetMetadataInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUpdateAssetMetadataInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_uploadAsset_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 UploadAssetInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNUploadAssetInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUploadAssetInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["name"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_asset_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +// endregion ***************************** args.gotpl ***************************** + +// region ************************** directives.gotpl ************************** + +// endregion ************************** directives.gotpl ************************** + +// region **************************** field.gotpl ***************************** + +func (ec *executionContext) _Asset_id(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_id(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, 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.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Asset_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_name(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, 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.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Asset_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_size(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_size(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Size, 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.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Asset_size(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_contentType(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_contentType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ContentType, 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.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Asset_contentType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_url(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_url(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.URL, 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) fieldContext_Asset_url(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_status(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_status(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Status, 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.(AssetStatus) + fc.Result = res + return ec.marshalNAssetStatus2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAssetStatus(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Asset_status(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type AssetStatus does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_error(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_error(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Error, 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) fieldContext_Asset_error(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_createdAt(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_createdAt(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, 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.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Asset_createdAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Asset_updatedAt(ctx context.Context, field graphql.CollectedField, obj *Asset) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Asset_updatedAt(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, 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.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Asset_updatedAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Asset", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DeleteAssetPayload_assetId(ctx context.Context, field graphql.CollectedField, obj *DeleteAssetPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DeleteAssetPayload_assetId(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.AssetID, 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.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DeleteAssetPayload_assetId(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DeleteAssetPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DeleteAssetsInGroupPayload_groupId(ctx context.Context, field graphql.CollectedField, obj *DeleteAssetsInGroupPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DeleteAssetsInGroupPayload_groupId(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.GroupID, 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.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DeleteAssetsInGroupPayload_groupId(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DeleteAssetsInGroupPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DeleteAssetsPayload_assetIds(ctx context.Context, field graphql.CollectedField, obj *DeleteAssetsPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DeleteAssetsPayload_assetIds(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.AssetIds, 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.([]string) + fc.Result = res + return ec.marshalNID2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DeleteAssetsPayload_assetIds(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DeleteAssetsPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _GetAssetUploadURLPayload_uploadURL(ctx context.Context, field graphql.CollectedField, obj *GetAssetUploadURLPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GetAssetUploadURLPayload_uploadURL(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UploadURL, 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.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GetAssetUploadURLPayload_uploadURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GetAssetUploadURLPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _MoveAssetPayload_asset(ctx context.Context, field graphql.CollectedField, obj *MoveAssetPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MoveAssetPayload_asset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Asset, 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.(*Asset) + fc.Result = res + return ec.marshalNAsset2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAsset(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MoveAssetPayload_asset(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MoveAssetPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Asset_id(ctx, field) + case "name": + return ec.fieldContext_Asset_name(ctx, field) + case "size": + return ec.fieldContext_Asset_size(ctx, field) + case "contentType": + return ec.fieldContext_Asset_contentType(ctx, field) + case "url": + return ec.fieldContext_Asset_url(ctx, field) + case "status": + return ec.fieldContext_Asset_status(ctx, field) + case "error": + return ec.fieldContext_Asset_error(ctx, field) + case "createdAt": + return ec.fieldContext_Asset_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_Asset_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Asset", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Mutation_uploadAsset(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_uploadAsset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().UploadAsset(rctx, fc.Args["input"].(UploadAssetInput)) + }) + 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.(*UploadAssetPayload) + fc.Result = res + return ec.marshalNUploadAssetPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUploadAssetPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_uploadAsset(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "asset": + return ec.fieldContext_UploadAssetPayload_asset(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type UploadAssetPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_uploadAsset_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_getAssetUploadURL(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_getAssetUploadURL(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().GetAssetUploadURL(rctx, fc.Args["input"].(GetAssetUploadURLInput)) + }) + 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.(*GetAssetUploadURLPayload) + fc.Result = res + return ec.marshalNGetAssetUploadURLPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐGetAssetUploadURLPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_getAssetUploadURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "uploadURL": + return ec.fieldContext_GetAssetUploadURLPayload_uploadURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type GetAssetUploadURLPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_getAssetUploadURL_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_updateAssetMetadata(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_updateAssetMetadata(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().UpdateAssetMetadata(rctx, fc.Args["input"].(UpdateAssetMetadataInput)) + }) + 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.(*UpdateAssetMetadataPayload) + fc.Result = res + return ec.marshalNUpdateAssetMetadataPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUpdateAssetMetadataPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_updateAssetMetadata(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "asset": + return ec.fieldContext_UpdateAssetMetadataPayload_asset(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type UpdateAssetMetadataPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_updateAssetMetadata_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_deleteAsset(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_deleteAsset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteAsset(rctx, fc.Args["input"].(DeleteAssetInput)) + }) + 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.(*DeleteAssetPayload) + fc.Result = res + return ec.marshalNDeleteAssetPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_deleteAsset(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "assetId": + return ec.fieldContext_DeleteAssetPayload_assetId(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DeleteAssetPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_deleteAsset_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_deleteAssets(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_deleteAssets(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteAssets(rctx, fc.Args["input"].(DeleteAssetsInput)) + }) + 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.(*DeleteAssetsPayload) + fc.Result = res + return ec.marshalNDeleteAssetsPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_deleteAssets(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "assetIds": + return ec.fieldContext_DeleteAssetsPayload_assetIds(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DeleteAssetsPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_deleteAssets_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_moveAsset(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_moveAsset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().MoveAsset(rctx, fc.Args["input"].(MoveAssetInput)) + }) + 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.(*MoveAssetPayload) + fc.Result = res + return ec.marshalNMoveAssetPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐMoveAssetPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_moveAsset(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "asset": + return ec.fieldContext_MoveAssetPayload_asset(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type MoveAssetPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_moveAsset_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_deleteAssetsInGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_deleteAssetsInGroup(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteAssetsInGroup(rctx, fc.Args["input"].(DeleteAssetsInGroupInput)) + }) + 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.(*DeleteAssetsInGroupPayload) + fc.Result = res + return ec.marshalNDeleteAssetsInGroupPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsInGroupPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_deleteAssetsInGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "groupId": + return ec.fieldContext_DeleteAssetsInGroupPayload_groupId(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DeleteAssetsInGroupPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_deleteAssetsInGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_asset(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_asset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Asset(rctx, fc.Args["id"].(string)) + }) + 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.(*Asset) + fc.Result = res + return ec.marshalNAsset2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAsset(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_asset(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Asset_id(ctx, field) + case "name": + return ec.fieldContext_Asset_name(ctx, field) + case "size": + return ec.fieldContext_Asset_size(ctx, field) + case "contentType": + return ec.fieldContext_Asset_contentType(ctx, field) + case "url": + return ec.fieldContext_Asset_url(ctx, field) + case "status": + return ec.fieldContext_Asset_status(ctx, field) + case "error": + return ec.fieldContext_Asset_error(ctx, field) + case "createdAt": + return ec.fieldContext_Asset_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_Asset_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Asset", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_asset_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_assets(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_assets(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Assets(rctx) + }) + 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.([]*Asset) + fc.Result = res + return ec.marshalNAsset2ᚕᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAssetᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_assets(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Asset_id(ctx, field) + case "name": + return ec.fieldContext_Asset_name(ctx, field) + case "size": + return ec.fieldContext_Asset_size(ctx, field) + case "contentType": + return ec.fieldContext_Asset_contentType(ctx, field) + case "url": + return ec.fieldContext_Asset_url(ctx, field) + case "status": + return ec.fieldContext_Asset_status(ctx, field) + case "error": + return ec.fieldContext_Asset_error(ctx, field) + case "createdAt": + return ec.fieldContext_Asset_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_Asset_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Asset", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query___type(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectType(fc.Args["name"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query___type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query___type_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query___schema(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectSchema() + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Schema) + fc.Result = res + return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query___schema(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "description": + return ec.fieldContext___Schema_description(ctx, field) + case "types": + return ec.fieldContext___Schema_types(ctx, field) + case "queryType": + return ec.fieldContext___Schema_queryType(ctx, field) + case "mutationType": + return ec.fieldContext___Schema_mutationType(ctx, field) + case "subscriptionType": + return ec.fieldContext___Schema_subscriptionType(ctx, field) + case "directives": + return ec.fieldContext___Schema_directives(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Schema", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _UpdateAssetMetadataPayload_asset(ctx context.Context, field graphql.CollectedField, obj *UpdateAssetMetadataPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_UpdateAssetMetadataPayload_asset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Asset, 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.(*Asset) + fc.Result = res + return ec.marshalNAsset2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAsset(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_UpdateAssetMetadataPayload_asset(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "UpdateAssetMetadataPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Asset_id(ctx, field) + case "name": + return ec.fieldContext_Asset_name(ctx, field) + case "size": + return ec.fieldContext_Asset_size(ctx, field) + case "contentType": + return ec.fieldContext_Asset_contentType(ctx, field) + case "url": + return ec.fieldContext_Asset_url(ctx, field) + case "status": + return ec.fieldContext_Asset_status(ctx, field) + case "error": + return ec.fieldContext_Asset_error(ctx, field) + case "createdAt": + return ec.fieldContext_Asset_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_Asset_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Asset", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _UploadAssetPayload_asset(ctx context.Context, field graphql.CollectedField, obj *UploadAssetPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_UploadAssetPayload_asset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Asset, 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.(*Asset) + fc.Result = res + return ec.marshalNAsset2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAsset(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_UploadAssetPayload_asset(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "UploadAssetPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Asset_id(ctx, field) + case "name": + return ec.fieldContext_Asset_name(ctx, field) + case "size": + return ec.fieldContext_Asset_size(ctx, field) + case "contentType": + return ec.fieldContext_Asset_contentType(ctx, field) + case "url": + return ec.fieldContext_Asset_url(ctx, field) + case "status": + return ec.fieldContext_Asset_status(ctx, field) + case "error": + return ec.fieldContext_Asset_error(ctx, field) + case "createdAt": + return ec.fieldContext_Asset_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_Asset_updatedAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Asset", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, 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.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), 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) fieldContext___Directive_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_locations(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Locations, 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.([]string) + fc.Result = res + return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_locations(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type __DirectiveLocation does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_args(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Args, 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.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_isRepeatable(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsRepeatable, 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.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, 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.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), 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) fieldContext___EnumValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_isDeprecated(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDeprecated(), 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.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_deprecationReason(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DeprecationReason(), 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) fieldContext___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, 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.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), 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) fieldContext___Field_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_args(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Args, 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.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_type(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, 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.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_isDeprecated(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDeprecated(), 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.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_deprecationReason(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DeprecationReason(), 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) fieldContext___Field_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, 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.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), 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) fieldContext___InputValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_type(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, 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.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_defaultValue(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DefaultValue, 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) fieldContext___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), 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) fieldContext___Schema_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_types(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Types(), 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.([]introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_types(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_queryType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.QueryType(), 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.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_queryType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_mutationType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MutationType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_mutationType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_subscriptionType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SubscriptionType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_directives(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Directives(), 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.([]introspection.Directive) + fc.Result = res + return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_directives(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Directive_name(ctx, field) + case "description": + return ec.fieldContext___Directive_description(ctx, field) + case "locations": + return ec.fieldContext___Directive_locations(ctx, field) + case "args": + return ec.fieldContext___Directive_args(ctx, field) + case "isRepeatable": + return ec.fieldContext___Directive_isRepeatable(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Directive", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_kind(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Kind(), 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.(string) + fc.Result = res + return ec.marshalN__TypeKind2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_kind(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type __TypeKind does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name(), 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) fieldContext___Type_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), 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) fieldContext___Type_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_fields(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Fields(fc.Args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Field) + fc.Result = res + return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_fields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Field_name(ctx, field) + case "description": + return ec.fieldContext___Field_description(ctx, field) + case "args": + return ec.fieldContext___Field_args(ctx, field) + case "type": + return ec.fieldContext___Field_type(ctx, field) + case "isDeprecated": + return ec.fieldContext___Field_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___Field_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Field", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Type_fields_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_interfaces(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Interfaces(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_interfaces(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_possibleTypes(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PossibleTypes(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_possibleTypes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_enumValues(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EnumValues(fc.Args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.EnumValue) + fc.Result = res + return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_enumValues(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___EnumValue_name(ctx, field) + case "description": + return ec.fieldContext___EnumValue_description(ctx, field) + case "isDeprecated": + return ec.fieldContext___EnumValue_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___EnumValue_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __EnumValue", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Type_enumValues_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_inputFields(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.InputFields(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_inputFields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_ofType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.OfType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_ofType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_specifiedByURL(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SpecifiedByURL(), 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) fieldContext___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputDeleteAssetInput(ctx context.Context, obj interface{}) (DeleteAssetInput, error) { + var it DeleteAssetInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"id"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "id": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.ID = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDeleteAssetsInGroupInput(ctx context.Context, obj interface{}) (DeleteAssetsInGroupInput, error) { + var it DeleteAssetsInGroupInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"groupId"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "groupId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("groupId")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.GroupID = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDeleteAssetsInput(ctx context.Context, obj interface{}) (DeleteAssetsInput, error) { + var it DeleteAssetsInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"ids"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "ids": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ids")) + data, err := ec.unmarshalNID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + it.Ids = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputGetAssetUploadURLInput(ctx context.Context, obj interface{}) (GetAssetUploadURLInput, error) { + var it GetAssetUploadURLInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"id"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "id": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.ID = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputMoveAssetInput(ctx context.Context, obj interface{}) (MoveAssetInput, error) { + var it MoveAssetInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"id", "toWorkspaceId", "toProjectId"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "id": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.ID = data + case "toWorkspaceId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("toWorkspaceId")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.ToWorkspaceID = data + case "toProjectId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("toProjectId")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.ToProjectID = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputUpdateAssetMetadataInput(ctx context.Context, obj interface{}) (UpdateAssetMetadataInput, error) { + var it UpdateAssetMetadataInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"id", "name", "size", "contentType"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "id": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.ID = data + case "name": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Name = data + case "size": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("size")) + data, err := ec.unmarshalNInt2int(ctx, v) + if err != nil { + return it, err + } + it.Size = data + case "contentType": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("contentType")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.ContentType = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputUploadAssetInput(ctx context.Context, obj interface{}) (UploadAssetInput, error) { + var it UploadAssetInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"id", "file"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "id": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.ID = data + case "file": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("file")) + data, err := ec.unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, v) + if err != nil { + return it, err + } + it.File = data + } + } + + return it, nil +} + +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var assetImplementors = []string{"Asset"} + +func (ec *executionContext) _Asset(ctx context.Context, sel ast.SelectionSet, obj *Asset) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, assetImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Asset") + case "id": + out.Values[i] = ec._Asset_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec._Asset_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "size": + out.Values[i] = ec._Asset_size(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "contentType": + out.Values[i] = ec._Asset_contentType(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "url": + out.Values[i] = ec._Asset_url(ctx, field, obj) + case "status": + out.Values[i] = ec._Asset_status(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "error": + out.Values[i] = ec._Asset_error(ctx, field, obj) + case "createdAt": + out.Values[i] = ec._Asset_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "updatedAt": + out.Values[i] = ec._Asset_updatedAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var deleteAssetPayloadImplementors = []string{"DeleteAssetPayload"} + +func (ec *executionContext) _DeleteAssetPayload(ctx context.Context, sel ast.SelectionSet, obj *DeleteAssetPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, deleteAssetPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DeleteAssetPayload") + case "assetId": + out.Values[i] = ec._DeleteAssetPayload_assetId(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var deleteAssetsInGroupPayloadImplementors = []string{"DeleteAssetsInGroupPayload"} + +func (ec *executionContext) _DeleteAssetsInGroupPayload(ctx context.Context, sel ast.SelectionSet, obj *DeleteAssetsInGroupPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, deleteAssetsInGroupPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DeleteAssetsInGroupPayload") + case "groupId": + out.Values[i] = ec._DeleteAssetsInGroupPayload_groupId(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var deleteAssetsPayloadImplementors = []string{"DeleteAssetsPayload"} + +func (ec *executionContext) _DeleteAssetsPayload(ctx context.Context, sel ast.SelectionSet, obj *DeleteAssetsPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, deleteAssetsPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DeleteAssetsPayload") + case "assetIds": + out.Values[i] = ec._DeleteAssetsPayload_assetIds(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var getAssetUploadURLPayloadImplementors = []string{"GetAssetUploadURLPayload"} + +func (ec *executionContext) _GetAssetUploadURLPayload(ctx context.Context, sel ast.SelectionSet, obj *GetAssetUploadURLPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, getAssetUploadURLPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("GetAssetUploadURLPayload") + case "uploadURL": + out.Values[i] = ec._GetAssetUploadURLPayload_uploadURL(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var moveAssetPayloadImplementors = []string{"MoveAssetPayload"} + +func (ec *executionContext) _MoveAssetPayload(ctx context.Context, sel ast.SelectionSet, obj *MoveAssetPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, moveAssetPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("MoveAssetPayload") + case "asset": + out.Values[i] = ec._MoveAssetPayload_asset(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var mutationImplementors = []string{"Mutation"} + +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Mutation", + }) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Mutation") + case "uploadAsset": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_uploadAsset(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "getAssetUploadURL": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_getAssetUploadURL(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "updateAssetMetadata": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_updateAssetMetadata(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deleteAsset": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_deleteAsset(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deleteAssets": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_deleteAssets(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "moveAsset": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_moveAsset(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deleteAssetsInGroup": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_deleteAssetsInGroup(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var queryImplementors = []string{"Query"} + +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Query", + }) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Query") + case "asset": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_asset(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "assets": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_assets(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "__type": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___type(ctx, field) + }) + case "__schema": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___schema(ctx, field) + }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var updateAssetMetadataPayloadImplementors = []string{"UpdateAssetMetadataPayload"} + +func (ec *executionContext) _UpdateAssetMetadataPayload(ctx context.Context, sel ast.SelectionSet, obj *UpdateAssetMetadataPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, updateAssetMetadataPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("UpdateAssetMetadataPayload") + case "asset": + out.Values[i] = ec._UpdateAssetMetadataPayload_asset(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var uploadAssetPayloadImplementors = []string{"UploadAssetPayload"} + +func (ec *executionContext) _UploadAssetPayload(ctx context.Context, sel ast.SelectionSet, obj *UploadAssetPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, uploadAssetPayloadImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("UploadAssetPayload") + case "asset": + out.Values[i] = ec._UploadAssetPayload_asset(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __DirectiveImplementors = []string{"__Directive"} + +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Directive") + case "name": + out.Values[i] = ec.___Directive_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___Directive_description(ctx, field, obj) + case "locations": + out.Values[i] = ec.___Directive_locations(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "args": + out.Values[i] = ec.___Directive_args(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "isRepeatable": + out.Values[i] = ec.___Directive_isRepeatable(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __EnumValueImplementors = []string{"__EnumValue"} + +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__EnumValue") + case "name": + out.Values[i] = ec.___EnumValue_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___EnumValue_description(ctx, field, obj) + case "isDeprecated": + out.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __FieldImplementors = []string{"__Field"} + +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Field") + case "name": + out.Values[i] = ec.___Field_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___Field_description(ctx, field, obj) + case "args": + out.Values[i] = ec.___Field_args(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "type": + out.Values[i] = ec.___Field_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "isDeprecated": + out.Values[i] = ec.___Field_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___Field_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __InputValueImplementors = []string{"__InputValue"} + +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__InputValue") + case "name": + out.Values[i] = ec.___InputValue_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___InputValue_description(ctx, field, obj) + case "type": + out.Values[i] = ec.___InputValue_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "defaultValue": + out.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __SchemaImplementors = []string{"__Schema"} + +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Schema") + case "description": + out.Values[i] = ec.___Schema_description(ctx, field, obj) + case "types": + out.Values[i] = ec.___Schema_types(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "queryType": + out.Values[i] = ec.___Schema_queryType(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "mutationType": + out.Values[i] = ec.___Schema_mutationType(ctx, field, obj) + case "subscriptionType": + out.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj) + case "directives": + out.Values[i] = ec.___Schema_directives(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __TypeImplementors = []string{"__Type"} + +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Type") + case "kind": + out.Values[i] = ec.___Type_kind(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec.___Type_name(ctx, field, obj) + case "description": + out.Values[i] = ec.___Type_description(ctx, field, obj) + case "fields": + out.Values[i] = ec.___Type_fields(ctx, field, obj) + case "interfaces": + out.Values[i] = ec.___Type_interfaces(ctx, field, obj) + case "possibleTypes": + out.Values[i] = ec.___Type_possibleTypes(ctx, field, obj) + case "enumValues": + out.Values[i] = ec.___Type_enumValues(ctx, field, obj) + case "inputFields": + out.Values[i] = ec.___Type_inputFields(ctx, field, obj) + case "ofType": + out.Values[i] = ec.___Type_ofType(ctx, field, obj) + case "specifiedByURL": + out.Values[i] = ec.___Type_specifiedByURL(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +// endregion **************************** object.gotpl **************************** + +// region ***************************** type.gotpl ***************************** + +func (ec *executionContext) marshalNAsset2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAsset(ctx context.Context, sel ast.SelectionSet, v Asset) graphql.Marshaler { + return ec._Asset(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAsset2ᚕᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAssetᚄ(ctx context.Context, sel ast.SelectionSet, v []*Asset) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNAsset2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAsset(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNAsset2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAsset(ctx context.Context, sel ast.SelectionSet, v *Asset) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._Asset(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNAssetStatus2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAssetStatus(ctx context.Context, v interface{}) (AssetStatus, error) { + var res AssetStatus + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNAssetStatus2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐAssetStatus(ctx context.Context, sel ast.SelectionSet, v AssetStatus) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNDeleteAssetInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetInput(ctx context.Context, v interface{}) (DeleteAssetInput, error) { + res, err := ec.unmarshalInputDeleteAssetInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDeleteAssetPayload2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetPayload(ctx context.Context, sel ast.SelectionSet, v DeleteAssetPayload) graphql.Marshaler { + return ec._DeleteAssetPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDeleteAssetPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetPayload(ctx context.Context, sel ast.SelectionSet, v *DeleteAssetPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DeleteAssetPayload(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNDeleteAssetsInGroupInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsInGroupInput(ctx context.Context, v interface{}) (DeleteAssetsInGroupInput, error) { + res, err := ec.unmarshalInputDeleteAssetsInGroupInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDeleteAssetsInGroupPayload2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsInGroupPayload(ctx context.Context, sel ast.SelectionSet, v DeleteAssetsInGroupPayload) graphql.Marshaler { + return ec._DeleteAssetsInGroupPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDeleteAssetsInGroupPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsInGroupPayload(ctx context.Context, sel ast.SelectionSet, v *DeleteAssetsInGroupPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DeleteAssetsInGroupPayload(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNDeleteAssetsInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsInput(ctx context.Context, v interface{}) (DeleteAssetsInput, error) { + res, err := ec.unmarshalInputDeleteAssetsInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDeleteAssetsPayload2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsPayload(ctx context.Context, sel ast.SelectionSet, v DeleteAssetsPayload) graphql.Marshaler { + return ec._DeleteAssetsPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDeleteAssetsPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐDeleteAssetsPayload(ctx context.Context, sel ast.SelectionSet, v *DeleteAssetsPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._DeleteAssetsPayload(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNGetAssetUploadURLInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐGetAssetUploadURLInput(ctx context.Context, v interface{}) (GetAssetUploadURLInput, error) { + res, err := ec.unmarshalInputGetAssetUploadURLInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNGetAssetUploadURLPayload2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐGetAssetUploadURLPayload(ctx context.Context, sel ast.SelectionSet, v GetAssetUploadURLPayload) graphql.Marshaler { + return ec._GetAssetUploadURLPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNGetAssetUploadURLPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐGetAssetUploadURLPayload(ctx context.Context, sel ast.SelectionSet, v *GetAssetUploadURLPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._GetAssetUploadURLPayload(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNID2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNID2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNID2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNID2string(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { + res, err := graphql.UnmarshalInt(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + res := graphql.MarshalInt(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNMoveAssetInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐMoveAssetInput(ctx context.Context, v interface{}) (MoveAssetInput, error) { + res, err := ec.unmarshalInputMoveAssetInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNMoveAssetPayload2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐMoveAssetPayload(ctx context.Context, sel ast.SelectionSet, v MoveAssetPayload) graphql.Marshaler { + return ec._MoveAssetPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNMoveAssetPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐMoveAssetPayload(ctx context.Context, sel ast.SelectionSet, v *MoveAssetPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._MoveAssetPayload(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { + res, err := graphql.UnmarshalTime(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { + res := graphql.MarshalTime(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNUpdateAssetMetadataInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUpdateAssetMetadataInput(ctx context.Context, v interface{}) (UpdateAssetMetadataInput, error) { + res, err := ec.unmarshalInputUpdateAssetMetadataInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNUpdateAssetMetadataPayload2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUpdateAssetMetadataPayload(ctx context.Context, sel ast.SelectionSet, v UpdateAssetMetadataPayload) graphql.Marshaler { + return ec._UpdateAssetMetadataPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNUpdateAssetMetadataPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUpdateAssetMetadataPayload(ctx context.Context, sel ast.SelectionSet, v *UpdateAssetMetadataPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._UpdateAssetMetadataPayload(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, v interface{}) (graphql.Upload, error) { + res, err := graphql.UnmarshalUpload(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, sel ast.SelectionSet, v graphql.Upload) graphql.Marshaler { + res := graphql.MarshalUpload(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNUploadAssetInput2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUploadAssetInput(ctx context.Context, v interface{}) (UploadAssetInput, error) { + res, err := ec.unmarshalInputUploadAssetInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNUploadAssetPayload2githubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUploadAssetPayload(ctx context.Context, sel ast.SelectionSet, v UploadAssetPayload) graphql.Marshaler { + return ec._UploadAssetPayload(ctx, sel, &v) +} + +func (ec *executionContext) marshalNUploadAssetPayload2ᚖgithubᚗcomᚋreearthᚋreearthxᚋassetᚋgraphqlᚐUploadAssetPayload(ctx context.Context, sel ast.SelectionSet, v *UploadAssetPayload) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._UploadAssetPayload(ctx, sel, v) +} + +func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { + return ec.___Directive(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { + return ec.___EnumValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { + return ec.___Field(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { + return ec.___InputValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { + return ec.___Type(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + return res +} + +func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalBoolean(*v) + return res +} + +func (ec *executionContext) unmarshalOID2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalID(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOID2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalID(*v) + return res +} + +func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalString(*v) + return res +} + +func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Schema(ctx, sel, v) +} + +func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +// endregion ***************************** type.gotpl ***************************** diff --git a/asset/graphql/gqlgen.yml b/asset/graphql/gqlgen.yml new file mode 100644 index 0000000..c206775 --- /dev/null +++ b/asset/graphql/gqlgen.yml @@ -0,0 +1,32 @@ +schema: + - schema.graphql + +exec: + filename: generated.go + package: graphql + +model: + filename: model.go + package: graphql + +resolver: + layout: follow-schema + dir: . + package: graphql + filename_template: "{name}.resolvers.go" + +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.ID + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + Int: + model: + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + Upload: + model: + - github.com/99designs/gqlgen/graphql.Upload \ No newline at end of file diff --git a/asset/graphql/helper.go b/asset/graphql/helper.go new file mode 100644 index 0000000..e960895 --- /dev/null +++ b/asset/graphql/helper.go @@ -0,0 +1,40 @@ +package graphql + +import ( + "io" + + "github.com/99designs/gqlgen/graphql" + "github.com/reearth/reearthx/asset/domain/entity" +) + +func FileFromUpload(file *graphql.Upload) io.Reader { + return file.File +} + +func AssetFromDomain(a *entity.Asset) *Asset { + if a == nil { + return nil + } + + var err *string + if e := a.Error(); e != "" { + err = &e + } + + var url *string + if u := a.URL(); u != "" { + url = &u + } + + return &Asset{ + ID: a.ID().String(), + Name: a.Name(), + Size: int(a.Size()), + ContentType: a.ContentType(), + URL: url, + Status: AssetStatus(a.Status()), + Error: err, + CreatedAt: a.CreatedAt(), + UpdatedAt: a.UpdatedAt(), + } +} diff --git a/asset/graphql/model.go b/asset/graphql/model.go new file mode 100644 index 0000000..b9d7bb3 --- /dev/null +++ b/asset/graphql/model.go @@ -0,0 +1,137 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package graphql + +import ( + "fmt" + "io" + "strconv" + "time" + + "github.com/99designs/gqlgen/graphql" +) + +type Asset struct { + ID string `json:"id"` + Name string `json:"name"` + Size int `json:"size"` + ContentType string `json:"contentType"` + URL *string `json:"url,omitempty"` + Status AssetStatus `json:"status"` + Error *string `json:"error,omitempty"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type DeleteAssetInput struct { + ID string `json:"id"` +} + +type DeleteAssetPayload struct { + AssetID string `json:"assetId"` +} + +type DeleteAssetsInGroupInput struct { + GroupID string `json:"groupId"` +} + +type DeleteAssetsInGroupPayload struct { + GroupID string `json:"groupId"` +} + +type DeleteAssetsInput struct { + Ids []string `json:"ids"` +} + +type DeleteAssetsPayload struct { + AssetIds []string `json:"assetIds"` +} + +type GetAssetUploadURLInput struct { + ID string `json:"id"` +} + +type GetAssetUploadURLPayload struct { + UploadURL string `json:"uploadURL"` +} + +type MoveAssetInput struct { + ID string `json:"id"` + ToWorkspaceID *string `json:"toWorkspaceId,omitempty"` + ToProjectID *string `json:"toProjectId,omitempty"` +} + +type MoveAssetPayload struct { + Asset *Asset `json:"asset"` +} + +type Mutation struct { +} + +type Query struct { +} + +type UpdateAssetMetadataInput struct { + ID string `json:"id"` + Name string `json:"name"` + Size int `json:"size"` + ContentType string `json:"contentType"` +} + +type UpdateAssetMetadataPayload struct { + Asset *Asset `json:"asset"` +} + +type UploadAssetInput struct { + ID string `json:"id"` + File graphql.Upload `json:"file"` +} + +type UploadAssetPayload struct { + Asset *Asset `json:"asset"` +} + +type AssetStatus string + +const ( + AssetStatusPending AssetStatus = "PENDING" + AssetStatusActive AssetStatus = "ACTIVE" + AssetStatusExtracting AssetStatus = "EXTRACTING" + AssetStatusError AssetStatus = "ERROR" +) + +var AllAssetStatus = []AssetStatus{ + AssetStatusPending, + AssetStatusActive, + AssetStatusExtracting, + AssetStatusError, +} + +func (e AssetStatus) IsValid() bool { + switch e { + case AssetStatusPending, AssetStatusActive, AssetStatusExtracting, AssetStatusError: + return true + } + return false +} + +func (e AssetStatus) String() string { + return string(e) +} + +func (e *AssetStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = AssetStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid AssetStatus", str) + } + return nil +} + +func (e AssetStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/asset/graphql/resolver.go b/asset/graphql/resolver.go new file mode 100644 index 0000000..45e95a0 --- /dev/null +++ b/asset/graphql/resolver.go @@ -0,0 +1,18 @@ +package graphql + +import ( + "github.com/reearth/reearthx/asset/repository" + assetusecase "github.com/reearth/reearthx/asset/usecase" +) + +type Resolver struct { + assetUsecase assetusecase.Usecase + pubsub repository.PubSubRepository +} + +func NewResolver(assetUsecase assetusecase.Usecase, pubsub repository.PubSubRepository) *Resolver { + return &Resolver{ + assetUsecase: assetUsecase, + pubsub: pubsub, + } +} diff --git a/asset/graphql/schema.graphql b/asset/graphql/schema.graphql new file mode 100644 index 0000000..9f397c4 --- /dev/null +++ b/asset/graphql/schema.graphql @@ -0,0 +1,113 @@ +type Asset { + id: ID! + name: String! + size: Int! + contentType: String! + url: String + status: AssetStatus! + error: String + createdAt: Time! + updatedAt: Time! +} + +enum AssetStatus { + PENDING + ACTIVE + EXTRACTING + ERROR +} + +scalar Time +scalar Upload + +type Query { + # Get a single asset by ID + asset(id: ID!): Asset! + # List all assets + assets: [Asset!]! +} + +type Mutation { + # Direct upload mutation + uploadAsset(input: UploadAssetInput!): UploadAssetPayload! + + # Get signed URL for upload + getAssetUploadURL(input: GetAssetUploadURLInput!): GetAssetUploadURLPayload! + + # Update asset metadata after signed URL upload + updateAssetMetadata(input: UpdateAssetMetadataInput!): UpdateAssetMetadataPayload! + + # Delete a single asset + deleteAsset(input: DeleteAssetInput!): DeleteAssetPayload! + + # Delete multiple assets + deleteAssets(input: DeleteAssetsInput!): DeleteAssetsPayload! + + # Move asset to another workspace/project + moveAsset(input: MoveAssetInput!): MoveAssetPayload! + + # Delete all assets in a group + deleteAssetsInGroup(input: DeleteAssetsInGroupInput!): DeleteAssetsInGroupPayload! +} + +input UploadAssetInput { + id: ID! + file: Upload! +} + +type UploadAssetPayload { + asset: Asset! +} + +input GetAssetUploadURLInput { + id: ID! +} + +type GetAssetUploadURLPayload { + uploadURL: String! +} + +input UpdateAssetMetadataInput { + id: ID! + name: String! + size: Int! + contentType: String! +} + +type UpdateAssetMetadataPayload { + asset: Asset! +} + +input DeleteAssetInput { + id: ID! +} + +type DeleteAssetPayload { + assetId: ID! +} + +input DeleteAssetsInput { + ids: [ID!]! +} + +type DeleteAssetsPayload { + assetIds: [ID!]! +} + +input MoveAssetInput { + id: ID! + toWorkspaceId: ID + toProjectId: ID +} + +type MoveAssetPayload { + asset: Asset! +} + +input DeleteAssetsInGroupInput { + groupId: ID! +} + +type DeleteAssetsInGroupPayload { + groupId: ID! +} \ No newline at end of file diff --git a/asset/graphql/schema.resolvers.go b/asset/graphql/schema.resolvers.go new file mode 100644 index 0000000..6778595 --- /dev/null +++ b/asset/graphql/schema.resolvers.go @@ -0,0 +1,229 @@ +package graphql + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.43 + +import ( + "context" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" +) + +// UploadAsset is the resolver for the uploadAsset field. +func (r *mutationResolver) UploadAsset(ctx context.Context, input UploadAssetInput) (*UploadAssetPayload, error) { + assetID, err := id.From(input.ID) + if err != nil { + return nil, err + } + + // Create asset metadata + asset := entity.NewAsset( + assetID, + input.File.Filename, + input.File.Size, + input.File.ContentType, + ) + + // Create asset metadata first + result := r.assetUsecase.CreateAsset(ctx, asset) + if !result.IsSuccess() { + return nil, result + } + + // Upload file content + result = r.assetUsecase.UploadAssetContent(ctx, assetID, FileFromUpload(&input.File)) + if !result.IsSuccess() { + return nil, result + } + + // Update asset status to active + asset.UpdateStatus(entity.StatusActive, "") + result = r.assetUsecase.UpdateAsset(ctx, asset) + if !result.IsSuccess() { + return nil, result + } + + return &UploadAssetPayload{ + Asset: AssetFromDomain(asset), + }, nil +} + +// GetAssetUploadURL is the resolver for the getAssetUploadURL field. +func (r *mutationResolver) GetAssetUploadURL(ctx context.Context, input GetAssetUploadURLInput) (*GetAssetUploadURLPayload, error) { + assetID, err := id.From(input.ID) + if err != nil { + return nil, err + } + + result := r.assetUsecase.GetAssetUploadURL(ctx, assetID) + if !result.IsSuccess() { + return nil, result + } + + return &GetAssetUploadURLPayload{ + UploadURL: result.Data.(string), + }, nil +} + +// UpdateAssetMetadata is the resolver for the updateAssetMetadata field. +func (r *mutationResolver) UpdateAssetMetadata(ctx context.Context, input UpdateAssetMetadataInput) (*UpdateAssetMetadataPayload, error) { + assetID, err := id.From(input.ID) + if err != nil { + return nil, err + } + + result := r.assetUsecase.GetAsset(ctx, assetID) + if !result.IsSuccess() { + return nil, result + } + asset := result.Data.(*entity.Asset) + + asset.UpdateMetadata(input.Name, "", input.ContentType) + asset.SetSize(int64(input.Size)) + result = r.assetUsecase.UpdateAsset(ctx, asset) + if !result.IsSuccess() { + return nil, result + } + + return &UpdateAssetMetadataPayload{ + Asset: AssetFromDomain(asset), + }, nil +} + +// DeleteAsset is the resolver for the deleteAsset field. +func (r *mutationResolver) DeleteAsset(ctx context.Context, input DeleteAssetInput) (*DeleteAssetPayload, error) { + assetID, err := id.From(input.ID) + if err != nil { + return nil, err + } + + result := r.assetUsecase.DeleteAsset(ctx, assetID) + if !result.IsSuccess() { + return nil, result + } + + return &DeleteAssetPayload{ + AssetID: input.ID, + }, nil +} + +// DeleteAssets is the resolver for the deleteAssets field. +func (r *mutationResolver) DeleteAssets(ctx context.Context, input DeleteAssetsInput) (*DeleteAssetsPayload, error) { + var assetIDs []id.ID + for _, idStr := range input.Ids { + assetID, err := id.From(idStr) + if err != nil { + return nil, err + } + assetIDs = append(assetIDs, assetID) + } + + for _, assetID := range assetIDs { + result := r.assetUsecase.DeleteAsset(ctx, assetID) + if !result.IsSuccess() { + return nil, result + } + } + + return &DeleteAssetsPayload{ + AssetIds: input.Ids, + }, nil +} + +// MoveAsset is the resolver for the moveAsset field. +func (r *mutationResolver) MoveAsset(ctx context.Context, input MoveAssetInput) (*MoveAssetPayload, error) { + assetID, err := id.From(input.ID) + if err != nil { + return nil, err + } + + result := r.assetUsecase.GetAsset(ctx, assetID) + if !result.IsSuccess() { + return nil, result + } + asset := result.Data.(*entity.Asset) + + if input.ToWorkspaceID != nil { + wsID, err := id.WorkspaceIDFrom(*input.ToWorkspaceID) + if err != nil { + return nil, err + } + asset.MoveToWorkspace(wsID) + } + + if input.ToProjectID != nil { + projID, err := id.ProjectIDFrom(*input.ToProjectID) + if err != nil { + return nil, err + } + asset.MoveToProject(projID) + } + + result = r.assetUsecase.UpdateAsset(ctx, asset) + if !result.IsSuccess() { + return nil, result + } + + return &MoveAssetPayload{ + Asset: AssetFromDomain(asset), + }, nil +} + +// DeleteAssetsInGroup is the resolver for the deleteAssetsInGroup field. +func (r *mutationResolver) DeleteAssetsInGroup(ctx context.Context, input DeleteAssetsInGroupInput) (*DeleteAssetsInGroupPayload, error) { + groupID, err := id.GroupIDFrom(input.GroupID) + if err != nil { + return nil, err + } + + result := r.assetUsecase.DeleteAllAssetsInGroup(ctx, groupID) + if !result.IsSuccess() { + return nil, result + } + + return &DeleteAssetsInGroupPayload{ + GroupID: input.GroupID, + }, nil +} + +// Asset is the resolver for the asset field. +func (r *queryResolver) Asset(ctx context.Context, assetID string) (*Asset, error) { + aid, err := id.From(assetID) + if err != nil { + return nil, err + } + + result := r.assetUsecase.GetAsset(ctx, aid) + if !result.IsSuccess() { + return nil, result + } + + return AssetFromDomain(result.Data.(*entity.Asset)), nil +} + +// Assets is the resolver for the assets field. +func (r *queryResolver) Assets(ctx context.Context) ([]*Asset, error) { + result := r.assetUsecase.ListAssets(ctx) + if !result.IsSuccess() { + return nil, result + } + + assets := result.Data.([]*entity.Asset) + graphqlAssets := make([]*Asset, len(assets)) + for i, asset := range assets { + graphqlAssets[i] = AssetFromDomain(asset) + } + + return graphqlAssets, nil +} + +// Mutation returns MutationResolver implementation. +func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } + +// Query returns QueryResolver implementation. +func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } + +type mutationResolver struct{ *Resolver } +type queryResolver struct{ *Resolver } diff --git a/asset/infrastructure/decompress/zip.go b/asset/infrastructure/decompress/zip.go new file mode 100644 index 0000000..03e12c1 --- /dev/null +++ b/asset/infrastructure/decompress/zip.go @@ -0,0 +1,220 @@ +// Package decompress provides functionality for decompressing various file formats. +package decompress + +import ( + "archive/zip" + "bytes" + "context" + "fmt" + "io" + "path/filepath" + "sync" + + "github.com/reearth/reearthx/log" + "go.uber.org/zap" + + "github.com/reearth/reearthx/asset/repository" +) + +// ZipDecompressor handles decompression of zip files. +type ZipDecompressor struct{} + +var _ repository.Decompressor = (*ZipDecompressor)(nil) + +// NewZipDecompressor creates a new zip decompressor +func NewZipDecompressor() repository.Decompressor { + return &ZipDecompressor{} +} + +// DecompressWithContent decompresses zip content directly. +// It processes each file asynchronously and returns a channel of decompressed files. +func (d *ZipDecompressor) DecompressWithContent(ctx context.Context, content []byte) (<-chan repository.DecompressedFile, error) { + zipReader, err := zip.NewReader(bytes.NewReader(content), int64(len(content))) + if err != nil { + return nil, fmt.Errorf("failed to create zip reader: %w", err) + } + + // Create a buffered channel to hold the decompressed files + resultChan := make(chan repository.DecompressedFile, len(zipReader.File)) + var wg sync.WaitGroup + + // Process files in a separate goroutine to avoid race conditions + go func() { + for _, f := range zipReader.File { + if f.FileInfo().IsDir() || isHiddenFile(f.Name) { + continue + } + + wg.Add(1) + go d.processZipFile(ctx, f, resultChan, &wg) + } + + // Wait for all files to be processed before closing the channel + wg.Wait() + close(resultChan) + }() + + return resultChan, nil +} + +// processZipFile handles processing of a single zip file entry +func (d *ZipDecompressor) processZipFile(ctx context.Context, f *zip.File, resultChan chan<- repository.DecompressedFile, wg *sync.WaitGroup) { + defer wg.Done() + + select { + case <-ctx.Done(): + resultChan <- repository.DecompressedFile{ + Name: f.Name, + Error: ctx.Err(), + } + return + default: + content, err := d.processFile(f) + if err != nil { + resultChan <- repository.DecompressedFile{ + Name: f.Name, + Error: err, + } + return + } + + resultChan <- repository.DecompressedFile{ + Name: f.Name, + Content: content, + } + } +} + +// processFile handles a single file from the zip archive +func (d *ZipDecompressor) processFile(f *zip.File) (io.Reader, error) { + rc, err := f.Open() + if err != nil { + return nil, fmt.Errorf("failed to open file in zip: %w", err) + } + defer func(rc io.ReadCloser) { + err := rc.Close() + if err != nil { + log.Warn("failed to close file in zip", zap.Error(err)) + } + }(rc) + + // Read the entire file content into memory + content, err := io.ReadAll(rc) + if err != nil { + return nil, fmt.Errorf("failed to read file content: %w", err) + } + + return bytes.NewReader(content), nil +} + +// CompressWithContent compresses the provided content into a zip archive. +// It takes a map of filenames to their content readers and returns a channel that will receive the compressed bytes. +// The channel will be closed when compression is complete or if an error occurs. +func (d *ZipDecompressor) CompressWithContent(ctx context.Context, files map[string]io.Reader) (<-chan repository.CompressResult, error) { + resultChan := make(chan repository.CompressResult, 1) + + go func() { + defer close(resultChan) + + select { + case <-ctx.Done(): + resultChan <- repository.CompressResult{Error: ctx.Err()} + return + default: + } + + buf := new(bytes.Buffer) + zipWriter := zip.NewWriter(buf) + defer func(zipWriter *zip.Writer) { + err := zipWriter.Close() + if err != nil { + log.Warn("failed to close zip writer", zap.Error(err)) + } + }(zipWriter) + + // Use a mutex to protect concurrent writes to the zip writer + var mu sync.Mutex + var wg sync.WaitGroup + errChan := make(chan error, 1) + + // Process each file sequentially to avoid corruption + for filename, content := range files { + select { + case <-ctx.Done(): + resultChan <- repository.CompressResult{Error: ctx.Err()} + return + default: + } + + wg.Add(1) + go func(filename string, content io.Reader) { + defer wg.Done() + + // Read the entire content first to avoid holding the lock during I/O + data, err := io.ReadAll(content) + if err != nil { + select { + case errChan <- fmt.Errorf("failed to read content: %w", err): + default: + } + return + } + + mu.Lock() + err = d.addFileToZip(zipWriter, filename, bytes.NewReader(data)) + mu.Unlock() + + if err != nil { + select { + case errChan <- err: + default: + } + } + }(filename, content) + } + + // Wait for all goroutines to finish + done := make(chan struct{}) + go func() { + wg.Wait() + close(done) + }() + + // Wait for either completion or error + select { + case <-ctx.Done(): + resultChan <- repository.CompressResult{Error: ctx.Err()} + case err := <-errChan: + resultChan <- repository.CompressResult{Error: err} + case <-done: + if err := zipWriter.Close(); err != nil { + resultChan <- repository.CompressResult{Error: fmt.Errorf("failed to close zip writer: %w", err)} + return + } + resultChan <- repository.CompressResult{Content: buf.Bytes()} + } + }() + + return resultChan, nil +} + +// addFileToZip adds a single file to the zip archive +// Note: This function is not thread-safe and should be protected by a mutex +func (d *ZipDecompressor) addFileToZip(zipWriter *zip.Writer, filename string, content io.Reader) error { + writer, err := zipWriter.Create(filename) + if err != nil { + return fmt.Errorf("failed to create file in zip: %w", err) + } + + if _, err := io.Copy(writer, content); err != nil { + return fmt.Errorf("failed to write content: %w", err) + } + + return nil +} + +// isHiddenFile checks if a file is hidden (starts with a dot). +func isHiddenFile(name string) bool { + base := filepath.Base(name) + return len(base) > 0 && base[0] == '.' +} diff --git a/asset/infrastructure/decompress/zip_test.go b/asset/infrastructure/decompress/zip_test.go new file mode 100644 index 0000000..74119a2 --- /dev/null +++ b/asset/infrastructure/decompress/zip_test.go @@ -0,0 +1,149 @@ +package decompress + +import ( + "context" + "io" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestZipDecompressor_DecompressWithContent(t *testing.T) { + // Create test data + files := map[string]string{ + "test1.txt": "Hello, World!", + "test2.txt": "This is a test file", + ".hidden": "This should be skipped", + } + + // Create a zip file + zipContent, err := createTestZip(files) + assert.NoError(t, err) + + // Create decompressor + d := NewZipDecompressor() + + // Test decompression + ctx := context.Background() + resultChan, err := d.DecompressWithContent(ctx, zipContent) + assert.NoError(t, err) + + // Collect results + results := make(map[string]string) + for file := range resultChan { + assert.NoError(t, file.Error) + if file.Error != nil { + continue + } + + content, err := io.ReadAll(file.Content) + assert.NoError(t, err) + results[file.Name] = string(content) + } + + // Verify results + assert.Equal(t, 2, len(results)) // .hidden should be skipped + assert.Equal(t, "Hello, World!", results["test1.txt"]) + assert.Equal(t, "This is a test file", results["test2.txt"]) +} + +func TestZipDecompressor_CompressWithContent(t *testing.T) { + // Create test data with small files to avoid memory issues + files := map[string]io.Reader{ + "test1.txt": strings.NewReader("Hello, World!"), + "test2.txt": strings.NewReader("This is a test file"), + } + + // Create decompressor + d := NewZipDecompressor() + + // Test compression + ctx := context.Background() + compressChan, err := d.CompressWithContent(ctx, files) + assert.NoError(t, err) + + // Get compression result + result := <-compressChan + assert.NoError(t, result.Error) + compressed := result.Content + + // Test decompression of the compressed content + resultChan, err := d.DecompressWithContent(ctx, compressed) + assert.NoError(t, err) + + // Collect and verify results + results := make(map[string]string) + for file := range resultChan { + assert.NoError(t, file.Error) + if file.Error != nil { + continue + } + + content, err := io.ReadAll(file.Content) + assert.NoError(t, err) + results[file.Name] = string(content) + } + + assert.Equal(t, 2, len(results)) + assert.Equal(t, "Hello, World!", results["test1.txt"]) + assert.Equal(t, "This is a test file", results["test2.txt"]) +} + +func TestZipDecompressor_ContextCancellation(t *testing.T) { + // Create test data + files := map[string]string{ + "test1.txt": "Hello, World!", + "test2.txt": "This is a test file", + } + + // Create a zip file + zipContent, err := createTestZip(files) + assert.NoError(t, err) + + // Create decompressor + d := NewZipDecompressor() + + // Create a context that's already cancelled + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + // Test decompression with cancelled context + resultChan, err := d.DecompressWithContent(ctx, zipContent) + assert.NoError(t, err) + + // Verify that all files return context cancelled error + for file := range resultChan { + assert.Error(t, file.Error) + assert.Equal(t, context.Canceled, file.Error) + } +} + +func TestZipDecompressor_InvalidZip(t *testing.T) { + d := NewZipDecompressor() + ctx := context.Background() + + // Test with invalid zip content + _, err := d.DecompressWithContent(ctx, []byte("invalid zip content")) + assert.Error(t, err) +} + +// Helper function to create a test zip file +func createTestZip(files map[string]string) ([]byte, error) { + d := NewZipDecompressor() + ctx := context.Background() + + // Convert string content to io.Reader + readers := make(map[string]io.Reader) + for name, content := range files { + readers[name] = strings.NewReader(content) + } + + compressChan, err := d.CompressWithContent(ctx, readers) + if err != nil { + return nil, err + } + + result := <-compressChan + return result.Content, result.Error +} diff --git a/asset/infrastructure/gcs/client.go b/asset/infrastructure/gcs/client.go new file mode 100644 index 0000000..03d8714 --- /dev/null +++ b/asset/infrastructure/gcs/client.go @@ -0,0 +1,314 @@ +package gcs + +import ( + "context" + "errors" + "fmt" + "io" + "net/url" + "path" + "strings" + "time" + + "cloud.google.com/go/storage" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/reearth/reearthx/asset/repository" + "google.golang.org/api/iterator" +) + +var ( + ErrFailedToCreateClient = errors.New("failed to create client") + ErrAssetAlreadyExists = errors.New("asset already exists") + ErrAssetNotFound = errors.New("asset not found") + ErrFailedToUpdateAsset = errors.New("failed to update asset") + ErrFailedToDeleteAsset = errors.New("failed to delete asset") + ErrFailedToListAssets = errors.New("failed to list assets") + ErrFailedToUploadFile = errors.New("failed to upload file") + ErrFailedToCloseWriter = errors.New("failed to close writer") + ErrFailedToReadFile = errors.New("failed to read file") + ErrFailedToGetAsset = errors.New("failed to get asset") + ErrFailedToGenerateURL = errors.New("failed to generate upload URL") + ErrFailedToMoveAsset = errors.New("failed to move asset") + ErrInvalidURL = errors.New("invalid URL format") +) + +type Client struct { + bucket *storage.BucketHandle + bucketName string + basePath string + baseURL *url.URL +} + +var _ repository.PersistenceRepository = (*Client)(nil) + +func NewClient(ctx context.Context, bucketName string, basePath string, baseURL string) (*Client, error) { + client, err := storage.NewClient(ctx) + if err != nil { + return nil, fmt.Errorf("%w: %v", ErrFailedToCreateClient, err) + } + + var u *url.URL + if baseURL != "" { + u, err = url.Parse(baseURL) + if err != nil { + return nil, fmt.Errorf("%w: %v", ErrInvalidURL, err) + } + } + + return &Client{ + bucket: client.Bucket(bucketName), + bucketName: bucketName, + basePath: basePath, + baseURL: u, + }, nil +} + +func (c *Client) Create(ctx context.Context, asset *entity.Asset) error { + obj := c.getObject(asset.ID()) + attrs := storage.ObjectAttrs{ + Metadata: map[string]string{ + "name": asset.Name(), + "content_type": asset.ContentType(), + }, + } + + if _, err := obj.Attrs(ctx); err == nil { + return fmt.Errorf("%w: %s", ErrAssetAlreadyExists, asset.ID()) + } + + writer := obj.NewWriter(ctx) + writer.ObjectAttrs = attrs + return writer.Close() +} + +func (c *Client) Read(ctx context.Context, id id.ID) (*entity.Asset, error) { + attrs, err := c.getObject(id).Attrs(ctx) + if err != nil { + return nil, c.handleNotFound(err, id) + } + + asset := entity.NewAsset( + id, + attrs.Metadata["name"], + attrs.Size, + attrs.ContentType, + ) + + return asset, nil +} + +func (c *Client) Update(ctx context.Context, asset *entity.Asset) error { + obj := c.getObject(asset.ID()) + update := storage.ObjectAttrsToUpdate{ + Metadata: map[string]string{ + "name": asset.Name(), + "content_type": asset.ContentType(), + }, + } + + if _, err := obj.Update(ctx, update); err != nil { + return fmt.Errorf("%w: %v", ErrFailedToUpdateAsset, err) + } + return nil +} + +func (c *Client) Delete(ctx context.Context, id id.ID) error { + obj := c.getObject(id) + if err := obj.Delete(ctx); err != nil { + if errors.Is(err, storage.ErrObjectNotExist) { + return nil + } + return fmt.Errorf("%w: %v", ErrFailedToDeleteAsset, err) + } + return nil +} + +func (c *Client) List(ctx context.Context) ([]*entity.Asset, error) { + var assets []*entity.Asset + it := c.bucket.Objects(ctx, &storage.Query{Prefix: c.basePath}) + + for { + attrs, err := it.Next() + if errors.Is(err, iterator.Done) { + break + } + if err != nil { + return nil, fmt.Errorf("%w: %v", ErrFailedToListAssets, err) + } + + id, err := id.From(path.Base(attrs.Name)) + if err != nil { + continue // skip invalid IDs + } + + asset := entity.NewAsset( + id, + attrs.Metadata["name"], + attrs.Size, + attrs.ContentType, + ) + assets = append(assets, asset) + } + + return assets, nil +} + +func (c *Client) Upload(ctx context.Context, id id.ID, content io.Reader) error { + obj := c.getObject(id) + writer := obj.NewWriter(ctx) + + if _, err := io.Copy(writer, content); err != nil { + _ = writer.Close() + return fmt.Errorf("%w: %v", ErrFailedToUploadFile, err) + } + + if err := writer.Close(); err != nil { + return fmt.Errorf("%w: %v", ErrFailedToCloseWriter, err) + } + return nil +} + +func (c *Client) Download(ctx context.Context, id id.ID) (io.ReadCloser, error) { + obj := c.getObject(id) + reader, err := obj.NewReader(ctx) + if err != nil { + if errors.Is(err, storage.ErrObjectNotExist) { + return nil, fmt.Errorf("%w: %s", ErrAssetNotFound, id) + } + return nil, fmt.Errorf("%w: %v", ErrFailedToReadFile, err) + } + return reader, nil +} + +func (c *Client) GetUploadURL(ctx context.Context, id id.ID) (string, error) { + opts := &storage.SignedURLOptions{ + Method: "PUT", + Expires: time.Now().Add(15 * time.Minute), + } + + signedURL, err := c.bucket.SignedURL(c.objectPath(id), opts) + if err != nil { + return "", fmt.Errorf("%w: %v", ErrFailedToGenerateURL, err) + } + return signedURL, nil +} + +func (c *Client) Move(ctx context.Context, fromID, toID id.ID) error { + src := c.getObject(fromID) + dst := c.getObject(toID) + + if _, err := dst.CopierFrom(src).Run(ctx); err != nil { + return fmt.Errorf("%w: %v", ErrFailedToMoveAsset, err) + } + + if err := src.Delete(ctx); err != nil { + return fmt.Errorf("%w: %v", ErrFailedToMoveAsset, err) + } + + return nil +} + +func (c *Client) DeleteAll(ctx context.Context, prefix string) error { + it := c.bucket.Objects(ctx, &storage.Query{ + Prefix: path.Join(c.basePath, prefix), + }) + + for { + attrs, err := it.Next() + if errors.Is(err, iterator.Done) { + break + } + if err != nil { + return fmt.Errorf("%w: %v", ErrFailedToDeleteAsset, err) + } + + if err := c.bucket.Object(attrs.Name).Delete(ctx); err != nil { + if !errors.Is(err, storage.ErrObjectNotExist) { + return fmt.Errorf("%w: %v", ErrFailedToDeleteAsset, err) + } + } + } + return nil +} + +func (c *Client) GetObjectURL(id id.ID) string { + if c.baseURL == nil { + return "" + } + u := *c.baseURL + u.Path = path.Join(u.Path, c.objectPath(id)) + return u.String() +} + +func (c *Client) GetIDFromURL(urlStr string) (id.ID, error) { + emptyID := id.NewID() + + if c.baseURL == nil { + return emptyID, fmt.Errorf("%w: base URL not set", ErrInvalidURL) + } + + u, err := url.Parse(urlStr) + if err != nil { + return emptyID, fmt.Errorf("%w: %v", ErrInvalidURL, err) + } + + if u.Host != c.baseURL.Host { + return emptyID, fmt.Errorf("%w: host mismatch", ErrInvalidURL) + } + + urlPath := strings.TrimPrefix(u.Path, c.baseURL.Path) + urlPath = strings.TrimPrefix(urlPath, "/") + urlPath = strings.TrimPrefix(urlPath, c.basePath) + urlPath = strings.TrimPrefix(urlPath, "/") + + return id.From(urlPath) +} + +func (c *Client) getObject(id id.ID) *storage.ObjectHandle { + return c.bucket.Object(c.objectPath(id)) +} + +func (c *Client) objectPath(id id.ID) string { + return path.Join(c.basePath, id.String()) +} + +func (c *Client) handleNotFound(err error, id id.ID) error { + if errors.Is(err, storage.ErrObjectNotExist) { + return fmt.Errorf("%w: %s", ErrAssetNotFound, id) + } + return fmt.Errorf("%w: %v", ErrFailedToGetAsset, err) +} + +func (c *Client) FindByGroup(ctx context.Context, groupID id.GroupID) ([]*entity.Asset, error) { + var assets []*entity.Asset + it := c.bucket.Objects(ctx, &storage.Query{Prefix: c.basePath}) + + for { + attrs, err := it.Next() + if errors.Is(err, iterator.Done) { + break + } + if err != nil { + return nil, fmt.Errorf("%w: %v", ErrFailedToListAssets, err) + } + + assetID, err := id.From(path.Base(attrs.Name)) + if err != nil { + continue // skip invalid IDs + } + + asset := entity.NewAsset( + assetID, + attrs.Metadata["name"], + attrs.Size, + attrs.ContentType, + ) + + if asset.GroupID() == groupID { + assets = append(assets, asset) + } + } + + return assets, nil +} diff --git a/asset/infrastructure/gcs/client_test.go b/asset/infrastructure/gcs/client_test.go new file mode 100644 index 0000000..94540d0 --- /dev/null +++ b/asset/infrastructure/gcs/client_test.go @@ -0,0 +1,735 @@ +package gcs + +import ( + "bytes" + "context" + "fmt" + "io" + "net/url" + "path" + "strings" + "testing" + + "cloud.google.com/go/storage" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/stretchr/testify/assert" +) + +type mockBucketHandle struct { + objects map[string]*mockObject +} + +type mockObject struct { + data []byte + attrs *storage.ObjectAttrs + bucket *mockBucketHandle + name string +} + +func (o *mockObject) Delete(context.Context) error { + delete(o.bucket.objects, o.name) + return nil +} + +func (o *mockObject) Attrs(context.Context) (*storage.ObjectAttrs, error) { + if o.attrs == nil { + return nil, storage.ErrObjectNotExist + } + return o.attrs, nil +} + +func (o *mockObject) NewReader(context.Context) (io.ReadCloser, error) { + if o.data == nil { + return nil, storage.ErrObjectNotExist + } + return &mockReader{bytes.NewReader(o.data)}, nil +} + +func (o *mockObject) NewWriter(context.Context) io.WriteCloser { + return &mockWriter{ + buf: bytes.NewBuffer(nil), + bucket: o.bucket, + objectName: o.name, + attrs: o.attrs, + } +} + +func (o *mockObject) Update(ctx context.Context, uattrs storage.ObjectAttrsToUpdate) (*storage.ObjectAttrs, error) { + if o.attrs == nil { + return nil, storage.ErrObjectNotExist + } + if uattrs.Metadata != nil { + o.attrs.Metadata = uattrs.Metadata + } + return o.attrs, nil +} + +func (o *mockObject) CopierFrom(src *storage.ObjectHandle) *storage.Copier { + return &storage.Copier{} +} + +type mockReader struct { + *bytes.Reader +} + +func (r *mockReader) Close() error { + return nil +} + +type mockWriter struct { + buf *bytes.Buffer + attrs *storage.ObjectAttrs + bucket *mockBucketHandle + objectName string +} + +func (w *mockWriter) Write(p []byte) (int, error) { + return w.buf.Write(p) +} + +func (w *mockWriter) Close() error { + obj := w.bucket.objects[w.objectName] + obj.data = w.buf.Bytes() + obj.attrs = w.attrs + return nil +} + +func newMockBucketHandle() *mockBucketHandle { + return &mockBucketHandle{ + objects: make(map[string]*mockObject), + } +} + +type testClient struct { + *Client + mockBucket *mockBucketHandle +} + +func newTestClient(_ *testing.T) *testClient { + mockBucket := newMockBucketHandle() + client := &Client{ + bucketName: "test-bucket", + basePath: "test-path", + baseURL: &url.URL{ + Scheme: "https", + Host: "storage.googleapis.com", + }, + } + return &testClient{ + Client: client, + mockBucket: mockBucket, + } +} + +func (c *testClient) Create(ctx context.Context, asset *entity.Asset) error { + objPath := c.objectPath(asset.ID()) + if _, exists := c.mockBucket.objects[objPath]; exists { + return fmt.Errorf("%w: %s", ErrAssetAlreadyExists, asset.ID()) + } + + c.mockBucket.objects[objPath] = &mockObject{ + bucket: c.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: map[string]string{ + "name": asset.Name(), + "content_type": asset.ContentType(), + }, + }, + } + return nil +} + +func (c *testClient) Read(ctx context.Context, id id.ID) (*entity.Asset, error) { + objPath := c.objectPath(id) + obj, exists := c.mockBucket.objects[objPath] + if !exists { + return nil, fmt.Errorf("%w: %s", ErrAssetNotFound, id) + } + + return entity.NewAsset( + id, + obj.attrs.Metadata["name"], + int64(len(obj.data)), + obj.attrs.Metadata["content_type"], + ), nil +} + +func (c *testClient) Update(ctx context.Context, asset *entity.Asset) error { + objPath := c.objectPath(asset.ID()) + obj, exists := c.mockBucket.objects[objPath] + if !exists { + return fmt.Errorf("%w: %s", ErrAssetNotFound, asset.ID()) + } + + obj.attrs.Metadata["name"] = asset.Name() + obj.attrs.Metadata["content_type"] = asset.ContentType() + return nil +} + +func (c *testClient) Delete(ctx context.Context, id id.ID) error { + objPath := c.objectPath(id) + delete(c.mockBucket.objects, objPath) + return nil +} + +func (c *testClient) Upload(ctx context.Context, id id.ID, content io.Reader) error { + objPath := c.objectPath(id) + data, err := io.ReadAll(content) + if err != nil { + return err + } + + obj, exists := c.mockBucket.objects[objPath] + if !exists { + obj = &mockObject{ + bucket: c.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: make(map[string]string), + }, + } + c.mockBucket.objects[objPath] = obj + } + + obj.data = data + return nil +} + +func (c *testClient) Download(ctx context.Context, id id.ID) (io.ReadCloser, error) { + objPath := c.objectPath(id) + obj, exists := c.mockBucket.objects[objPath] + if !exists { + return nil, fmt.Errorf("%w: %s", ErrAssetNotFound, id) + } + + return &mockReader{bytes.NewReader(obj.data)}, nil +} + +func (c *testClient) GetUploadURL(ctx context.Context, id id.ID) (string, error) { + return fmt.Sprintf("https://storage.googleapis.com/%s", c.objectPath(id)), nil +} + +func (c *testClient) Move(ctx context.Context, fromID, toID id.ID) error { + fromPath := c.objectPath(fromID) + toPath := c.objectPath(toID) + + fromObj, exists := c.mockBucket.objects[fromPath] + if !exists { + return fmt.Errorf("%w: %s", ErrAssetNotFound, fromID) + } + + if _, exists := c.mockBucket.objects[toPath]; exists { + return fmt.Errorf("destination already exists") + } + + c.mockBucket.objects[toPath] = &mockObject{ + bucket: c.mockBucket, + name: toPath, + data: fromObj.data, + attrs: &storage.ObjectAttrs{ + Name: toPath, + Metadata: fromObj.attrs.Metadata, + }, + } + + delete(c.mockBucket.objects, fromPath) + return nil +} + +func (c *testClient) List(ctx context.Context) ([]*entity.Asset, error) { + var assets []*entity.Asset + for _, obj := range c.mockBucket.objects { + id, err := id.From(path.Base(obj.name)) + if err != nil { + continue + } + + asset := entity.NewAsset( + id, + obj.attrs.Metadata["name"], + int64(len(obj.data)), + obj.attrs.Metadata["content_type"], + ) + assets = append(assets, asset) + } + return assets, nil +} + +func (c *testClient) DeleteAll(ctx context.Context, prefix string) error { + fullPrefix := path.Join(c.basePath, prefix) + for name := range c.mockBucket.objects { + if strings.HasPrefix(name, fullPrefix) { + delete(c.mockBucket.objects, name) + } + } + return nil +} + +func TestClient_Create(t *testing.T) { + client := newTestClient(t) + + asset := entity.NewAsset( + id.NewID(), + "test-asset", + 100, + "application/json", + ) + + err := client.Create(context.Background(), asset) + assert.NoError(t, err) + + obj := client.mockBucket.objects[client.objectPath(asset.ID())] + assert.NotNil(t, obj) + assert.Equal(t, asset.Name(), obj.attrs.Metadata["name"]) + assert.Equal(t, asset.ContentType(), obj.attrs.Metadata["content_type"]) +} + +func TestClient_Read(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + name := "test-asset" + contentType := "application/json" + objPath := client.objectPath(id) + + client.mockBucket.objects[objPath] = &mockObject{ + bucket: client.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: map[string]string{ + "name": name, + "content_type": contentType, + }, + }, + } + + asset, err := client.Read(context.Background(), id) + assert.NoError(t, err) + assert.Equal(t, id, asset.ID()) + assert.Equal(t, name, asset.Name()) + assert.Equal(t, contentType, asset.ContentType()) +} + +func TestClient_Update(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + objPath := client.objectPath(id) + + client.mockBucket.objects[objPath] = &mockObject{ + bucket: client.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: map[string]string{ + "name": "test-asset", + "content_type": "application/json", + }, + }, + } + + updatedAsset := entity.NewAsset( + id, + "updated-asset", + 100, + "application/json", + ) + + err := client.Update(context.Background(), updatedAsset) + assert.NoError(t, err) + + obj := client.mockBucket.objects[objPath] + assert.Equal(t, updatedAsset.Name(), obj.attrs.Metadata["name"]) +} + +func TestClient_Delete(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + objPath := client.objectPath(id) + + client.mockBucket.objects[objPath] = &mockObject{ + bucket: client.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: map[string]string{ + "name": "test-asset", + "content_type": "application/json", + }, + }, + } + + err := client.Delete(context.Background(), id) + assert.NoError(t, err) + + _, exists := client.mockBucket.objects[objPath] + assert.False(t, exists) +} + +func TestClient_Upload(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + content := []byte("test content") + objPath := client.objectPath(id) + + err := client.Upload(context.Background(), id, bytes.NewReader(content)) + assert.NoError(t, err) + + obj := client.mockBucket.objects[objPath] + assert.Equal(t, content, obj.data) +} + +func TestClient_Download(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + content := []byte("test content") + objPath := client.objectPath(id) + + client.mockBucket.objects[objPath] = &mockObject{ + bucket: client.mockBucket, + name: objPath, + data: content, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: make(map[string]string), + }, + } + + reader, err := client.Download(context.Background(), id) + assert.NoError(t, err) + + downloaded, err := io.ReadAll(reader) + assert.NoError(t, err) + assert.Equal(t, content, downloaded) +} + +func TestClient_Create_AlreadyExists(t *testing.T) { + client := newTestClient(t) + + asset := entity.NewAsset( + id.NewID(), + "test-asset", + 100, + "application/json", + ) + + objPath := client.objectPath(asset.ID()) + client.mockBucket.objects[objPath] = &mockObject{ + bucket: client.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: make(map[string]string), + }, + } + + err := client.Create(context.Background(), asset) + assert.Error(t, err) +} + +func TestClient_Read_NotFound(t *testing.T) { + client := newTestClient(t) + + _, err := client.Read(context.Background(), id.NewID()) + assert.Error(t, err) +} + +func TestClient_Update_NotFound(t *testing.T) { + client := newTestClient(t) + + asset := entity.NewAsset( + id.NewID(), + "test-asset", + 100, + "application/json", + ) + + err := client.Update(context.Background(), asset) + assert.Error(t, err) +} + +func TestClient_Download_NotFound(t *testing.T) { + client := newTestClient(t) + + _, err := client.Download(context.Background(), id.NewID()) + assert.Error(t, err) +} + +func TestClient_GetObjectURL(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + url := client.GetObjectURL(id) + assert.NotEmpty(t, url) + assert.Contains(t, url, client.objectPath(id)) +} + +func TestClient_GetIDFromURL(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + url := client.GetObjectURL(id) + + parsedID, err := client.GetIDFromURL(url) + assert.NoError(t, err) + assert.Equal(t, id, parsedID) +} + +func TestClient_GetIDFromURL_InvalidURL(t *testing.T) { + client := newTestClient(t) + + _, err := client.GetIDFromURL("invalid-url") + assert.Error(t, err) +} + +func TestClient_GetIDFromURL_MismatchedHost(t *testing.T) { + client := newTestClient(t) + + _, err := client.GetIDFromURL("https://different-host.com/test-path/123") + assert.Error(t, err) +} + +func TestClient_GetIDFromURL_EmptyPath(t *testing.T) { + client := newTestClient(t) + + _, err := client.GetIDFromURL("https://storage.googleapis.com") + assert.Error(t, err) +} + +func TestNewClient(t *testing.T) { + tests := []struct { + name string + bucketName string + basePath string + baseURL string + wantErr bool + }{ + { + name: "valid configuration", + bucketName: "test-bucket", + basePath: "test-path", + baseURL: "https://storage.googleapis.com", + wantErr: false, + }, + { + name: "empty bucket name", + bucketName: "", + basePath: "test-path", + baseURL: "https://storage.googleapis.com", + wantErr: true, + }, + { + name: "invalid base URL", + bucketName: "test-bucket", + basePath: "test-path", + baseURL: "://invalid-url", + wantErr: true, + }, + { + name: "empty base URL", + bucketName: "test-bucket", + basePath: "test-path", + baseURL: "", + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.bucketName == "" { + assert.Error(t, fmt.Errorf("bucket name is required")) + return + } + + client := &Client{ + bucketName: tt.bucketName, + basePath: tt.basePath, + } + + var err error + if tt.baseURL != "" { + client.baseURL, err = url.Parse(tt.baseURL) + if tt.wantErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + assert.NotNil(t, client.baseURL) + assert.Equal(t, tt.baseURL, client.baseURL.String()) + } + + assert.Equal(t, tt.bucketName, client.bucketName) + assert.Equal(t, tt.basePath, client.basePath) + }) + } +} + +func TestClient_List(t *testing.T) { + client := newTestClient(t) + + // Create multiple test objects + objects := []struct { + id id.ID + name string + contentType string + }{ + {id.NewID(), "asset1", "application/json"}, + {id.NewID(), "asset2", "application/json"}, + {id.NewID(), "asset3", "application/json"}, + } + + for _, obj := range objects { + objPath := client.objectPath(obj.id) + client.mockBucket.objects[objPath] = &mockObject{ + bucket: client.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: map[string]string{ + "name": obj.name, + "content_type": obj.contentType, + }, + }, + } + } + + assets, err := client.List(context.Background()) + assert.NoError(t, err) + assert.Len(t, assets, len(objects)) +} + +func TestClient_DeleteAll(t *testing.T) { + client := newTestClient(t) + + // Create test objects with different prefixes + objects := []struct { + id id.ID + name string + contentType string + prefix string + }{ + {id.NewID(), "asset1", "application/json", "test-prefix"}, + {id.NewID(), "asset2", "application/json", "test-prefix"}, + {id.NewID(), "asset3", "application/json", "other-prefix"}, + } + + for _, obj := range objects { + objPath := path.Join(client.basePath, obj.prefix, obj.id.String()) + client.mockBucket.objects[objPath] = &mockObject{ + bucket: client.mockBucket, + name: objPath, + attrs: &storage.ObjectAttrs{ + Name: objPath, + Metadata: map[string]string{ + "name": obj.name, + "content_type": obj.contentType, + }, + }, + } + } + + // Delete objects with test-prefix + err := client.DeleteAll(context.Background(), "test-prefix") + assert.NoError(t, err) + + // Verify only objects with test-prefix are deleted + var remainingCount int + for name := range client.mockBucket.objects { + if strings.Contains(name, "test-prefix") { + t.Errorf("Object with test-prefix should be deleted: %s", name) + } + remainingCount++ + } + assert.Equal(t, 1, remainingCount, "Should have one object remaining with other-prefix") +} + +func TestClient_Move(t *testing.T) { + client := newTestClient(t) + + fromID := id.NewID() + toID := id.NewID() + content := []byte("test content") + fromPath := client.objectPath(fromID) + toPath := client.objectPath(toID) + + client.mockBucket.objects[fromPath] = &mockObject{ + bucket: client.mockBucket, + name: fromPath, + data: content, + attrs: &storage.ObjectAttrs{ + Name: fromPath, + Metadata: map[string]string{ + "name": "test-asset", + "content_type": "application/json", + }, + }, + } + + err := client.Move(context.Background(), fromID, toID) + assert.NoError(t, err) + + _, exists := client.mockBucket.objects[fromPath] + assert.False(t, exists) + + obj := client.mockBucket.objects[toPath] + assert.NotNil(t, obj) + assert.Equal(t, content, obj.data) +} + +func TestClient_Move_SourceNotFound(t *testing.T) { + client := newTestClient(t) + + err := client.Move(context.Background(), id.NewID(), id.NewID()) + assert.Error(t, err) +} + +func TestClient_Move_DestinationExists(t *testing.T) { + client := newTestClient(t) + + fromID := id.NewID() + toID := id.NewID() + fromPath := client.objectPath(fromID) + toPath := client.objectPath(toID) + + // Create source object + client.mockBucket.objects[fromPath] = &mockObject{ + bucket: client.mockBucket, + name: fromPath, + attrs: &storage.ObjectAttrs{ + Name: fromPath, + Metadata: make(map[string]string), + }, + } + + // Create destination object + client.mockBucket.objects[toPath] = &mockObject{ + bucket: client.mockBucket, + name: toPath, + attrs: &storage.ObjectAttrs{ + Name: toPath, + Metadata: make(map[string]string), + }, + } + + err := client.Move(context.Background(), fromID, toID) + assert.Error(t, err) +} + +func TestClient_GetUploadURL(t *testing.T) { + client := newTestClient(t) + + id := id.NewID() + objPath := client.objectPath(id) + + url, err := client.GetUploadURL(context.Background(), id) + assert.NoError(t, err) + assert.Contains(t, url, objPath) +} diff --git a/asset/infrastructure/memory/decompress_job.go b/asset/infrastructure/memory/decompress_job.go new file mode 100644 index 0000000..ecd767f --- /dev/null +++ b/asset/infrastructure/memory/decompress_job.go @@ -0,0 +1,120 @@ +package memory + +import ( + "context" + "sync" + + "github.com/reearth/reearthx/asset/repository" + assetusecase "github.com/reearth/reearthx/asset/usecase" + "github.com/reearth/reearthx/rerror" +) + +var _ repository.DecompressJobRepository = (*DecompressJobRepository)(nil) + +// DecompressJobRepository is an in-memory implementation of repository.DecompressJobRepository +type DecompressJobRepository struct { + mu sync.RWMutex + jobs map[string]*assetusecase.DecompressStatus +} + +// NewDecompressJobRepository creates a new in-memory decompress job repository +func NewDecompressJobRepository() *DecompressJobRepository { + return &DecompressJobRepository{ + jobs: make(map[string]*assetusecase.DecompressStatus), + } +} + +// Save saves or updates a decompress job status +func (r *DecompressJobRepository) Save(ctx context.Context, status *assetusecase.DecompressStatus) error { + if status == nil { + return rerror.ErrInvalidParams + } + + r.mu.Lock() + defer r.mu.Unlock() + + r.jobs[status.JobID] = status + return nil +} + +// Get retrieves a decompress job status by ID +func (r *DecompressJobRepository) Get(ctx context.Context, jobID string) (*assetusecase.DecompressStatus, error) { + r.mu.RLock() + defer r.mu.RUnlock() + + if status, ok := r.jobs[jobID]; ok { + return status, nil + } + return nil, rerror.ErrNotFound +} + +// List retrieves all active decompress jobs +func (r *DecompressJobRepository) List(ctx context.Context) ([]*assetusecase.DecompressStatus, error) { + r.mu.RLock() + defer r.mu.RUnlock() + + jobs := make([]*assetusecase.DecompressStatus, 0, len(r.jobs)) + for _, status := range r.jobs { + if status.Status != "completed" && status.Status != "failed" { + jobs = append(jobs, status) + } + } + return jobs, nil +} + +// Delete removes a decompress job status +func (r *DecompressJobRepository) Delete(ctx context.Context, jobID string) error { + r.mu.Lock() + defer r.mu.Unlock() + + if _, ok := r.jobs[jobID]; !ok { + return rerror.ErrNotFound + } + + delete(r.jobs, jobID) + return nil +} + +// UpdateProgress updates the progress of a decompress job +func (r *DecompressJobRepository) UpdateProgress(ctx context.Context, jobID string, progress float64) error { + r.mu.Lock() + defer r.mu.Unlock() + + status, ok := r.jobs[jobID] + if !ok { + return rerror.ErrNotFound + } + + status.Progress = progress + return nil +} + +// Complete marks a decompress job as completed +func (r *DecompressJobRepository) Complete(ctx context.Context, jobID string) error { + r.mu.Lock() + defer r.mu.Unlock() + + status, ok := r.jobs[jobID] + if !ok { + return rerror.ErrNotFound + } + + status.Status = "completed" + status.Progress = 100 + return nil +} + +// Fail marks a decompress job as failed with an error message +func (r *DecompressJobRepository) Fail(ctx context.Context, jobID string, err string) error { + r.mu.Lock() + defer r.mu.Unlock() + + status, ok := r.jobs[jobID] + if !ok { + return rerror.ErrNotFound + } + + status.Status = "failed" + status.Error = err + return nil +} diff --git a/asset/infrastructure/memory/decompress_job_test.go b/asset/infrastructure/memory/decompress_job_test.go new file mode 100644 index 0000000..df940c2 --- /dev/null +++ b/asset/infrastructure/memory/decompress_job_test.go @@ -0,0 +1,171 @@ +package memory + +import ( + "context" + "testing" + "time" + + "github.com/reearth/reearthx/asset/domain/id" + assetusecase "github.com/reearth/reearthx/asset/usecase" + "github.com/reearth/reearthx/rerror" + "github.com/stretchr/testify/assert" +) + +func TestDecompressJobRepository(t *testing.T) { + ctx := context.Background() + repo := NewDecompressJobRepository() + + t.Run("Save and Get", func(t *testing.T) { + status := &assetusecase.DecompressStatus{ + JobID: "job1", + AssetID: id.NewID(), + Status: "pending", + Progress: 0, + StartedAt: time.Now(), + } + + // Test Save + err := repo.Save(ctx, status) + assert.NoError(t, err) + + // Test Get + got, err := repo.Get(ctx, "job1") + assert.NoError(t, err) + assert.Equal(t, status, got) + + // Test Get non-existent + _, err = repo.Get(ctx, "non-existent") + assert.Equal(t, rerror.ErrNotFound, err) + + // Test Save nil + err = repo.Save(ctx, nil) + assert.Equal(t, rerror.ErrInvalidParams, err) + }) + + t.Run("List", func(t *testing.T) { + repo := NewDecompressJobRepository() + + status1 := &assetusecase.DecompressStatus{ + JobID: "job1", + Status: "processing", + Progress: 50, + StartedAt: time.Now(), + } + status2 := &assetusecase.DecompressStatus{ + JobID: "job2", + Status: "completed", + Progress: 100, + StartedAt: time.Now(), + } + status3 := &assetusecase.DecompressStatus{ + JobID: "job3", + Status: "pending", + Progress: 0, + StartedAt: time.Now(), + } + + err := repo.Save(ctx, status1) + assert.NoError(t, err) + + err = repo.Save(ctx, status2) + assert.NoError(t, err) + + err = repo.Save(ctx, status3) + assert.NoError(t, err) + + // Should only return active jobs (not completed or failed) + jobs, err := repo.List(ctx) + assert.NoError(t, err) + assert.Len(t, jobs, 2) + }) + + t.Run("Delete", func(t *testing.T) { + repo := NewDecompressJobRepository() + status := &assetusecase.DecompressStatus{ + JobID: "job1", + Status: "pending", + StartedAt: time.Now(), + } + + err := repo.Save(ctx, status) + assert.NoError(t, err) + + // Test Delete + err = repo.Delete(ctx, "job1") + assert.NoError(t, err) + + // Verify deletion + _, err = repo.Get(ctx, "job1") + assert.Equal(t, rerror.ErrNotFound, err) + + // Test Delete non-existent + err = repo.Delete(ctx, "non-existent") + assert.Equal(t, rerror.ErrNotFound, err) + }) + + t.Run("UpdateProgress", func(t *testing.T) { + repo := NewDecompressJobRepository() + status := &assetusecase.DecompressStatus{ + JobID: "job1", + Status: "processing", + Progress: 0, + StartedAt: time.Now(), + } + + err := repo.Save(ctx, status) + assert.NoError(t, err) + + // Test UpdateProgress + err = repo.UpdateProgress(ctx, "job1", 50.0) + assert.NoError(t, err) + + // Verify progress update + got, _ := repo.Get(ctx, "job1") + assert.Equal(t, 50.0, got.Progress) + + // Test UpdateProgress non-existent + err = repo.UpdateProgress(ctx, "non-existent", 50.0) + assert.Equal(t, rerror.ErrNotFound, err) + }) + + t.Run("Complete and Fail", func(t *testing.T) { + repo := NewDecompressJobRepository() + status1 := &assetusecase.DecompressStatus{ + JobID: "job1", + Status: "processing", + StartedAt: time.Now(), + } + status2 := &assetusecase.DecompressStatus{ + JobID: "job2", + Status: "processing", + StartedAt: time.Now(), + } + + err := repo.Save(ctx, status1) + assert.NoError(t, err) + err = repo.Save(ctx, status2) + assert.NoError(t, err) + + // Test Complete + err = repo.Complete(ctx, "job1") + assert.NoError(t, err) + got, _ := repo.Get(ctx, "job1") + assert.Equal(t, "completed", got.Status) + assert.Equal(t, 100.0, got.Progress) + + // Test Fail + err = repo.Fail(ctx, "job2", "test error") + assert.NoError(t, err) + got, _ = repo.Get(ctx, "job2") + assert.Equal(t, "failed", got.Status) + assert.Equal(t, "test error", got.Error) + + // Test Complete non-existent + err = repo.Complete(ctx, "non-existent") + assert.Equal(t, rerror.ErrNotFound, err) + + // Test Fail non-existent + err = repo.Fail(ctx, "non-existent", "error") + assert.Equal(t, rerror.ErrNotFound, err) + }) +} diff --git a/asset/infrastructure/pubsub/pubsub.go b/asset/infrastructure/pubsub/pubsub.go new file mode 100644 index 0000000..df52164 --- /dev/null +++ b/asset/infrastructure/pubsub/pubsub.go @@ -0,0 +1,195 @@ +package pubsub + +import ( + "context" + "reflect" + "sync" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/reearth/reearthx/asset/repository" + "github.com/reearth/reearthx/log" +) + +// Publisher defines the interface for publishing events +type Publisher interface { + Publish(ctx context.Context, topic string, msg interface{}) error +} + +type subscription struct { + eventType repository.EventType + handler repository.EventHandler +} + +// AssetPubSub handles publishing and subscribing to asset events +type AssetPubSub struct { + publisher Publisher + topic string + mu sync.RWMutex + subscriptions []subscription +} + +var _ repository.PubSubRepository = (*AssetPubSub)(nil) + +// NewAssetPubSub creates a new AssetPubSub instance +func NewAssetPubSub(publisher Publisher, topic string) *AssetPubSub { + return &AssetPubSub{ + publisher: publisher, + topic: topic, + } +} + +// Subscribe registers a handler for a specific event type +func (p *AssetPubSub) Subscribe(eventType repository.EventType, handler repository.EventHandler) { + p.mu.Lock() + defer p.mu.Unlock() + + p.subscriptions = append(p.subscriptions, subscription{ + eventType: eventType, + handler: handler, + }) +} + +// Unsubscribe removes a handler for a specific event type +func (p *AssetPubSub) Unsubscribe(eventType repository.EventType, handler repository.EventHandler) { + p.mu.Lock() + defer p.mu.Unlock() + + handlerValue := reflect.ValueOf(handler) + for i := len(p.subscriptions) - 1; i >= 0; i-- { + s := p.subscriptions[i] + if s.eventType == eventType && reflect.ValueOf(s.handler) == handlerValue { + p.subscriptions = append(p.subscriptions[:i], p.subscriptions[i+1:]...) + } + } +} + +// notify notifies all subscribers of an event +func (p *AssetPubSub) notify(ctx context.Context, event repository.AssetEvent) { + p.mu.RLock() + subs := make([]subscription, len(p.subscriptions)) + copy(subs, p.subscriptions) + p.mu.RUnlock() + + for _, sub := range subs { + if sub.eventType == event.Type || sub.eventType == "*" { + sub.handler(ctx, event) + } + } +} + +// PublishAssetCreated publishes an asset created event +func (p *AssetPubSub) PublishAssetCreated(ctx context.Context, asset *entity.Asset) error { + event := repository.AssetEvent{ + Type: repository.EventTypeAssetCreated, + AssetID: asset.ID(), + WorkspaceID: asset.WorkspaceID(), + ProjectID: asset.ProjectID(), + Status: string(asset.Status()), + Error: asset.Error(), + } + + if err := p.publisher.Publish(ctx, p.topic, event); err != nil { + log.Errorfc(ctx, "failed to publish asset created event: %v", err) + return err + } + + p.notify(ctx, event) + return nil +} + +// PublishAssetUpdated publishes an asset updated event +func (p *AssetPubSub) PublishAssetUpdated(ctx context.Context, asset *entity.Asset) error { + event := repository.AssetEvent{ + Type: repository.EventTypeAssetUpdated, + AssetID: asset.ID(), + WorkspaceID: asset.WorkspaceID(), + ProjectID: asset.ProjectID(), + Status: string(asset.Status()), + Error: asset.Error(), + } + + if err := p.publisher.Publish(ctx, p.topic, event); err != nil { + log.Errorfc(ctx, "failed to publish asset updated event: %v", err) + return err + } + + p.notify(ctx, event) + return nil +} + +// PublishAssetDeleted publishes an asset deleted event +func (p *AssetPubSub) PublishAssetDeleted(ctx context.Context, assetID id.ID) error { + event := repository.AssetEvent{ + Type: repository.EventTypeAssetDeleted, + AssetID: assetID, + } + + if err := p.publisher.Publish(ctx, p.topic, event); err != nil { + log.Errorfc(ctx, "failed to publish asset deleted event: %v", err) + return err + } + + p.notify(ctx, event) + return nil +} + +// PublishAssetUploaded publishes an asset uploaded event +func (p *AssetPubSub) PublishAssetUploaded(ctx context.Context, asset *entity.Asset) error { + event := repository.AssetEvent{ + Type: repository.EventTypeAssetUploaded, + AssetID: asset.ID(), + WorkspaceID: asset.WorkspaceID(), + ProjectID: asset.ProjectID(), + Status: string(asset.Status()), + Error: asset.Error(), + } + + if err := p.publisher.Publish(ctx, p.topic, event); err != nil { + log.Errorfc(ctx, "failed to publish asset uploaded event: %v", err) + return err + } + + p.notify(ctx, event) + return nil +} + +// PublishAssetExtracted publishes an asset extraction status event +func (p *AssetPubSub) PublishAssetExtracted(ctx context.Context, asset *entity.Asset) error { + event := repository.AssetEvent{ + Type: repository.EventTypeAssetExtracted, + AssetID: asset.ID(), + WorkspaceID: asset.WorkspaceID(), + ProjectID: asset.ProjectID(), + Status: string(asset.Status()), + Error: asset.Error(), + } + + if err := p.publisher.Publish(ctx, p.topic, event); err != nil { + log.Errorfc(ctx, "failed to publish asset extracted event: %v", err) + return err + } + + p.notify(ctx, event) + return nil +} + +// PublishAssetTransferred publishes an asset transferred event +func (p *AssetPubSub) PublishAssetTransferred(ctx context.Context, asset *entity.Asset) error { + event := repository.AssetEvent{ + Type: repository.EventTypeAssetTransferred, + AssetID: asset.ID(), + WorkspaceID: asset.WorkspaceID(), + ProjectID: asset.ProjectID(), + Status: string(asset.Status()), + Error: asset.Error(), + } + + if err := p.publisher.Publish(ctx, p.topic, event); err != nil { + log.Errorfc(ctx, "failed to publish asset transferred event: %v", err) + return err + } + + p.notify(ctx, event) + return nil +} diff --git a/asset/infrastructure/pubsub/pubsub_test.go b/asset/infrastructure/pubsub/pubsub_test.go new file mode 100644 index 0000000..012a26c --- /dev/null +++ b/asset/infrastructure/pubsub/pubsub_test.go @@ -0,0 +1,223 @@ +package pubsub + +import ( + "context" + "sync" + "testing" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/reearth/reearthx/asset/repository" + "github.com/stretchr/testify/assert" +) + +type mockPublisher struct { + published []mockPublishedEvent +} + +type mockPublishedEvent struct { + topic string + msg interface{} +} + +func (m *mockPublisher) Publish(ctx context.Context, topic string, msg interface{}) error { + // Make a copy of the event to ensure it's not modified after storage + if event, ok := msg.(repository.AssetEvent); ok { + eventCopy := repository.AssetEvent{ + Type: event.Type, + AssetID: event.AssetID, + WorkspaceID: event.WorkspaceID, + ProjectID: event.ProjectID, + Status: event.Status, + Error: event.Error, + } + m.published = append(m.published, mockPublishedEvent{topic: topic, msg: eventCopy}) + } else { + m.published = append(m.published, mockPublishedEvent{topic: topic, msg: msg}) + } + return nil +} + +func TestNewAssetPubSub(t *testing.T) { + pub := &mockPublisher{} + ps := NewAssetPubSub(pub, "test-topic") + assert.NotNil(t, ps) + assert.Equal(t, pub, ps.publisher) + assert.Equal(t, "test-topic", ps.topic) +} + +func TestAssetPubSub_Subscribe(t *testing.T) { + ps := NewAssetPubSub(&mockPublisher{}, "test-topic") + + var receivedEvents []repository.AssetEvent + var mu sync.Mutex + + // Subscribe to all events + ps.Subscribe("*", func(ctx context.Context, event repository.AssetEvent) { + mu.Lock() + receivedEvents = append(receivedEvents, event) + mu.Unlock() + }) + + // Create test asset + asset := entity.NewAsset( + id.NewID(), + "test.txt", + 100, + "text/plain", + ) + asset.MoveToWorkspace(id.NewWorkspaceID()) + asset.MoveToProject(id.NewProjectID()) + asset.UpdateStatus(entity.StatusActive, "") + + // Publish events + ctx := context.Background() + assert.NoError(t, ps.PublishAssetCreated(ctx, asset)) + assert.NoError(t, ps.PublishAssetUpdated(ctx, asset)) + assert.NoError(t, ps.PublishAssetUploaded(ctx, asset)) + + // Check received events + mu.Lock() + defer mu.Unlock() + assert.Equal(t, 3, len(receivedEvents)) + assert.Equal(t, repository.EventTypeAssetCreated, receivedEvents[0].Type) + assert.Equal(t, repository.EventTypeAssetUpdated, receivedEvents[1].Type) + assert.Equal(t, repository.EventTypeAssetUploaded, receivedEvents[2].Type) +} + +func TestAssetPubSub_SubscribeSpecificEvent(t *testing.T) { + ps := NewAssetPubSub(&mockPublisher{}, "test-topic") + + var receivedEvents []repository.AssetEvent + var mu sync.Mutex + + // Subscribe only to created events + ps.Subscribe(repository.EventTypeAssetCreated, func(ctx context.Context, event repository.AssetEvent) { + mu.Lock() + receivedEvents = append(receivedEvents, event) + mu.Unlock() + }) + + // Create test asset + asset := entity.NewAsset( + id.NewID(), + "test.txt", + 100, + "text/plain", + ) + + // Publish different events + ctx := context.Background() + assert.NoError(t, ps.PublishAssetCreated(ctx, asset)) // Should be received + assert.NoError(t, ps.PublishAssetUpdated(ctx, asset)) // Should be ignored + assert.NoError(t, ps.PublishAssetUploaded(ctx, asset)) // Should be ignored + + // Check received events + mu.Lock() + defer mu.Unlock() + assert.Equal(t, 1, len(receivedEvents)) + assert.Equal(t, repository.EventTypeAssetCreated, receivedEvents[0].Type) +} + +func TestAssetPubSub_Unsubscribe(t *testing.T) { + ps := NewAssetPubSub(&mockPublisher{}, "test-topic") + + var receivedEvents []repository.AssetEvent + var mu sync.Mutex + + handler := func(ctx context.Context, event repository.AssetEvent) { + mu.Lock() + receivedEvents = append(receivedEvents, event) + mu.Unlock() + } + + // Subscribe and then unsubscribe + ps.Subscribe(repository.EventTypeAssetCreated, handler) + ps.Unsubscribe(repository.EventTypeAssetCreated, handler) + + // Create test asset + asset := entity.NewAsset( + id.NewID(), + "test.txt", + 100, + "text/plain", + ) + + // Publish event + ctx := context.Background() + assert.NoError(t, ps.PublishAssetCreated(ctx, asset)) + + // Check that no events were received + mu.Lock() + defer mu.Unlock() + assert.Equal(t, 0, len(receivedEvents)) +} + +func TestAssetPubSub_PublishEvents(t *testing.T) { + pub := &mockPublisher{} + ps := NewAssetPubSub(pub, "test-topic") + + // Create test asset + asset := entity.NewAsset( + id.NewID(), + "test.txt", + 100, + "text/plain", + ) + workspaceID := id.NewWorkspaceID() + projectID := id.NewProjectID() + asset.MoveToWorkspace(workspaceID) + asset.MoveToProject(projectID) + + // Set status and error before publishing + asset.UpdateStatus(entity.StatusActive, "test error") + + // Test all publish methods + ctx := context.Background() + assert.NoError(t, ps.PublishAssetCreated(ctx, asset)) + assert.NoError(t, ps.PublishAssetUpdated(ctx, asset)) + assert.NoError(t, ps.PublishAssetDeleted(ctx, asset.ID())) + assert.NoError(t, ps.PublishAssetUploaded(ctx, asset)) + assert.NoError(t, ps.PublishAssetExtracted(ctx, asset)) + assert.NoError(t, ps.PublishAssetTransferred(ctx, asset)) + + // Verify published events + assert.Equal(t, 6, len(pub.published)) + + // Verify event details + for i, event := range pub.published { + assert.Equal(t, "test-topic", event.topic) + assetEvent, ok := event.msg.(repository.AssetEvent) + assert.True(t, ok, "Event message should be of type AssetEvent") + assert.Equal(t, asset.ID(), assetEvent.AssetID) + + // For deleted event, we don't expect other fields + if i == 2 { // deleted event + assert.Equal(t, repository.EventTypeAssetDeleted, assetEvent.Type) + assert.Empty(t, assetEvent.WorkspaceID) + assert.Empty(t, assetEvent.ProjectID) + assert.Empty(t, assetEvent.Status) + assert.Empty(t, assetEvent.Error) + continue + } + + assert.Equal(t, workspaceID, assetEvent.WorkspaceID, "Event %d: WorkspaceID mismatch", i) + assert.Equal(t, projectID, assetEvent.ProjectID, "Event %d: ProjectID mismatch", i) + assert.Equal(t, string(asset.Status()), assetEvent.Status, "Event %d: Status mismatch", i) + assert.Equal(t, asset.Error(), assetEvent.Error, "Event %d: Error mismatch", i) + + // Verify event types + switch i { + case 0: + assert.Equal(t, repository.EventTypeAssetCreated, assetEvent.Type, "Event 0 should be Created") + case 1: + assert.Equal(t, repository.EventTypeAssetUpdated, assetEvent.Type, "Event 1 should be Updated") + case 3: + assert.Equal(t, repository.EventTypeAssetUploaded, assetEvent.Type, "Event 3 should be Uploaded") + case 4: + assert.Equal(t, repository.EventTypeAssetExtracted, assetEvent.Type, "Event 4 should be Extracted") + case 5: + assert.Equal(t, repository.EventTypeAssetTransferred, assetEvent.Type, "Event 5 should be Transferred") + } + } +} diff --git a/asset/repository/decompress_job.go b/asset/repository/decompress_job.go new file mode 100644 index 0000000..7fa4368 --- /dev/null +++ b/asset/repository/decompress_job.go @@ -0,0 +1,31 @@ +package repository + +import ( + "context" + + assetusecase "github.com/reearth/reearthx/asset/usecase" +) + +// DecompressJobRepository defines the interface for storing decompression job status +type DecompressJobRepository interface { + // Save saves or updates a decompress job status + Save(ctx context.Context, status *assetusecase.DecompressStatus) error + + // Get retrieves a decompress job status by ID + Get(ctx context.Context, jobID string) (*assetusecase.DecompressStatus, error) + + // List retrieves all active decompress jobs + List(ctx context.Context) ([]*assetusecase.DecompressStatus, error) + + // Delete removes a decompress job status + Delete(ctx context.Context, jobID string) error + + // UpdateProgress updates the progress of a decompress job + UpdateProgress(ctx context.Context, jobID string, progress float64) error + + // Complete marks a decompress job as completed + Complete(ctx context.Context, jobID string) error + + // Fail marks a decompress job as failed with an error message + Fail(ctx context.Context, jobID string, err string) error +} diff --git a/asset/repository/decompressor_repository.go b/asset/repository/decompressor_repository.go new file mode 100644 index 0000000..fb46f08 --- /dev/null +++ b/asset/repository/decompressor_repository.go @@ -0,0 +1,31 @@ +package repository + +import ( + "context" + "io" +) + +// CompressResult represents the result of a compression operation +type CompressResult struct { + Content []byte + Error error +} + +// Decompressor defines the interface for compression and decompression operations +type Decompressor interface { + // DecompressWithContent decompresses zip content directly and returns a channel of decompressed files + // The channel will be closed when all files have been processed or an error occurs + DecompressWithContent(ctx context.Context, content []byte) (<-chan DecompressedFile, error) + + // CompressWithContent compresses the provided content into a zip archive + // Returns a channel that will receive the compressed bytes or an error + // The channel will be closed when compression is complete or if an error occurs + CompressWithContent(ctx context.Context, files map[string]io.Reader) (<-chan CompressResult, error) +} + +// DecompressedFile represents a single file from the zip archive +type DecompressedFile struct { + Name string + Content io.Reader + Error error +} diff --git a/asset/repository/event.go b/asset/repository/event.go new file mode 100644 index 0000000..eb71def --- /dev/null +++ b/asset/repository/event.go @@ -0,0 +1,32 @@ +package repository + +import ( + "context" + + "github.com/reearth/reearthx/asset/domain/id" +) + +// EventType represents the type of asset event +type EventType string + +const ( + EventTypeAssetCreated EventType = "asset.created" + EventTypeAssetUpdated EventType = "asset.updated" + EventTypeAssetDeleted EventType = "asset.deleted" + EventTypeAssetUploaded EventType = "asset.uploaded" + EventTypeAssetExtracted EventType = "asset.extracted" + EventTypeAssetTransferred EventType = "asset.transferred" +) + +// AssetEvent represents an asset event +type AssetEvent struct { + Type EventType + AssetID id.ID + WorkspaceID id.WorkspaceID + ProjectID id.ProjectID + Status string + Error string +} + +// EventHandler is a function that handles asset events +type EventHandler func(ctx context.Context, event AssetEvent) diff --git a/asset/repository/group_repository.go b/asset/repository/group_repository.go new file mode 100644 index 0000000..332de55 --- /dev/null +++ b/asset/repository/group_repository.go @@ -0,0 +1,25 @@ +package repository + +import ( + "context" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" +) + +type GroupReader interface { + FindByID(ctx context.Context, id id.GroupID) (*entity.Group, error) + FindByIDs(ctx context.Context, ids []id.GroupID) ([]*entity.Group, error) + List(ctx context.Context) ([]*entity.Group, error) +} + +type GroupWriter interface { + Create(ctx context.Context, group *entity.Group) error + Update(ctx context.Context, group *entity.Group) error + Delete(ctx context.Context, id id.GroupID) error +} + +type GroupRepository interface { + GroupReader + GroupWriter +} diff --git a/asset/repository/persistence_repository.go b/asset/repository/persistence_repository.go new file mode 100644 index 0000000..b41a40c --- /dev/null +++ b/asset/repository/persistence_repository.go @@ -0,0 +1,33 @@ +package repository + +import ( + "context" + "io" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" +) + +type Reader interface { + Read(ctx context.Context, id id.ID) (*entity.Asset, error) + List(ctx context.Context) ([]*entity.Asset, error) + FindByGroup(ctx context.Context, groupID id.GroupID) ([]*entity.Asset, error) +} + +type Writer interface { + Create(ctx context.Context, asset *entity.Asset) error + Update(ctx context.Context, asset *entity.Asset) error + Delete(ctx context.Context, id id.ID) error +} + +type FileOperator interface { + Upload(ctx context.Context, id id.ID, content io.Reader) error + Download(ctx context.Context, id id.ID) (io.ReadCloser, error) + GetUploadURL(ctx context.Context, id id.ID) (string, error) +} + +type PersistenceRepository interface { + Reader + Writer + FileOperator +} diff --git a/asset/repository/pubsub_repository.go b/asset/repository/pubsub_repository.go new file mode 100644 index 0000000..61f9be9 --- /dev/null +++ b/asset/repository/pubsub_repository.go @@ -0,0 +1,36 @@ +package repository + +import ( + "context" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" +) + +// PubSubRepository defines the interface for publishing and subscribing to asset events +type PubSubRepository interface { + // PublishAssetCreated publishes an asset created event + PublishAssetCreated(ctx context.Context, asset *entity.Asset) error + + // PublishAssetUpdated publishes an asset updated event + PublishAssetUpdated(ctx context.Context, asset *entity.Asset) error + + // PublishAssetDeleted publishes an asset deleted event + PublishAssetDeleted(ctx context.Context, assetID id.ID) error + + // PublishAssetUploaded publishes an asset uploaded event + PublishAssetUploaded(ctx context.Context, asset *entity.Asset) error + + // PublishAssetExtracted publishes an asset extraction status event + PublishAssetExtracted(ctx context.Context, asset *entity.Asset) error + + // PublishAssetTransferred publishes an asset transferred event + PublishAssetTransferred(ctx context.Context, asset *entity.Asset) error + + // Subscribe registers a handler for a specific event type + // Use "*" as eventType to subscribe to all events + Subscribe(eventType EventType, handler EventHandler) + + // Unsubscribe removes a handler for a specific event type + Unsubscribe(eventType EventType, handler EventHandler) +} diff --git a/asset/usecase/interactor/interactor.go b/asset/usecase/interactor/interactor.go new file mode 100644 index 0000000..cf28065 --- /dev/null +++ b/asset/usecase/interactor/interactor.go @@ -0,0 +1,384 @@ +package assetinteractor + +import ( + "context" + "fmt" + "io" + "time" + + "github.com/google/uuid" + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" + "github.com/reearth/reearthx/asset/infrastructure/decompress" + "github.com/reearth/reearthx/asset/repository" + assetusecase "github.com/reearth/reearthx/asset/usecase" + "github.com/reearth/reearthx/log" +) + +type AssetInteractor struct { + repo repository.PersistenceRepository + decompressor repository.Decompressor + pubsub repository.PubSubRepository + txManager assetusecase.TransactionManager + jobRepo repository.DecompressJobRepository +} + +func NewAssetInteractor( + repo repository.PersistenceRepository, + pubsub repository.PubSubRepository, + txManager assetusecase.TransactionManager, + jobRepo repository.DecompressJobRepository, +) *AssetInteractor { + return &AssetInteractor{ + repo: repo, + decompressor: decompress.NewZipDecompressor(), + pubsub: pubsub, + txManager: txManager, + jobRepo: jobRepo, + } +} + +// validateAsset validates an asset using domain rules +func (i *AssetInteractor) validateAsset(ctx context.Context, asset *entity.Asset) *assetusecase.Result { + if result := asset.Validate(ctx); !result.IsValid { + return assetusecase.NewValidationErrorResult(result.Errors) + } + return nil +} + +// CreateAsset creates a new asset +func (i *AssetInteractor) CreateAsset(ctx context.Context, asset *entity.Asset) *assetusecase.Result { + if validationResult := i.validateAsset(ctx, asset); validationResult != nil { + return validationResult + } + + var createdAsset *entity.Asset + err := i.txManager.WithTransaction(ctx, func(ctx context.Context) error { + if err := i.repo.Create(ctx, asset); err != nil { + return err + } + + if err := i.pubsub.PublishAssetCreated(ctx, asset); err != nil { + log.Errorfc(ctx, "failed to publish asset created event: %v", err) + return err + } + + createdAsset = asset + return nil + }) + + if err != nil { + return assetusecase.NewErrorResult("CREATE_ASSET_FAILED", err.Error(), nil) + } + + return assetusecase.NewResult(createdAsset) +} + +// GetAsset retrieves an asset by ID +func (i *AssetInteractor) GetAsset(ctx context.Context, id id.ID) *assetusecase.Result { + asset, err := i.repo.Read(ctx, id) + if err != nil { + return assetusecase.NewErrorResult("GET_ASSET_FAILED", err.Error(), nil) + } + return assetusecase.NewResult(asset) +} + +// UpdateAsset updates an existing asset +func (i *AssetInteractor) UpdateAsset(ctx context.Context, asset *entity.Asset) *assetusecase.Result { + if validationResult := i.validateAsset(ctx, asset); validationResult != nil { + return validationResult + } + + var updatedAsset *entity.Asset + err := i.txManager.WithTransaction(ctx, func(ctx context.Context) error { + if err := i.repo.Update(ctx, asset); err != nil { + return err + } + + if err := i.pubsub.PublishAssetUpdated(ctx, asset); err != nil { + log.Errorfc(ctx, "failed to publish asset updated event: %v", err) + return err + } + + updatedAsset = asset + return nil + }) + + if err != nil { + return assetusecase.NewErrorResult("UPDATE_ASSET_FAILED", err.Error(), nil) + } + + return assetusecase.NewResult(updatedAsset) +} + +// DeleteAsset removes an asset by ID +func (i *AssetInteractor) DeleteAsset(ctx context.Context, id id.ID) *assetusecase.Result { + err := i.txManager.WithTransaction(ctx, func(ctx context.Context) error { + if err := i.repo.Delete(ctx, id); err != nil { + return err + } + + if err := i.pubsub.PublishAssetDeleted(ctx, id); err != nil { + log.Errorfc(ctx, "failed to publish asset deleted event: %v", err) + return err + } + + return nil + }) + + if err != nil { + return assetusecase.NewErrorResult("DELETE_ASSET_FAILED", err.Error(), nil) + } + + return assetusecase.NewResult(nil) +} + +// UploadAssetContent uploads content for an asset with the given ID +func (i *AssetInteractor) UploadAssetContent(ctx context.Context, id id.ID, content io.Reader) *assetusecase.Result { + var uploadedAsset *entity.Asset + err := i.txManager.WithTransaction(ctx, func(ctx context.Context) error { + if err := i.repo.Upload(ctx, id, content); err != nil { + return err + } + + asset, err := i.repo.Read(ctx, id) + if err != nil { + return err + } + + if err := i.pubsub.PublishAssetUploaded(ctx, asset); err != nil { + log.Errorfc(ctx, "failed to publish asset uploaded event: %v", err) + return err + } + + uploadedAsset = asset + return nil + }) + + if err != nil { + return assetusecase.NewErrorResult("UPLOAD_CONTENT_FAILED", err.Error(), nil) + } + + return assetusecase.NewResult(uploadedAsset) +} + +// DownloadAssetContent retrieves the content of an asset by ID +func (i *AssetInteractor) DownloadAssetContent(ctx context.Context, id id.ID) *assetusecase.Result { + content, err := i.repo.Download(ctx, id) + if err != nil { + return assetusecase.NewErrorResult("DOWNLOAD_CONTENT_FAILED", err.Error(), nil) + } + return assetusecase.NewResult(content) +} + +// GetAssetUploadURL generates a URL for uploading content to an asset +func (i *AssetInteractor) GetAssetUploadURL(ctx context.Context, id id.ID) *assetusecase.Result { + url, err := i.repo.GetUploadURL(ctx, id) + if err != nil { + return assetusecase.NewErrorResult("GET_UPLOAD_URL_FAILED", err.Error(), nil) + } + return assetusecase.NewResult(url) +} + +// ListAssets returns all assets +func (i *AssetInteractor) ListAssets(ctx context.Context) *assetusecase.Result { + assets, err := i.repo.List(ctx) + if err != nil { + return assetusecase.NewErrorResult("LIST_ASSETS_FAILED", err.Error(), nil) + } + return assetusecase.NewResult(assets) +} + +// DecompressZipContent decompresses zip content and returns a channel of decompressed files +func (i *AssetInteractor) DecompressZipContent(ctx context.Context, content []byte) *assetusecase.Result { + ch, err := i.decompressor.DecompressWithContent(ctx, content) + if err != nil { + return assetusecase.NewErrorResult("DECOMPRESS_FAILED", err.Error(), nil) + } + + if assetID, ok := ctx.Value("assetID").(id.ID); ok { + jobID := uuid.New().String() + status := &assetusecase.DecompressStatus{ + JobID: jobID, + AssetID: assetID, + Status: "pending", + Progress: 0, + StartedAt: time.Now(), + } + + err := i.jobRepo.Save(ctx, status) + if err != nil { + return assetusecase.NewErrorResult("JOB_CREATION_FAILED", err.Error(), nil) + } + + go func() { + ctx := context.Background() + status.Status = "processing" + if err := i.jobRepo.Save(ctx, status); err != nil { + log.Errorfc(ctx, "failed to save job status: %v", err) + } + + err := i.txManager.WithTransaction(ctx, func(ctx context.Context) error { + asset, err := i.repo.Read(ctx, assetID) + if err != nil { + return err + } + + asset.UpdateStatus(entity.StatusExtracting, "") + if err := i.repo.Update(ctx, asset); err != nil { + return err + } + + if err := i.pubsub.PublishAssetExtracted(ctx, asset); err != nil { + log.Errorfc(ctx, "failed to publish asset extracted event: %v", err) + return err + } + + return nil + }) + + if err != nil { + status.Status = "failed" + status.Error = err.Error() + if err := i.jobRepo.Save(ctx, status); err != nil { + log.Errorfc(ctx, "failed to save job status: %v", err) + } + return + } + + // Process decompressed files + totalFiles := 0 + processedFiles := 0 + for range ch { + totalFiles++ + } + + for range ch { + processedFiles++ + progress := float64(processedFiles) / float64(totalFiles) * 100 + if err := i.jobRepo.UpdateProgress(ctx, jobID, progress); err != nil { + log.Errorfc(ctx, "failed to update job progress: %v", err) + } + } + + status.Status = "completed" + status.Progress = 100 + status.CompletedAt = time.Now() + if err := i.jobRepo.Save(ctx, status); err != nil { + log.Errorfc(ctx, "failed to save job status: %v", err) + } + }() + + return assetusecase.NewResult(map[string]interface{}{ + "jobID": jobID, + "ch": ch, + }) + } + + return assetusecase.NewResult(ch) +} + +// CompressToZip compresses the provided files into a zip archive +func (i *AssetInteractor) CompressToZip(ctx context.Context, files map[string]io.Reader) *assetusecase.Result { + ch, err := i.decompressor.CompressWithContent(ctx, files) + if err != nil { + return assetusecase.NewErrorResult("COMPRESS_FAILED", err.Error(), nil) + } + return assetusecase.NewResult(ch) +} + +// DeleteAllAssetsInGroup deletes all assets in a group +func (i *AssetInteractor) DeleteAllAssetsInGroup(ctx context.Context, groupID id.GroupID) *assetusecase.Result { + err := i.txManager.WithTransaction(ctx, func(ctx context.Context) error { + assets, err := i.repo.FindByGroup(ctx, groupID) + if err != nil { + return err + } + + for _, asset := range assets { + if err := i.DeleteAsset(ctx, asset.ID()).GetError(); err != nil { + log.Errorfc(ctx, "failed to delete asset %s in group %s: %v", asset.ID(), groupID, err) + return err + } + } + + return nil + }) + + if err != nil { + return assetusecase.NewErrorResult("DELETE_GROUP_ASSETS_FAILED", err.Error(), nil) + } + + return assetusecase.NewResult(nil) +} + +// DeliverAsset implements the asset delivery functionality +func (i *AssetInteractor) DeliverAsset(ctx context.Context, id id.ID, options *assetusecase.DeliverOptions) *assetusecase.Result { + // Get asset metadata + asset, err := i.repo.Read(ctx, id) + if err != nil { + return assetusecase.NewErrorResult("ASSET_NOT_FOUND", err.Error(), nil) + } + + // Get content + content, err := i.repo.Download(ctx, id) + if err != nil { + return assetusecase.NewErrorResult("CONTENT_DOWNLOAD_FAILED", err.Error(), nil) + } + + // Apply transformations if needed + if options != nil && options.Transform { + // TODO: Implement transformation logic when needed + log.Infofc(ctx, "Asset transformation requested but not implemented yet") + } + + // Prepare response metadata + contentType := asset.ContentType() + if options != nil && options.ContentType != "" { + contentType = options.ContentType + } + + headers := map[string]string{ + "Content-Type": contentType, + } + + if options != nil { + // Add cache control + if options.MaxAge > 0 { + headers["Cache-Control"] = fmt.Sprintf("max-age=%d", options.MaxAge) + } + + // Add content disposition + if options.Disposition != "" { + headers["Content-Disposition"] = options.Disposition + } + + // Add custom headers + for k, v := range options.Headers { + headers[k] = v + } + } + + return assetusecase.NewResult(map[string]interface{}{ + "content": content, + "headers": headers, + }) +} + +// GetDecompressStatus implements the decompress status retrieval +func (i *AssetInteractor) GetDecompressStatus(ctx context.Context, jobID string) *assetusecase.Result { + status, err := i.jobRepo.Get(ctx, jobID) + if err != nil { + return assetusecase.NewErrorResult("JOB_NOT_FOUND", err.Error(), nil) + } + return assetusecase.NewResult(status) +} + +// ListDecompressJobs implements the decompress jobs listing +func (i *AssetInteractor) ListDecompressJobs(ctx context.Context) *assetusecase.Result { + jobs, err := i.jobRepo.List(ctx) + if err != nil { + return assetusecase.NewErrorResult("LIST_JOBS_FAILED", err.Error(), nil) + } + return assetusecase.NewResult(jobs) +} diff --git a/asset/usecase/result.go b/asset/usecase/result.go new file mode 100644 index 0000000..4236881 --- /dev/null +++ b/asset/usecase/result.go @@ -0,0 +1,109 @@ +package assetusecase + +import ( + "fmt" + + "github.com/reearth/reearthx/asset/domain/validation" +) + +// ResultCode represents the status of an operation +type ResultCode string + +const ( + ResultCodeSuccess ResultCode = "SUCCESS" + ResultCodeError ResultCode = "ERROR" +) + +// Result represents the result of a use case operation +type Result struct { + Code ResultCode + Data interface{} + Errors []*Error + Message string +} + +// Error represents an error in the use case layer +type Error struct { + Code string + Message string + Details map[string]interface{} +} + +// Error implements the error interface +func (e *Error) Error() string { + if e == nil { + return "" + } + if len(e.Details) > 0 { + return fmt.Sprintf("%s: %s (details: %v)", e.Code, e.Message, e.Details) + } + return fmt.Sprintf("%s: %s", e.Code, e.Message) +} + +// NewResult creates a new success result with data +func NewResult(data interface{}) *Result { + return &Result{ + Code: ResultCodeSuccess, + Data: data, + } +} + +// NewErrorResult creates a new error result +func NewErrorResult(code string, message string, details map[string]interface{}) *Result { + return &Result{ + Code: ResultCodeError, + Errors: []*Error{ + { + Code: code, + Message: message, + Details: details, + }, + }, + } +} + +// NewValidationErrorResult creates a new validation error result +func NewValidationErrorResult(validationErrors []*validation.Error) *Result { + errors := make([]*Error, len(validationErrors)) + for i, ve := range validationErrors { + errors[i] = &Error{ + Code: "VALIDATION_ERROR", + Message: ve.Error(), + Details: map[string]interface{}{ + "field": ve.Field, + }, + } + } + + return &Result{ + Code: ResultCodeError, + Errors: errors, + } +} + +// IsSuccess returns true if the result represents a successful operation +func (r *Result) IsSuccess() bool { + return r.Code == ResultCodeSuccess +} + +// GetError returns the first error if any +func (r *Result) GetError() error { + if len(r.Errors) > 0 { + return r.Errors[0] + } + return nil +} + +// WithMessage adds a message to the result +func (r *Result) WithMessage(message string) *Result { + r.Message = message + return r +} + +// Error implements the error interface for Result +func (r *Result) Error() string { + if r == nil || len(r.Errors) == 0 { + return "" + } + return r.Errors[0].Error() +} diff --git a/asset/usecase/transaction.go b/asset/usecase/transaction.go new file mode 100644 index 0000000..f321aea --- /dev/null +++ b/asset/usecase/transaction.go @@ -0,0 +1,26 @@ +package assetusecase + +import ( + "context" +) + +// TransactionManager defines the interface for managing transactions +type TransactionManager interface { + // WithTransaction executes the given function within a transaction + // If the function returns an error, the transaction is rolled back + // If the function returns nil, the transaction is committed + WithTransaction(ctx context.Context, fn func(ctx context.Context) error) error +} + +// TransactionKey is the context key for storing transaction information +type transactionKey struct{} + +// NewTransactionContext creates a new context with transaction information +func NewTransactionContext(ctx context.Context, tx interface{}) context.Context { + return context.WithValue(ctx, transactionKey{}, tx) +} + +// GetTransactionFromContext retrieves transaction information from context +func GetTransactionFromContext(ctx context.Context) interface{} { + return ctx.Value(transactionKey{}) +} diff --git a/asset/usecase/usecase.go b/asset/usecase/usecase.go new file mode 100644 index 0000000..37f8030 --- /dev/null +++ b/asset/usecase/usecase.go @@ -0,0 +1,61 @@ +package assetusecase + +import ( + "context" + "io" + "time" + + "github.com/reearth/reearthx/asset/domain/entity" + "github.com/reearth/reearthx/asset/domain/id" +) + +// DeliverOptions contains options for asset delivery +type DeliverOptions struct { + Transform bool // Whether to transform the content + ContentType string // Optional content type override + Headers map[string]string // Additional response headers + MaxAge int // Cache control max age in seconds + Disposition string // Content disposition (inline/attachment) +} + +// DecompressStatus represents the status of a decompression job +type DecompressStatus struct { + JobID string + AssetID id.ID + Status string // "pending", "processing", "completed", "failed" + Progress float64 // 0-100 + Error string + StartedAt time.Time + CompletedAt time.Time +} + +type Usecase interface { + // CreateAsset creates a new asset + CreateAsset(ctx context.Context, asset *entity.Asset) *Result + // GetAsset retrieves an asset by ID + GetAsset(ctx context.Context, id id.ID) *Result + // UpdateAsset updates an existing asset + UpdateAsset(ctx context.Context, asset *entity.Asset) *Result + // DeleteAsset removes an asset by ID + DeleteAsset(ctx context.Context, id id.ID) *Result + // UploadAssetContent uploads content for an asset with the given ID + UploadAssetContent(ctx context.Context, id id.ID, content io.Reader) *Result + // DownloadAssetContent retrieves the content of an asset by ID + DownloadAssetContent(ctx context.Context, id id.ID) *Result + // GetAssetUploadURL generates a URL for uploading content to an asset + GetAssetUploadURL(ctx context.Context, id id.ID) *Result + // ListAssets returns all assets + ListAssets(ctx context.Context) *Result + // DecompressZipContent decompresses zip content and returns a channel of decompressed files + DecompressZipContent(ctx context.Context, content []byte) *Result + // CompressToZip compresses the provided files into a zip archive + CompressToZip(ctx context.Context, files map[string]io.Reader) *Result + // DeleteAllAssetsInGroup deletes all assets in a group + DeleteAllAssetsInGroup(ctx context.Context, groupID id.GroupID) *Result + // DeliverAsset proxies the asset content with optional transformations + DeliverAsset(ctx context.Context, id id.ID, options *DeliverOptions) *Result + // GetDecompressStatus gets the current status of an async decompression + GetDecompressStatus(ctx context.Context, jobID string) *Result + // ListDecompressJobs lists all active decompression jobs + ListDecompressJobs(ctx context.Context) *Result +} diff --git a/go.mod b/go.mod index ab466a0..67b41a6 100644 --- a/go.mod +++ b/go.mod @@ -29,29 +29,49 @@ require ( github.com/samber/lo v1.39.0 github.com/sendgrid/sendgrid-go v3.14.0+incompatible github.com/spf13/afero v1.11.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible github.com/vektah/gqlparser/v2 v2.5.11 github.com/zitadel/oidc v1.13.5 go.mongodb.org/mongo-driver v1.13.1 - go.opentelemetry.io/otel v1.22.0 - go.opentelemetry.io/otel/sdk v1.22.0 + go.opentelemetry.io/otel v1.29.0 + go.opentelemetry.io/otel/sdk v1.29.0 go.uber.org/atomic v1.11.0 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.31.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a - golang.org/x/text v0.14.0 + golang.org/x/text v0.21.0 gopkg.in/go-jose/go-jose.v2 v2.6.2 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v2 v2.4.0 ) require ( - cloud.google.com/go/compute v1.23.4 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/trace v1.10.5 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.45.0 // indirect + cel.dev/expr v0.16.1 // indirect + cloud.google.com/go v0.116.0 // indirect + cloud.google.com/go/auth v0.13.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect + cloud.google.com/go/iam v1.2.2 // indirect + cloud.google.com/go/monitoring v1.21.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect + github.com/envoyproxy/go-control-plane v0.13.1 // indirect + github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect +) + +require ( + cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/storage v1.49.0 + cloud.google.com/go/trace v1.11.2 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/alexflint/go-arg v1.4.3 // indirect @@ -71,14 +91,13 @@ require ( github.com/dgryski/trifles v0.0.0-20200705224438-cafc02a1ee2b // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/google/s2a-go v0.1.7 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/s2a-go v0.1.8 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.14.0 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -98,7 +117,7 @@ require ( github.com/sendgrid/rest v2.6.9+incompatible // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sosodev/duration v1.2.0 // indirect - github.com/stretchr/objx v0.5.1 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect @@ -108,25 +127,24 @@ require ( github.com/zitadel/logging v0.3.4 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib v1.22.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.17.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/api v0.161.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/grpc v1.61.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect + google.golang.org/api v0.214.0 + google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/grpc v1.67.3 // indirect + google.golang.org/protobuf v1.35.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fe2f940..9258c53 100644 --- a/go.sum +++ b/go.sum @@ -1,31 +1,44 @@ +cel.dev/expr v0.16.1 h1:NR0+oFYzR1CqLFhTAqg3ql59G9VfN8fKq1TCHJ6gq1g= +cel.dev/expr v0.16.1/go.mod h1:AsGA5zb3WruAEQeQng1RZdGEXmBj0jvMWh6l5SnNuC8= cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= -cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/logging v1.9.0 h1:iEIOXFO9EmSiTjDmfpbRjOxECO7R8C7b8IXUGOj7xZw= -cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= -cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= -cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= -cloud.google.com/go/monitoring v1.17.0 h1:blrdvF0MkPPivSO041ihul7rFMhXdVp8Uq7F59DKXTU= -cloud.google.com/go/monitoring v1.17.0/go.mod h1:KwSsX5+8PnXv5NJnICZzW2R8pWTis8ypC4zmdRD63Tw= -cloud.google.com/go/trace v1.10.5 h1:0pr4lIKJ5XZFYD9GtxXEWr0KkVeigc3wlGpZco0X1oA= -cloud.google.com/go/trace v1.10.5/go.mod h1:9hjCV1nGBCtXbAE4YK7OqJ8pmPYSxPA0I67JwRd5s3M= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= +cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= +cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= +cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= +cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= +cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= +cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= +cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/gqlgen v0.17.43 h1:I4SYg6ahjowErAQcHFVKy5EcWuwJ3+Xw9z2fLpuFCPo= github.com/99designs/gqlgen v0.17.43/go.mod h1:lO0Zjy8MkZgBdv4T1U91x09r0e0WFOdhVUutlQs1Rsc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.21.0 h1:OEgjQy1rH4Fbn5IpuI9d0uhLl+j6DkDvh9Q2Ucd6GK8= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.21.0/go.mod h1:EUfJ8lb3pjD8VasPPwqIvG2XVCE6DOT8tY5tcwbWA+A= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.45.0 h1:/BF7rO6PYcmFoyJrq6HA3LqQpFSQei9aNuO1fvV3OqU= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.45.0/go.mod h1:WntFIMzxcU+PMBuekFc34UOsEZ9sP+vsnBYTyaNBkOs= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.45.0 h1:o/Nf55GfyLwGDaHkVAkRGgBXeExce73L6N9w2PZTB3k= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.45.0/go.mod h1:qkFPtMouQjW5ugdHIOthiTbweVHUTqbS0Qsu55KqXks= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1/go.mod h1:0wEl7vrAD8mehJyohS9HZy+WyEOaQO2mJx86Cvh93kM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Khan/genqlient v0.6.0 h1:Bwb1170ekuNIVIwTJEqvO8y7RxBxXu639VJOkKSrwAk= @@ -78,10 +91,14 @@ github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6 github.com/bradleyjkemp/cupaloy/v2 v2.6.0 h1:knToPYa2xtfg42U3I6punFEjaGFKWQRXJwj0JTv4mTs= github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -92,9 +109,11 @@ github.com/dgryski/trifles v0.0.0-20200705224438-cafc02a1ee2b/go.mod h1:if7Fbed8 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE= +github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -104,8 +123,8 @@ github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhs github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= @@ -140,14 +159,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -157,20 +172,21 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= @@ -205,6 +221,8 @@ github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -237,7 +255,6 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6f github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -246,6 +263,8 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.2.2-0.20190308074557-af07aa5181b3/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= @@ -254,6 +273,8 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/ravilushqa/otelgqlgen v0.15.0 h1:U85nrlweMXTGaMChUViYM39/MXBZVeVVlpuHq+6eECQ= github.com/ravilushqa/otelgqlgen v0.15.0/go.mod h1:o+1Eju0VySmgq2BP8Vupz2YrN21Bj7D7imBqu3m2uB8= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= @@ -279,8 +300,8 @@ github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7Sr github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -288,9 +309,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= @@ -320,22 +340,28 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib v1.22.0 h1:QflN9z334UrOPzGGEr8VaMlWm+i+d9YLW8KzQtbvmBM= go.opentelemetry.io/contrib v1.22.0/go.mod h1:usW9bPlrjHiJFbK0a6yK/M5wNHs3nLmtrT3vzhoD3co= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/contrib/detectors/gcp v1.29.0 h1:TiaiXB4DpGD3sdzNlYQxruQngn5Apwzi1X0DRhuGvDQ= +go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -345,8 +371,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -364,8 +390,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -377,19 +403,19 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -408,8 +434,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -419,11 +445,11 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -434,8 +460,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -446,31 +472,29 @@ gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.161.0 h1:oYzk/bs26WN10AV7iU7MVJVXBH8oCPS2hHyBiEeFoSU= -google.golang.org/api v0.161.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= +google.golang.org/api v0.214.0 h1:h2Gkq07OYi6kusGOaT/9rnNljuXmqPnaig7WGPmKbwA= +google.golang.org/api v0.214.0/go.mod h1:bYPpLG8AyeMWwDU6NXoB00xC0DFkikVvd5MfwoxjLqE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe h1:USL2DhxfgRchafRvt/wYyyQNzwgL7ZiURcozOE/Pkvo= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= +google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:pgr/4QbFyktUv9CtQ/Fq4gzEE6/Xs7iCXbktaGzLHbQ= +google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8= +google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -480,16 +504,14 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/go-jose/go-jose.v2 v2.6.2 h1:Rl5+9rA0kG3vsO1qhncMPRT5eHICihAMQYJkD7u/i4M= gopkg.in/go-jose/go-jose.v2 v2.6.2/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=