diff --git a/conversion/ent_to_graphql.go b/conversion/ent_to_graphql.go index 57b3afcf..29a61749 100644 --- a/conversion/ent_to_graphql.go +++ b/conversion/ent_to_graphql.go @@ -99,7 +99,7 @@ type Mod interface { // goverter:extend TimeToString UIntToInt Int64ToInt type Version interface { // goverter:map Edges.Targets Targets - // goverter:ignore Link Mod Dependencies SmlVersion + // goverter:ignore Link Mod Dependencies SmlVersion VirustotalResults Convert(source *ent.Version) *generated.Version ConvertSlice(source []*ent.Version) []*generated.Version @@ -118,6 +118,15 @@ type VersionDependency interface { ConvertSlice(source []*ent.VersionDependency) []*generated.VersionDependency } +// goverter:converter +// goverter:output:file ../generated/conv/virustotal_result.go +// goverter:output:package conv +// goverter:extend TimeToString UIntToInt Int64ToInt +type VirustotalResult interface { + Convert(source *ent.VirustotalResult) *generated.VirustotalResult + ConvertSlice(source []*ent.VirustotalResult) []*generated.VirustotalResult +} + func TimeToString(i time.Time) string { return i.Format(time.RFC3339) } diff --git a/db/schema/version.go b/db/schema/version.go index 87a2fc4a..c84726b3 100644 --- a/db/schema/version.go +++ b/db/schema/version.go @@ -61,5 +61,6 @@ func (Version) Edges() []ent.Edge { edge.To("dependencies", Mod.Type). Through("version_dependencies", VersionDependency.Type), edge.To("targets", VersionTarget.Type), + edge.To("virustotal_results", VirustotalResult.Type), } } diff --git a/db/schema/virustotal_result.go b/db/schema/virustotal_result.go new file mode 100644 index 00000000..efc63317 --- /dev/null +++ b/db/schema/virustotal_result.go @@ -0,0 +1,45 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" +) + +type VirustotalResult struct { + ent.Schema +} + +func (VirustotalResult) Mixin() []ent.Mixin { + return []ent.Mixin{ + IDMixin{}, + TimeMixin{}, + } +} + +func (VirustotalResult) Fields() []ent.Field { + return []ent.Field{ + field.Bool("safe").Default(false), + field.String("hash").Unique().NotEmpty(), + field.String("file_name").NotEmpty(), + field.String("version_id").NotEmpty(), + } +} + +func (VirustotalResult) Annotations() []schema.Annotation { + return []schema.Annotation{ + entsql.Annotation{Table: "virustotal_results"}, + } +} + +func (VirustotalResult) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("version", Version.Type). + Ref("virustotal_results"). + Field("version_id"). + Unique(). + Required(), + } +} diff --git a/generated/conv/version.go b/generated/conv/version.go index 0a5673c7..811d2cb4 100755 --- a/generated/conv/version.go +++ b/generated/conv/version.go @@ -129,6 +129,7 @@ func (c *VersionImpl) ConvertTarget(source *ent.VersionTarget) *generated.Versio generatedVersionTarget.Size = &pInt pString := (*source).Hash generatedVersionTarget.Hash = &pString + generatedVersionTarget.ID = (*source).ID pGeneratedVersionTarget = &generatedVersionTarget } return pGeneratedVersionTarget diff --git a/generated/conv/virustotal_result.go b/generated/conv/virustotal_result.go new file mode 100644 index 00000000..12033788 --- /dev/null +++ b/generated/conv/virustotal_result.go @@ -0,0 +1,44 @@ +// Code generated by github.com/jmattheis/goverter, DO NOT EDIT. +//go:build !goverter + +package conv + +import ( + conversion "github.com/satisfactorymodding/smr-api/conversion" + generated "github.com/satisfactorymodding/smr-api/generated" + ent "github.com/satisfactorymodding/smr-api/generated/ent" + "time" +) + +type VirustotalResultImpl struct{} + +func (c *VirustotalResultImpl) Convert(source *ent.VirustotalResult) *generated.VirustotalResult { + var pGeneratedVirustotalResult *generated.VirustotalResult + if source != nil { + var generatedVirustotalResult generated.VirustotalResult + pString := (*source).ID + generatedVirustotalResult.ID = &pString + generatedVirustotalResult.Hash = (*source).Hash + generatedVirustotalResult.Safe = (*source).Safe + generatedVirustotalResult.FileName = (*source).FileName + generatedVirustotalResult.VersionID = (*source).VersionID + generatedVirustotalResult.CreatedAt = conversion.TimeToString((*source).CreatedAt) + generatedVirustotalResult.UpdatedAt = c.timeTimeToPString((*source).UpdatedAt) + pGeneratedVirustotalResult = &generatedVirustotalResult + } + return pGeneratedVirustotalResult +} +func (c *VirustotalResultImpl) ConvertSlice(source []*ent.VirustotalResult) []*generated.VirustotalResult { + var pGeneratedVirustotalResultList []*generated.VirustotalResult + if source != nil { + pGeneratedVirustotalResultList = make([]*generated.VirustotalResult, len(source)) + for i := 0; i < len(source); i++ { + pGeneratedVirustotalResultList[i] = c.Convert(source[i]) + } + } + return pGeneratedVirustotalResultList +} +func (c *VirustotalResultImpl) timeTimeToPString(source time.Time) *string { + xstring := conversion.TimeToString(source) + return &xstring +} diff --git a/generated/ent/client.go b/generated/ent/client.go index bbf32d69..229f799d 100644 --- a/generated/ent/client.go +++ b/generated/ent/client.go @@ -29,6 +29,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiondependency" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" stdsql "database/sql" ) @@ -66,6 +67,8 @@ type Client struct { VersionDependency *VersionDependencyClient // VersionTarget is the client for interacting with the VersionTarget builders. VersionTarget *VersionTargetClient + // VirustotalResult is the client for interacting with the VirustotalResult builders. + VirustotalResult *VirustotalResultClient } // NewClient creates a new client configured with the given options. @@ -91,6 +94,7 @@ func (c *Client) init() { c.Version = NewVersionClient(c.config) c.VersionDependency = NewVersionDependencyClient(c.config) c.VersionTarget = NewVersionTargetClient(c.config) + c.VirustotalResult = NewVirustotalResultClient(c.config) } type ( @@ -197,6 +201,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { Version: NewVersionClient(cfg), VersionDependency: NewVersionDependencyClient(cfg), VersionTarget: NewVersionTargetClient(cfg), + VirustotalResult: NewVirustotalResultClient(cfg), }, nil } @@ -230,6 +235,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) Version: NewVersionClient(cfg), VersionDependency: NewVersionDependencyClient(cfg), VersionTarget: NewVersionTargetClient(cfg), + VirustotalResult: NewVirustotalResultClient(cfg), }, nil } @@ -261,7 +267,7 @@ func (c *Client) Use(hooks ...Hook) { for _, n := range []interface{ Use(...Hook) }{ c.Announcement, c.Guide, c.GuideTag, c.Mod, c.ModTag, c.SatisfactoryVersion, c.Tag, c.User, c.UserGroup, c.UserMod, c.UserSession, c.Version, - c.VersionDependency, c.VersionTarget, + c.VersionDependency, c.VersionTarget, c.VirustotalResult, } { n.Use(hooks...) } @@ -273,7 +279,7 @@ func (c *Client) Intercept(interceptors ...Interceptor) { for _, n := range []interface{ Intercept(...Interceptor) }{ c.Announcement, c.Guide, c.GuideTag, c.Mod, c.ModTag, c.SatisfactoryVersion, c.Tag, c.User, c.UserGroup, c.UserMod, c.UserSession, c.Version, - c.VersionDependency, c.VersionTarget, + c.VersionDependency, c.VersionTarget, c.VirustotalResult, } { n.Intercept(interceptors...) } @@ -310,6 +316,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.VersionDependency.mutate(ctx, m) case *VersionTargetMutation: return c.VersionTarget.mutate(ctx, m) + case *VirustotalResultMutation: + return c.VirustotalResult.mutate(ctx, m) default: return nil, fmt.Errorf("ent: unknown mutation type %T", m) } @@ -2233,6 +2241,22 @@ func (c *VersionClient) QueryTargets(v *Version) *VersionTargetQuery { return query } +// QueryVirustotalResults queries the virustotal_results edge of a Version. +func (c *VersionClient) QueryVirustotalResults(v *Version) *VirustotalResultQuery { + query := (&VirustotalResultClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := v.ID + step := sqlgraph.NewStep( + sqlgraph.From(version.Table, version.FieldID, id), + sqlgraph.To(virustotalresult.Table, virustotalresult.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, version.VirustotalResultsTable, version.VirustotalResultsColumn), + ) + fromV = sqlgraph.Neighbors(v.driver.Dialect(), step) + return fromV, nil + } + return query +} + // QueryVersionDependencies queries the version_dependencies edge of a Version. func (c *VersionClient) QueryVersionDependencies(v *Version) *VersionDependencyQuery { query := (&VersionDependencyClient{config: c.config}).Query() @@ -2543,17 +2567,166 @@ func (c *VersionTargetClient) mutate(ctx context.Context, m *VersionTargetMutati } } +// VirustotalResultClient is a client for the VirustotalResult schema. +type VirustotalResultClient struct { + config +} + +// NewVirustotalResultClient returns a client for the VirustotalResult from the given config. +func NewVirustotalResultClient(c config) *VirustotalResultClient { + return &VirustotalResultClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `virustotalresult.Hooks(f(g(h())))`. +func (c *VirustotalResultClient) Use(hooks ...Hook) { + c.hooks.VirustotalResult = append(c.hooks.VirustotalResult, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `virustotalresult.Intercept(f(g(h())))`. +func (c *VirustotalResultClient) Intercept(interceptors ...Interceptor) { + c.inters.VirustotalResult = append(c.inters.VirustotalResult, interceptors...) +} + +// Create returns a builder for creating a VirustotalResult entity. +func (c *VirustotalResultClient) Create() *VirustotalResultCreate { + mutation := newVirustotalResultMutation(c.config, OpCreate) + return &VirustotalResultCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of VirustotalResult entities. +func (c *VirustotalResultClient) CreateBulk(builders ...*VirustotalResultCreate) *VirustotalResultCreateBulk { + return &VirustotalResultCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *VirustotalResultClient) MapCreateBulk(slice any, setFunc func(*VirustotalResultCreate, int)) *VirustotalResultCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &VirustotalResultCreateBulk{err: fmt.Errorf("calling to VirustotalResultClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*VirustotalResultCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &VirustotalResultCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for VirustotalResult. +func (c *VirustotalResultClient) Update() *VirustotalResultUpdate { + mutation := newVirustotalResultMutation(c.config, OpUpdate) + return &VirustotalResultUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *VirustotalResultClient) UpdateOne(vr *VirustotalResult) *VirustotalResultUpdateOne { + mutation := newVirustotalResultMutation(c.config, OpUpdateOne, withVirustotalResult(vr)) + return &VirustotalResultUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *VirustotalResultClient) UpdateOneID(id string) *VirustotalResultUpdateOne { + mutation := newVirustotalResultMutation(c.config, OpUpdateOne, withVirustotalResultID(id)) + return &VirustotalResultUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for VirustotalResult. +func (c *VirustotalResultClient) Delete() *VirustotalResultDelete { + mutation := newVirustotalResultMutation(c.config, OpDelete) + return &VirustotalResultDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *VirustotalResultClient) DeleteOne(vr *VirustotalResult) *VirustotalResultDeleteOne { + return c.DeleteOneID(vr.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *VirustotalResultClient) DeleteOneID(id string) *VirustotalResultDeleteOne { + builder := c.Delete().Where(virustotalresult.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &VirustotalResultDeleteOne{builder} +} + +// Query returns a query builder for VirustotalResult. +func (c *VirustotalResultClient) Query() *VirustotalResultQuery { + return &VirustotalResultQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeVirustotalResult}, + inters: c.Interceptors(), + } +} + +// Get returns a VirustotalResult entity by its id. +func (c *VirustotalResultClient) Get(ctx context.Context, id string) (*VirustotalResult, error) { + return c.Query().Where(virustotalresult.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *VirustotalResultClient) GetX(ctx context.Context, id string) *VirustotalResult { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryVersion queries the version edge of a VirustotalResult. +func (c *VirustotalResultClient) QueryVersion(vr *VirustotalResult) *VersionQuery { + query := (&VersionClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := vr.ID + step := sqlgraph.NewStep( + sqlgraph.From(virustotalresult.Table, virustotalresult.FieldID, id), + sqlgraph.To(version.Table, version.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, virustotalresult.VersionTable, virustotalresult.VersionColumn), + ) + fromV = sqlgraph.Neighbors(vr.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *VirustotalResultClient) Hooks() []Hook { + return c.hooks.VirustotalResult +} + +// Interceptors returns the client interceptors. +func (c *VirustotalResultClient) Interceptors() []Interceptor { + return c.inters.VirustotalResult +} + +func (c *VirustotalResultClient) mutate(ctx context.Context, m *VirustotalResultMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&VirustotalResultCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&VirustotalResultUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&VirustotalResultUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&VirustotalResultDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown VirustotalResult mutation op: %q", m.Op()) + } +} + // hooks and interceptors per client, for fast access. type ( hooks struct { Announcement, Guide, GuideTag, Mod, ModTag, SatisfactoryVersion, Tag, User, - UserGroup, UserMod, UserSession, Version, VersionDependency, - VersionTarget []ent.Hook + UserGroup, UserMod, UserSession, Version, VersionDependency, VersionTarget, + VirustotalResult []ent.Hook } inters struct { Announcement, Guide, GuideTag, Mod, ModTag, SatisfactoryVersion, Tag, User, - UserGroup, UserMod, UserSession, Version, VersionDependency, - VersionTarget []ent.Interceptor + UserGroup, UserMod, UserSession, Version, VersionDependency, VersionTarget, + VirustotalResult []ent.Interceptor } ) diff --git a/generated/ent/ent.go b/generated/ent/ent.go index 83819a87..f85692b0 100644 --- a/generated/ent/ent.go +++ b/generated/ent/ent.go @@ -26,6 +26,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiondependency" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" ) // ent aliases to avoid import conflicts in user's code. @@ -100,6 +101,7 @@ func checkColumn(table, column string) error { version.Table: version.ValidColumn, versiondependency.Table: versiondependency.ValidColumn, versiontarget.Table: versiontarget.ValidColumn, + virustotalresult.Table: virustotalresult.ValidColumn, }) }) return columnCheck(table, column) diff --git a/generated/ent/hook/hook.go b/generated/ent/hook/hook.go index 2d493f83..45849c4c 100644 --- a/generated/ent/hook/hook.go +++ b/generated/ent/hook/hook.go @@ -177,6 +177,18 @@ func (f VersionTargetFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Valu return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.VersionTargetMutation", m) } +// The VirustotalResultFunc type is an adapter to allow the use of ordinary +// function as VirustotalResult mutator. +type VirustotalResultFunc func(context.Context, *ent.VirustotalResultMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f VirustotalResultFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.VirustotalResultMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.VirustotalResultMutation", m) +} + // Condition is a hook condition function. type Condition func(context.Context, ent.Mutation) bool diff --git a/generated/ent/intercept/intercept.go b/generated/ent/intercept/intercept.go index b2049660..d56f178f 100644 --- a/generated/ent/intercept/intercept.go +++ b/generated/ent/intercept/intercept.go @@ -23,6 +23,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiondependency" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" ) // The Query interface represents an operation that queries a graph. @@ -459,6 +460,33 @@ func (f TraverseVersionTarget) Traverse(ctx context.Context, q ent.Query) error return fmt.Errorf("unexpected query type %T. expect *ent.VersionTargetQuery", q) } +// The VirustotalResultFunc type is an adapter to allow the use of ordinary function as a Querier. +type VirustotalResultFunc func(context.Context, *ent.VirustotalResultQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f VirustotalResultFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.VirustotalResultQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.VirustotalResultQuery", q) +} + +// The TraverseVirustotalResult type is an adapter to allow the use of ordinary function as Traverser. +type TraverseVirustotalResult func(context.Context, *ent.VirustotalResultQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseVirustotalResult) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseVirustotalResult) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.VirustotalResultQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.VirustotalResultQuery", q) +} + // NewQuery returns the generic Query interface for the given typed query. func NewQuery(q ent.Query) (Query, error) { switch q := q.(type) { @@ -490,6 +518,8 @@ func NewQuery(q ent.Query) (Query, error) { return &query[*ent.VersionDependencyQuery, predicate.VersionDependency, versiondependency.OrderOption]{typ: ent.TypeVersionDependency, tq: q}, nil case *ent.VersionTargetQuery: return &query[*ent.VersionTargetQuery, predicate.VersionTarget, versiontarget.OrderOption]{typ: ent.TypeVersionTarget, tq: q}, nil + case *ent.VirustotalResultQuery: + return &query[*ent.VirustotalResultQuery, predicate.VirustotalResult, virustotalresult.OrderOption]{typ: ent.TypeVirustotalResult, tq: q}, nil default: return nil, fmt.Errorf("unknown query type %T", q) } diff --git a/generated/ent/internal/schema.go b/generated/ent/internal/schema.go index f3baf616..224e810d 100644 --- a/generated/ent/internal/schema.go +++ b/generated/ent/internal/schema.go @@ -6,4 +6,4 @@ // Package internal holds a loadable version of the latest schema. package internal -const Schema = "{\"Schema\":\"github.com/satisfactorymodding/smr-api/db/schema\",\"Package\":\"github.com/satisfactorymodding/smr-api/generated/ent\",\"Schemas\":[{\"name\":\"Announcement\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"message\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"importance\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"Guide\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"guides\",\"unique\":true,\"inverse\":true},{\"name\":\"tags\",\"type\":\"Tag\",\"through\":{\"N\":\"guide_tags\",\"T\":\"GuideTag\"}}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"user_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"short_description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":128,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"guide\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"GuideTag\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"guide\",\"type\":\"Guide\",\"field\":\"guide_id\",\"unique\":true,\"required\":true},{\"name\":\"tag\",\"type\":\"Tag\",\"field\":\"tag_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"guide_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"tag_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"annotations\":{\"Fields\":{\"ID\":[\"guide_id\",\"tag_id\"],\"StructTag\":null}}},{\"name\":\"Mod\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"versions\",\"type\":\"Version\"},{\"name\":\"authors\",\"type\":\"User\",\"ref_name\":\"mods\",\"through\":{\"N\":\"user_mods\",\"T\":\"UserMod\"},\"inverse\":true},{\"name\":\"tags\",\"type\":\"Tag\",\"through\":{\"N\":\"mod_tags\",\"T\":\"ModTag\"}},{\"name\":\"dependents\",\"type\":\"Version\",\"ref_name\":\"dependencies\",\"through\":{\"N\":\"version_dependencies\",\"T\":\"VersionDependency\"},\"inverse\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"short_description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":128,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"full_description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"logo\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"logo_thumbhash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source_url\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"creator_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"approved\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hotness\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"popularity\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"denied\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_version_date\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":13,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_reference\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":14,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hidden\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":15,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"compatibility\",\"type\":{\"Type\":3,\"Ident\":\"*util.CompatibilityInfo\",\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"PkgName\":\"util\",\"Nillable\":true,\"RType\":{\"Name\":\"CompatibilityInfo\",\"Ident\":\"util.CompatibilityInfo\",\"Kind\":22,\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":16,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"toggle_network_use\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":17,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"toggle_explicit_content\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":18,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"fields\":[\"last_version_date\"]},{\"unique\":true,\"fields\":[\"mod_reference\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"ModTag\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"unique\":true,\"required\":true},{\"name\":\"tag\",\"type\":\"Tag\",\"field\":\"tag_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"tag_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"annotations\":{\"Fields\":{\"ID\":[\"mod_id\",\"tag_id\"],\"StructTag\":null}}},{\"name\":\"SatisfactoryVersion\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"version\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"engine_version\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"default\":true,\"default_value\":\"4.26\",\"default_kind\":24,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}]},{\"name\":\"Tag\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"mods\",\"type\":\"Mod\",\"ref_name\":\"tags\",\"through\":{\"N\":\"mod_tags\",\"T\":\"ModTag\"},\"inverse\":true},{\"name\":\"guides\",\"type\":\"Guide\",\"ref_name\":\"tags\",\"through\":{\"N\":\"guide_tags\",\"T\":\"GuideTag\"},\"inverse\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":24,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":512,\"optional\":true,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"guides\",\"type\":\"Guide\"},{\"name\":\"sessions\",\"type\":\"UserSession\",\"storage_key\":{\"Table\":\"\",\"Symbols\":null,\"Columns\":[\"user_id\"]}},{\"name\":\"mods\",\"type\":\"Mod\",\"through\":{\"N\":\"user_mods\",\"T\":\"UserMod\"}},{\"name\":\"groups\",\"type\":\"UserGroup\"}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":256,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"username\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"avatar_thumbhash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"joined_from\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"banned\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"rank\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"github_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"optional\":true,\"validators\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"google_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"optional\":true,\"validators\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"facebook_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"optional\":true,\"validators\":1,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"unique\":true,\"fields\":[\"email\"]},{\"unique\":true,\"fields\":[\"github_id\"]},{\"unique\":true,\"fields\":[\"google_id\"]},{\"unique\":true,\"fields\":[\"facebook_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"UserGroup\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"user_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":14,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":14,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"unique\":true,\"fields\":[\"user_id\",\"group_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"UserMod\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"unique\":true,\"required\":true},{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"user_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"role\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"annotations\":{\"Fields\":{\"ID\":[\"user_id\",\"mod_id\"],\"StructTag\":null}}},{\"name\":\"UserSession\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"sessions\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"token\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":512,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_agent\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"unique\":true,\"fields\":[\"token\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"Version\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"ref_name\":\"versions\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"dependencies\",\"type\":\"Mod\",\"through\":{\"N\":\"version_dependencies\",\"T\":\"VersionDependency\"}},{\"name\":\"targets\",\"type\":\"VersionTarget\"}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"game_version\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"changelog\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"stability\",\"type\":{\"Type\":6,\"Ident\":\"util.Stability\",\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"PkgName\":\"util\",\"Nillable\":false,\"RType\":{\"Name\":\"Stability\",\"Ident\":\"util.Stability\",\"Kind\":24,\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"Methods\":{\"Values\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"enums\":[{\"N\":\"release\",\"V\":\"release\"},{\"N\":\"beta\",\"V\":\"beta\"},{\"N\":\"alpha\",\"V\":\"alpha\"}],\"default\":true,\"default_value\":\"release\",\"default_kind\":24,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"approved\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hotness\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"denied\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"metadata\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_reference\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version_major\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version_minor\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":13,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version_patch\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":14,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":15,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":64,\"optional\":true,\"validators\":2,\"position\":{\"Index\":16,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"fields\":[\"approved\"]},{\"fields\":[\"denied\"]},{\"fields\":[\"mod_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"VersionDependency\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"version\",\"type\":\"Version\",\"field\":\"version_id\",\"unique\":true,\"required\":true},{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"version_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"condition\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":64,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"optional\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}],\"annotations\":{\"Fields\":{\"ID\":[\"version_id\",\"mod_id\"],\"StructTag\":null}}},{\"name\":\"VersionTarget\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"version\",\"type\":\"Version\",\"field\":\"version_id\",\"ref_name\":\"targets\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"version_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"target_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"version_id\",\"target_name\"]}]}],\"Features\":[\"sql/modifier\",\"intercept\",\"schema/snapshot\",\"sql/execquery\",\"sql/upsert\"]}" +const Schema = "{\"Schema\":\"github.com/satisfactorymodding/smr-api/db/schema\",\"Package\":\"github.com/satisfactorymodding/smr-api/generated/ent\",\"Schemas\":[{\"name\":\"Announcement\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"message\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"importance\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"Guide\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"guides\",\"unique\":true,\"inverse\":true},{\"name\":\"tags\",\"type\":\"Tag\",\"through\":{\"N\":\"guide_tags\",\"T\":\"GuideTag\"}}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"user_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"short_description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":128,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"guide\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"GuideTag\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"guide\",\"type\":\"Guide\",\"field\":\"guide_id\",\"unique\":true,\"required\":true},{\"name\":\"tag\",\"type\":\"Tag\",\"field\":\"tag_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"guide_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"tag_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"annotations\":{\"Fields\":{\"ID\":[\"guide_id\",\"tag_id\"],\"StructTag\":null}}},{\"name\":\"Mod\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"versions\",\"type\":\"Version\"},{\"name\":\"authors\",\"type\":\"User\",\"ref_name\":\"mods\",\"through\":{\"N\":\"user_mods\",\"T\":\"UserMod\"},\"inverse\":true},{\"name\":\"tags\",\"type\":\"Tag\",\"through\":{\"N\":\"mod_tags\",\"T\":\"ModTag\"}},{\"name\":\"dependents\",\"type\":\"Version\",\"ref_name\":\"dependencies\",\"through\":{\"N\":\"version_dependencies\",\"T\":\"VersionDependency\"},\"inverse\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"short_description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":128,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"full_description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"logo\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"logo_thumbhash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source_url\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"creator_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"approved\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hotness\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"popularity\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"denied\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_version_date\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":13,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_reference\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":14,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hidden\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":15,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"compatibility\",\"type\":{\"Type\":3,\"Ident\":\"*util.CompatibilityInfo\",\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"PkgName\":\"util\",\"Nillable\":true,\"RType\":{\"Name\":\"CompatibilityInfo\",\"Ident\":\"util.CompatibilityInfo\",\"Kind\":22,\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":16,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"toggle_network_use\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":17,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"toggle_explicit_content\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":18,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"fields\":[\"last_version_date\"]},{\"unique\":true,\"fields\":[\"mod_reference\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"ModTag\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"unique\":true,\"required\":true},{\"name\":\"tag\",\"type\":\"Tag\",\"field\":\"tag_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"tag_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"annotations\":{\"Fields\":{\"ID\":[\"mod_id\",\"tag_id\"],\"StructTag\":null}}},{\"name\":\"SatisfactoryVersion\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"version\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"engine_version\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"default\":true,\"default_value\":\"4.26\",\"default_kind\":24,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}]},{\"name\":\"Tag\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"mods\",\"type\":\"Mod\",\"ref_name\":\"tags\",\"through\":{\"N\":\"mod_tags\",\"T\":\"ModTag\"},\"inverse\":true},{\"name\":\"guides\",\"type\":\"Guide\",\"ref_name\":\"tags\",\"through\":{\"N\":\"guide_tags\",\"T\":\"GuideTag\"},\"inverse\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":24,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"description\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":512,\"optional\":true,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"guides\",\"type\":\"Guide\"},{\"name\":\"sessions\",\"type\":\"UserSession\",\"storage_key\":{\"Table\":\"\",\"Symbols\":null,\"Columns\":[\"user_id\"]}},{\"name\":\"mods\",\"type\":\"Mod\",\"through\":{\"N\":\"user_mods\",\"T\":\"UserMod\"}},{\"name\":\"groups\",\"type\":\"UserGroup\"}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":256,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"username\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"avatar_thumbhash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"joined_from\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"banned\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"rank\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"github_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"optional\":true,\"validators\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"google_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"optional\":true,\"validators\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"facebook_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"optional\":true,\"validators\":1,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"unique\":true,\"fields\":[\"email\"]},{\"unique\":true,\"fields\":[\"github_id\"]},{\"unique\":true,\"fields\":[\"google_id\"]},{\"unique\":true,\"fields\":[\"facebook_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"UserGroup\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"user_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":14,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":14,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"unique\":true,\"fields\":[\"user_id\",\"group_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"UserMod\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"unique\":true,\"required\":true},{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"user_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"role\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"annotations\":{\"Fields\":{\"ID\":[\"user_id\",\"mod_id\"],\"StructTag\":null}}},{\"name\":\"UserSession\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"sessions\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"token\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":512,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_agent\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"unique\":true,\"fields\":[\"token\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"Version\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"ref_name\":\"versions\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"dependencies\",\"type\":\"Mod\",\"through\":{\"N\":\"version_dependencies\",\"T\":\"VersionDependency\"}},{\"name\":\"targets\",\"type\":\"VersionTarget\"},{\"name\":\"virustotal_results\",\"type\":\"VirustotalResult\"}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}},{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":16,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"game_version\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"changelog\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"stability\",\"type\":{\"Type\":6,\"Ident\":\"util.Stability\",\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"PkgName\":\"util\",\"Nillable\":false,\"RType\":{\"Name\":\"Stability\",\"Ident\":\"util.Stability\",\"Kind\":24,\"PkgPath\":\"github.com/satisfactorymodding/smr-api/util\",\"Methods\":{\"Values\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"enums\":[{\"N\":\"release\",\"V\":\"release\"},{\"N\":\"beta\",\"V\":\"beta\"},{\"N\":\"alpha\",\"V\":\"alpha\"}],\"default\":true,\"default_value\":\"release\",\"default_kind\":24,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"approved\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hotness\",\"type\":{\"Type\":17,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":7,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"denied\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"metadata\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_reference\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":32,\"validators\":1,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version_major\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":12,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version_minor\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":13,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version_patch\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":14,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":15,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":64,\"optional\":true,\"validators\":2,\"position\":{\"Index\":16,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]},{\"fields\":[\"approved\"]},{\"fields\":[\"denied\"]},{\"fields\":[\"mod_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":2}]},{\"name\":\"VersionDependency\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"version\",\"type\":\"Version\",\"field\":\"version_id\",\"unique\":true,\"required\":true},{\"name\":\"mod\",\"type\":\"Mod\",\"field\":\"mod_id\",\"unique\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"version_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"mod_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"condition\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":64,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"optional\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"deleted_at\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}],\"annotations\":{\"Fields\":{\"ID\":[\"version_id\",\"mod_id\"],\"StructTag\":null}}},{\"name\":\"VersionTarget\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"version\",\"type\":\"Version\",\"field\":\"version_id\",\"ref_name\":\"targets\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"version_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"target_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"version_id\",\"target_name\"]}]},{\"name\":\"VirustotalResult\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"version\",\"type\":\"Version\",\"field\":\"version_id\",\"ref_name\":\"virustotal_results\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}},{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":1}},{\"name\":\"safe\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"hash\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"version_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"validators\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"annotations\":{\"EntSQL\":{\"table\":\"virustotal_results\"}}}],\"Features\":[\"sql/modifier\",\"intercept\",\"schema/snapshot\",\"sql/execquery\",\"sql/upsert\"]}" diff --git a/generated/ent/migrate/schema.go b/generated/ent/migrate/schema.go index 6f2294de..724e2e2e 100644 --- a/generated/ent/migrate/schema.go +++ b/generated/ent/migrate/schema.go @@ -3,6 +3,7 @@ package migrate import ( + "entgo.io/ent/dialect/entsql" "entgo.io/ent/dialect/sql/schema" "entgo.io/ent/schema/field" ) @@ -470,6 +471,30 @@ var ( }, }, } + // VirustotalResultsColumns holds the columns for the "virustotal_results" table. + VirustotalResultsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeString}, + {Name: "created_at", Type: field.TypeTime}, + {Name: "updated_at", Type: field.TypeTime}, + {Name: "safe", Type: field.TypeBool, Default: false}, + {Name: "hash", Type: field.TypeString, Unique: true}, + {Name: "file_name", Type: field.TypeString}, + {Name: "version_id", Type: field.TypeString}, + } + // VirustotalResultsTable holds the schema information for the "virustotal_results" table. + VirustotalResultsTable = &schema.Table{ + Name: "virustotal_results", + Columns: VirustotalResultsColumns, + PrimaryKey: []*schema.Column{VirustotalResultsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "virustotal_results_versions_virustotal_results", + Columns: []*schema.Column{VirustotalResultsColumns[6]}, + RefColumns: []*schema.Column{VersionsColumns[0]}, + OnDelete: schema.NoAction, + }, + }, + } // Tables holds all the tables in the schema. Tables = []*schema.Table{ AnnouncementsTable, @@ -486,6 +511,7 @@ var ( VersionsTable, VersionDependenciesTable, VersionTargetsTable, + VirustotalResultsTable, } ) @@ -503,4 +529,8 @@ func init() { VersionDependenciesTable.ForeignKeys[0].RefTable = VersionsTable VersionDependenciesTable.ForeignKeys[1].RefTable = ModsTable VersionTargetsTable.ForeignKeys[0].RefTable = VersionsTable + VirustotalResultsTable.ForeignKeys[0].RefTable = VersionsTable + VirustotalResultsTable.Annotation = &entsql.Annotation{ + Table: "virustotal_results", + } } diff --git a/generated/ent/mutation.go b/generated/ent/mutation.go index 8c9af714..0bdb0e20 100644 --- a/generated/ent/mutation.go +++ b/generated/ent/mutation.go @@ -26,6 +26,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiondependency" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" "github.com/satisfactorymodding/smr-api/util" ) @@ -52,6 +53,7 @@ const ( TypeVersion = "Version" TypeVersionDependency = "VersionDependency" TypeVersionTarget = "VersionTarget" + TypeVirustotalResult = "VirustotalResult" ) // AnnouncementMutation represents an operation that mutates the Announcement nodes in the graph. @@ -8727,46 +8729,49 @@ func (m *UserSessionMutation) ResetEdge(name string) error { // VersionMutation represents an operation that mutates the Version nodes in the graph. type VersionMutation struct { config - op Op - typ string - id *string - created_at *time.Time - updated_at *time.Time - deleted_at *time.Time - version *string - game_version *string - changelog *string - downloads *uint - adddownloads *int - key *string - stability *util.Stability - approved *bool - hotness *uint - addhotness *int - denied *bool - metadata *string - mod_reference *string - version_major *int - addversion_major *int - version_minor *int - addversion_minor *int - version_patch *int - addversion_patch *int - size *int64 - addsize *int64 - hash *string - clearedFields map[string]struct{} - mod *string - clearedmod bool - dependencies map[string]struct{} - removeddependencies map[string]struct{} - cleareddependencies bool - targets map[string]struct{} - removedtargets map[string]struct{} - clearedtargets bool - done bool - oldValue func(context.Context) (*Version, error) - predicates []predicate.Version + op Op + typ string + id *string + created_at *time.Time + updated_at *time.Time + deleted_at *time.Time + version *string + game_version *string + changelog *string + downloads *uint + adddownloads *int + key *string + stability *util.Stability + approved *bool + hotness *uint + addhotness *int + denied *bool + metadata *string + mod_reference *string + version_major *int + addversion_major *int + version_minor *int + addversion_minor *int + version_patch *int + addversion_patch *int + size *int64 + addsize *int64 + hash *string + clearedFields map[string]struct{} + mod *string + clearedmod bool + dependencies map[string]struct{} + removeddependencies map[string]struct{} + cleareddependencies bool + targets map[string]struct{} + removedtargets map[string]struct{} + clearedtargets bool + virustotal_results map[string]struct{} + removedvirustotal_results map[string]struct{} + clearedvirustotal_results bool + done bool + oldValue func(context.Context) (*Version, error) + predicates []predicate.Version } var _ ent.Mutation = (*VersionMutation)(nil) @@ -9969,6 +9974,60 @@ func (m *VersionMutation) ResetTargets() { m.removedtargets = nil } +// AddVirustotalResultIDs adds the "virustotal_results" edge to the VirustotalResult entity by ids. +func (m *VersionMutation) AddVirustotalResultIDs(ids ...string) { + if m.virustotal_results == nil { + m.virustotal_results = make(map[string]struct{}) + } + for i := range ids { + m.virustotal_results[ids[i]] = struct{}{} + } +} + +// ClearVirustotalResults clears the "virustotal_results" edge to the VirustotalResult entity. +func (m *VersionMutation) ClearVirustotalResults() { + m.clearedvirustotal_results = true +} + +// VirustotalResultsCleared reports if the "virustotal_results" edge to the VirustotalResult entity was cleared. +func (m *VersionMutation) VirustotalResultsCleared() bool { + return m.clearedvirustotal_results +} + +// RemoveVirustotalResultIDs removes the "virustotal_results" edge to the VirustotalResult entity by IDs. +func (m *VersionMutation) RemoveVirustotalResultIDs(ids ...string) { + if m.removedvirustotal_results == nil { + m.removedvirustotal_results = make(map[string]struct{}) + } + for i := range ids { + delete(m.virustotal_results, ids[i]) + m.removedvirustotal_results[ids[i]] = struct{}{} + } +} + +// RemovedVirustotalResults returns the removed IDs of the "virustotal_results" edge to the VirustotalResult entity. +func (m *VersionMutation) RemovedVirustotalResultsIDs() (ids []string) { + for id := range m.removedvirustotal_results { + ids = append(ids, id) + } + return +} + +// VirustotalResultsIDs returns the "virustotal_results" edge IDs in the mutation. +func (m *VersionMutation) VirustotalResultsIDs() (ids []string) { + for id := range m.virustotal_results { + ids = append(ids, id) + } + return +} + +// ResetVirustotalResults resets all changes to the "virustotal_results" edge. +func (m *VersionMutation) ResetVirustotalResults() { + m.virustotal_results = nil + m.clearedvirustotal_results = false + m.removedvirustotal_results = nil +} + // Where appends a list predicates to the VersionMutation builder. func (m *VersionMutation) Where(ps ...predicate.Version) { m.predicates = append(m.predicates, ps...) @@ -10557,7 +10616,7 @@ func (m *VersionMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *VersionMutation) AddedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.mod != nil { edges = append(edges, version.EdgeMod) } @@ -10567,6 +10626,9 @@ func (m *VersionMutation) AddedEdges() []string { if m.targets != nil { edges = append(edges, version.EdgeTargets) } + if m.virustotal_results != nil { + edges = append(edges, version.EdgeVirustotalResults) + } return edges } @@ -10590,19 +10652,28 @@ func (m *VersionMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case version.EdgeVirustotalResults: + ids := make([]ent.Value, 0, len(m.virustotal_results)) + for id := range m.virustotal_results { + ids = append(ids, id) + } + return ids } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *VersionMutation) RemovedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.removeddependencies != nil { edges = append(edges, version.EdgeDependencies) } if m.removedtargets != nil { edges = append(edges, version.EdgeTargets) } + if m.removedvirustotal_results != nil { + edges = append(edges, version.EdgeVirustotalResults) + } return edges } @@ -10622,13 +10693,19 @@ func (m *VersionMutation) RemovedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case version.EdgeVirustotalResults: + ids := make([]ent.Value, 0, len(m.removedvirustotal_results)) + for id := range m.removedvirustotal_results { + ids = append(ids, id) + } + return ids } return nil } // ClearedEdges returns all edge names that were cleared in this mutation. func (m *VersionMutation) ClearedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.clearedmod { edges = append(edges, version.EdgeMod) } @@ -10638,6 +10715,9 @@ func (m *VersionMutation) ClearedEdges() []string { if m.clearedtargets { edges = append(edges, version.EdgeTargets) } + if m.clearedvirustotal_results { + edges = append(edges, version.EdgeVirustotalResults) + } return edges } @@ -10651,6 +10731,8 @@ func (m *VersionMutation) EdgeCleared(name string) bool { return m.cleareddependencies case version.EdgeTargets: return m.clearedtargets + case version.EdgeVirustotalResults: + return m.clearedvirustotal_results } return false } @@ -10679,6 +10761,9 @@ func (m *VersionMutation) ResetEdge(name string) error { case version.EdgeTargets: m.ResetTargets() return nil + case version.EdgeVirustotalResults: + m.ResetVirustotalResults() + return nil } return fmt.Errorf("unknown Version edge %s", name) } @@ -11957,3 +12042,659 @@ func (m *VersionTargetMutation) ResetEdge(name string) error { } return fmt.Errorf("unknown VersionTarget edge %s", name) } + +// VirustotalResultMutation represents an operation that mutates the VirustotalResult nodes in the graph. +type VirustotalResultMutation struct { + config + op Op + typ string + id *string + created_at *time.Time + updated_at *time.Time + safe *bool + hash *string + file_name *string + clearedFields map[string]struct{} + version *string + clearedversion bool + done bool + oldValue func(context.Context) (*VirustotalResult, error) + predicates []predicate.VirustotalResult +} + +var _ ent.Mutation = (*VirustotalResultMutation)(nil) + +// virustotalresultOption allows management of the mutation configuration using functional options. +type virustotalresultOption func(*VirustotalResultMutation) + +// newVirustotalResultMutation creates new mutation for the VirustotalResult entity. +func newVirustotalResultMutation(c config, op Op, opts ...virustotalresultOption) *VirustotalResultMutation { + m := &VirustotalResultMutation{ + config: c, + op: op, + typ: TypeVirustotalResult, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withVirustotalResultID sets the ID field of the mutation. +func withVirustotalResultID(id string) virustotalresultOption { + return func(m *VirustotalResultMutation) { + var ( + err error + once sync.Once + value *VirustotalResult + ) + m.oldValue = func(ctx context.Context) (*VirustotalResult, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().VirustotalResult.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withVirustotalResult sets the old VirustotalResult of the mutation. +func withVirustotalResult(node *VirustotalResult) virustotalresultOption { + return func(m *VirustotalResultMutation) { + m.oldValue = func(context.Context) (*VirustotalResult, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m VirustotalResultMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m VirustotalResultMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of VirustotalResult entities. +func (m *VirustotalResultMutation) SetID(id string) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *VirustotalResultMutation) ID() (id string, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *VirustotalResultMutation) IDs(ctx context.Context) ([]string, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []string{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().VirustotalResult.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *VirustotalResultMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *VirustotalResultMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the VirustotalResult entity. +// If the VirustotalResult object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *VirustotalResultMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *VirustotalResultMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *VirustotalResultMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *VirustotalResultMutation) UpdatedAt() (r time.Time, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the VirustotalResult entity. +// If the VirustotalResult object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *VirustotalResultMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *VirustotalResultMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetSafe sets the "safe" field. +func (m *VirustotalResultMutation) SetSafe(b bool) { + m.safe = &b +} + +// Safe returns the value of the "safe" field in the mutation. +func (m *VirustotalResultMutation) Safe() (r bool, exists bool) { + v := m.safe + if v == nil { + return + } + return *v, true +} + +// OldSafe returns the old "safe" field's value of the VirustotalResult entity. +// If the VirustotalResult object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *VirustotalResultMutation) OldSafe(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSafe is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSafe requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSafe: %w", err) + } + return oldValue.Safe, nil +} + +// ResetSafe resets all changes to the "safe" field. +func (m *VirustotalResultMutation) ResetSafe() { + m.safe = nil +} + +// SetHash sets the "hash" field. +func (m *VirustotalResultMutation) SetHash(s string) { + m.hash = &s +} + +// Hash returns the value of the "hash" field in the mutation. +func (m *VirustotalResultMutation) Hash() (r string, exists bool) { + v := m.hash + if v == nil { + return + } + return *v, true +} + +// OldHash returns the old "hash" field's value of the VirustotalResult entity. +// If the VirustotalResult object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *VirustotalResultMutation) OldHash(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldHash is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldHash requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldHash: %w", err) + } + return oldValue.Hash, nil +} + +// ResetHash resets all changes to the "hash" field. +func (m *VirustotalResultMutation) ResetHash() { + m.hash = nil +} + +// SetFileName sets the "file_name" field. +func (m *VirustotalResultMutation) SetFileName(s string) { + m.file_name = &s +} + +// FileName returns the value of the "file_name" field in the mutation. +func (m *VirustotalResultMutation) FileName() (r string, exists bool) { + v := m.file_name + if v == nil { + return + } + return *v, true +} + +// OldFileName returns the old "file_name" field's value of the VirustotalResult entity. +// If the VirustotalResult object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *VirustotalResultMutation) OldFileName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldFileName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldFileName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldFileName: %w", err) + } + return oldValue.FileName, nil +} + +// ResetFileName resets all changes to the "file_name" field. +func (m *VirustotalResultMutation) ResetFileName() { + m.file_name = nil +} + +// SetVersionID sets the "version_id" field. +func (m *VirustotalResultMutation) SetVersionID(s string) { + m.version = &s +} + +// VersionID returns the value of the "version_id" field in the mutation. +func (m *VirustotalResultMutation) VersionID() (r string, exists bool) { + v := m.version + if v == nil { + return + } + return *v, true +} + +// OldVersionID returns the old "version_id" field's value of the VirustotalResult entity. +// If the VirustotalResult object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *VirustotalResultMutation) OldVersionID(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldVersionID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldVersionID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldVersionID: %w", err) + } + return oldValue.VersionID, nil +} + +// ResetVersionID resets all changes to the "version_id" field. +func (m *VirustotalResultMutation) ResetVersionID() { + m.version = nil +} + +// ClearVersion clears the "version" edge to the Version entity. +func (m *VirustotalResultMutation) ClearVersion() { + m.clearedversion = true + m.clearedFields[virustotalresult.FieldVersionID] = struct{}{} +} + +// VersionCleared reports if the "version" edge to the Version entity was cleared. +func (m *VirustotalResultMutation) VersionCleared() bool { + return m.clearedversion +} + +// VersionIDs returns the "version" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// VersionID instead. It exists only for internal usage by the builders. +func (m *VirustotalResultMutation) VersionIDs() (ids []string) { + if id := m.version; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetVersion resets all changes to the "version" edge. +func (m *VirustotalResultMutation) ResetVersion() { + m.version = nil + m.clearedversion = false +} + +// Where appends a list predicates to the VirustotalResultMutation builder. +func (m *VirustotalResultMutation) Where(ps ...predicate.VirustotalResult) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the VirustotalResultMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *VirustotalResultMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.VirustotalResult, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *VirustotalResultMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *VirustotalResultMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (VirustotalResult). +func (m *VirustotalResultMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *VirustotalResultMutation) Fields() []string { + fields := make([]string, 0, 6) + if m.created_at != nil { + fields = append(fields, virustotalresult.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, virustotalresult.FieldUpdatedAt) + } + if m.safe != nil { + fields = append(fields, virustotalresult.FieldSafe) + } + if m.hash != nil { + fields = append(fields, virustotalresult.FieldHash) + } + if m.file_name != nil { + fields = append(fields, virustotalresult.FieldFileName) + } + if m.version != nil { + fields = append(fields, virustotalresult.FieldVersionID) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *VirustotalResultMutation) Field(name string) (ent.Value, bool) { + switch name { + case virustotalresult.FieldCreatedAt: + return m.CreatedAt() + case virustotalresult.FieldUpdatedAt: + return m.UpdatedAt() + case virustotalresult.FieldSafe: + return m.Safe() + case virustotalresult.FieldHash: + return m.Hash() + case virustotalresult.FieldFileName: + return m.FileName() + case virustotalresult.FieldVersionID: + return m.VersionID() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *VirustotalResultMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case virustotalresult.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case virustotalresult.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case virustotalresult.FieldSafe: + return m.OldSafe(ctx) + case virustotalresult.FieldHash: + return m.OldHash(ctx) + case virustotalresult.FieldFileName: + return m.OldFileName(ctx) + case virustotalresult.FieldVersionID: + return m.OldVersionID(ctx) + } + return nil, fmt.Errorf("unknown VirustotalResult field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *VirustotalResultMutation) SetField(name string, value ent.Value) error { + switch name { + case virustotalresult.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case virustotalresult.FieldUpdatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case virustotalresult.FieldSafe: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSafe(v) + return nil + case virustotalresult.FieldHash: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetHash(v) + return nil + case virustotalresult.FieldFileName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetFileName(v) + return nil + case virustotalresult.FieldVersionID: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetVersionID(v) + return nil + } + return fmt.Errorf("unknown VirustotalResult field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *VirustotalResultMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *VirustotalResultMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *VirustotalResultMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown VirustotalResult numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *VirustotalResultMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *VirustotalResultMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *VirustotalResultMutation) ClearField(name string) error { + return fmt.Errorf("unknown VirustotalResult nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *VirustotalResultMutation) ResetField(name string) error { + switch name { + case virustotalresult.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case virustotalresult.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case virustotalresult.FieldSafe: + m.ResetSafe() + return nil + case virustotalresult.FieldHash: + m.ResetHash() + return nil + case virustotalresult.FieldFileName: + m.ResetFileName() + return nil + case virustotalresult.FieldVersionID: + m.ResetVersionID() + return nil + } + return fmt.Errorf("unknown VirustotalResult field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *VirustotalResultMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.version != nil { + edges = append(edges, virustotalresult.EdgeVersion) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *VirustotalResultMutation) AddedIDs(name string) []ent.Value { + switch name { + case virustotalresult.EdgeVersion: + if id := m.version; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *VirustotalResultMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *VirustotalResultMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *VirustotalResultMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedversion { + edges = append(edges, virustotalresult.EdgeVersion) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *VirustotalResultMutation) EdgeCleared(name string) bool { + switch name { + case virustotalresult.EdgeVersion: + return m.clearedversion + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *VirustotalResultMutation) ClearEdge(name string) error { + switch name { + case virustotalresult.EdgeVersion: + m.ClearVersion() + return nil + } + return fmt.Errorf("unknown VirustotalResult unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *VirustotalResultMutation) ResetEdge(name string) error { + switch name { + case virustotalresult.EdgeVersion: + m.ResetVersion() + return nil + } + return fmt.Errorf("unknown VirustotalResult edge %s", name) +} diff --git a/generated/ent/predicate/predicate.go b/generated/ent/predicate/predicate.go index 788d43e8..4992ae4e 100644 --- a/generated/ent/predicate/predicate.go +++ b/generated/ent/predicate/predicate.go @@ -47,3 +47,6 @@ type VersionDependency func(*sql.Selector) // VersionTarget is the predicate function for versiontarget builders. type VersionTarget func(*sql.Selector) + +// VirustotalResult is the predicate function for virustotalresult builders. +type VirustotalResult func(*sql.Selector) diff --git a/generated/ent/runtime/runtime.go b/generated/ent/runtime/runtime.go index 69ec1572..6b90a806 100644 --- a/generated/ent/runtime/runtime.go +++ b/generated/ent/runtime/runtime.go @@ -17,6 +17,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiondependency" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" ) // The init function reads all schema descriptors with runtime code @@ -420,6 +421,43 @@ func init() { versiontargetDescID := versiontargetMixinFields0[0].Descriptor() // versiontarget.DefaultID holds the default value on creation for the id field. versiontarget.DefaultID = versiontargetDescID.Default.(func() string) + virustotalresultMixin := schema.VirustotalResult{}.Mixin() + virustotalresultMixinFields0 := virustotalresultMixin[0].Fields() + _ = virustotalresultMixinFields0 + virustotalresultMixinFields1 := virustotalresultMixin[1].Fields() + _ = virustotalresultMixinFields1 + virustotalresultFields := schema.VirustotalResult{}.Fields() + _ = virustotalresultFields + // virustotalresultDescCreatedAt is the schema descriptor for created_at field. + virustotalresultDescCreatedAt := virustotalresultMixinFields1[0].Descriptor() + // virustotalresult.DefaultCreatedAt holds the default value on creation for the created_at field. + virustotalresult.DefaultCreatedAt = virustotalresultDescCreatedAt.Default.(func() time.Time) + // virustotalresultDescUpdatedAt is the schema descriptor for updated_at field. + virustotalresultDescUpdatedAt := virustotalresultMixinFields1[1].Descriptor() + // virustotalresult.DefaultUpdatedAt holds the default value on creation for the updated_at field. + virustotalresult.DefaultUpdatedAt = virustotalresultDescUpdatedAt.Default.(func() time.Time) + // virustotalresult.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + virustotalresult.UpdateDefaultUpdatedAt = virustotalresultDescUpdatedAt.UpdateDefault.(func() time.Time) + // virustotalresultDescSafe is the schema descriptor for safe field. + virustotalresultDescSafe := virustotalresultFields[0].Descriptor() + // virustotalresult.DefaultSafe holds the default value on creation for the safe field. + virustotalresult.DefaultSafe = virustotalresultDescSafe.Default.(bool) + // virustotalresultDescHash is the schema descriptor for hash field. + virustotalresultDescHash := virustotalresultFields[1].Descriptor() + // virustotalresult.HashValidator is a validator for the "hash" field. It is called by the builders before save. + virustotalresult.HashValidator = virustotalresultDescHash.Validators[0].(func(string) error) + // virustotalresultDescFileName is the schema descriptor for file_name field. + virustotalresultDescFileName := virustotalresultFields[2].Descriptor() + // virustotalresult.FileNameValidator is a validator for the "file_name" field. It is called by the builders before save. + virustotalresult.FileNameValidator = virustotalresultDescFileName.Validators[0].(func(string) error) + // virustotalresultDescVersionID is the schema descriptor for version_id field. + virustotalresultDescVersionID := virustotalresultFields[3].Descriptor() + // virustotalresult.VersionIDValidator is a validator for the "version_id" field. It is called by the builders before save. + virustotalresult.VersionIDValidator = virustotalresultDescVersionID.Validators[0].(func(string) error) + // virustotalresultDescID is the schema descriptor for id field. + virustotalresultDescID := virustotalresultMixinFields0[0].Descriptor() + // virustotalresult.DefaultID holds the default value on creation for the id field. + virustotalresult.DefaultID = virustotalresultDescID.Default.(func() string) } const ( diff --git a/generated/ent/tx.go b/generated/ent/tx.go index 0d68cfe7..4bf737e2 100644 --- a/generated/ent/tx.go +++ b/generated/ent/tx.go @@ -42,6 +42,8 @@ type Tx struct { VersionDependency *VersionDependencyClient // VersionTarget is the client for interacting with the VersionTarget builders. VersionTarget *VersionTargetClient + // VirustotalResult is the client for interacting with the VirustotalResult builders. + VirustotalResult *VirustotalResultClient // lazily loaded. client *Client @@ -187,6 +189,7 @@ func (tx *Tx) init() { tx.Version = NewVersionClient(tx.config) tx.VersionDependency = NewVersionDependencyClient(tx.config) tx.VersionTarget = NewVersionTargetClient(tx.config) + tx.VirustotalResult = NewVirustotalResultClient(tx.config) } // txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation. diff --git a/generated/ent/version.go b/generated/ent/version.go index 1418fd32..db808cac 100644 --- a/generated/ent/version.go +++ b/generated/ent/version.go @@ -73,11 +73,13 @@ type VersionEdges struct { Dependencies []*Mod `json:"dependencies,omitempty"` // Targets holds the value of the targets edge. Targets []*VersionTarget `json:"targets,omitempty"` + // VirustotalResults holds the value of the virustotal_results edge. + VirustotalResults []*VirustotalResult `json:"virustotal_results,omitempty"` // VersionDependencies holds the value of the version_dependencies edge. VersionDependencies []*VersionDependency `json:"version_dependencies,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [4]bool + loadedTypes [5]bool } // ModOrErr returns the Mod value or an error if the edge @@ -109,10 +111,19 @@ func (e VersionEdges) TargetsOrErr() ([]*VersionTarget, error) { return nil, &NotLoadedError{edge: "targets"} } +// VirustotalResultsOrErr returns the VirustotalResults value or an error if the edge +// was not loaded in eager-loading. +func (e VersionEdges) VirustotalResultsOrErr() ([]*VirustotalResult, error) { + if e.loadedTypes[3] { + return e.VirustotalResults, nil + } + return nil, &NotLoadedError{edge: "virustotal_results"} +} + // VersionDependenciesOrErr returns the VersionDependencies value or an error if the edge // was not loaded in eager-loading. func (e VersionEdges) VersionDependenciesOrErr() ([]*VersionDependency, error) { - if e.loadedTypes[3] { + if e.loadedTypes[4] { return e.VersionDependencies, nil } return nil, &NotLoadedError{edge: "version_dependencies"} @@ -300,6 +311,11 @@ func (v *Version) QueryTargets() *VersionTargetQuery { return NewVersionClient(v.config).QueryTargets(v) } +// QueryVirustotalResults queries the "virustotal_results" edge of the Version entity. +func (v *Version) QueryVirustotalResults() *VirustotalResultQuery { + return NewVersionClient(v.config).QueryVirustotalResults(v) +} + // QueryVersionDependencies queries the "version_dependencies" edge of the Version entity. func (v *Version) QueryVersionDependencies() *VersionDependencyQuery { return NewVersionClient(v.config).QueryVersionDependencies(v) diff --git a/generated/ent/version/version.go b/generated/ent/version/version.go index 87384bcf..c32a2166 100644 --- a/generated/ent/version/version.go +++ b/generated/ent/version/version.go @@ -63,6 +63,8 @@ const ( EdgeDependencies = "dependencies" // EdgeTargets holds the string denoting the targets edge name in mutations. EdgeTargets = "targets" + // EdgeVirustotalResults holds the string denoting the virustotal_results edge name in mutations. + EdgeVirustotalResults = "virustotal_results" // EdgeVersionDependencies holds the string denoting the version_dependencies edge name in mutations. EdgeVersionDependencies = "version_dependencies" // Table holds the table name of the version in the database. @@ -86,6 +88,13 @@ const ( TargetsInverseTable = "version_targets" // TargetsColumn is the table column denoting the targets relation/edge. TargetsColumn = "version_id" + // VirustotalResultsTable is the table that holds the virustotal_results relation/edge. + VirustotalResultsTable = "virustotal_results" + // VirustotalResultsInverseTable is the table name for the VirustotalResult entity. + // It exists in this package in order to avoid circular dependency with the "virustotalresult" package. + VirustotalResultsInverseTable = "virustotal_results" + // VirustotalResultsColumn is the table column denoting the virustotal_results relation/edge. + VirustotalResultsColumn = "version_id" // VersionDependenciesTable is the table that holds the version_dependencies relation/edge. VersionDependenciesTable = "version_dependencies" // VersionDependenciesInverseTable is the table name for the VersionDependency entity. @@ -323,6 +332,20 @@ func ByTargets(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { } } +// ByVirustotalResultsCount orders the results by virustotal_results count. +func ByVirustotalResultsCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newVirustotalResultsStep(), opts...) + } +} + +// ByVirustotalResults orders the results by virustotal_results terms. +func ByVirustotalResults(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newVirustotalResultsStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} + // ByVersionDependenciesCount orders the results by version_dependencies count. func ByVersionDependenciesCount(opts ...sql.OrderTermOption) OrderOption { return func(s *sql.Selector) { @@ -357,6 +380,13 @@ func newTargetsStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, false, TargetsTable, TargetsColumn), ) } +func newVirustotalResultsStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(VirustotalResultsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, VirustotalResultsTable, VirustotalResultsColumn), + ) +} func newVersionDependenciesStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), diff --git a/generated/ent/version/where.go b/generated/ent/version/where.go index c6fb9945..2f4b8076 100644 --- a/generated/ent/version/where.go +++ b/generated/ent/version/where.go @@ -1250,6 +1250,29 @@ func HasTargetsWith(preds ...predicate.VersionTarget) predicate.Version { }) } +// HasVirustotalResults applies the HasEdge predicate on the "virustotal_results" edge. +func HasVirustotalResults() predicate.Version { + return predicate.Version(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, VirustotalResultsTable, VirustotalResultsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasVirustotalResultsWith applies the HasEdge predicate on the "virustotal_results" edge with a given conditions (other predicates). +func HasVirustotalResultsWith(preds ...predicate.VirustotalResult) predicate.Version { + return predicate.Version(func(s *sql.Selector) { + step := newVirustotalResultsStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // HasVersionDependencies applies the HasEdge predicate on the "version_dependencies" edge. func HasVersionDependencies() predicate.Version { return predicate.Version(func(s *sql.Selector) { diff --git a/generated/ent/version_create.go b/generated/ent/version_create.go index efc1abeb..9f83447a 100644 --- a/generated/ent/version_create.go +++ b/generated/ent/version_create.go @@ -15,6 +15,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/mod" "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" "github.com/satisfactorymodding/smr-api/util" ) @@ -323,6 +324,21 @@ func (vc *VersionCreate) AddTargets(v ...*VersionTarget) *VersionCreate { return vc.AddTargetIDs(ids...) } +// AddVirustotalResultIDs adds the "virustotal_results" edge to the VirustotalResult entity by IDs. +func (vc *VersionCreate) AddVirustotalResultIDs(ids ...string) *VersionCreate { + vc.mutation.AddVirustotalResultIDs(ids...) + return vc +} + +// AddVirustotalResults adds the "virustotal_results" edges to the VirustotalResult entity. +func (vc *VersionCreate) AddVirustotalResults(v ...*VirustotalResult) *VersionCreate { + ids := make([]string, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return vc.AddVirustotalResultIDs(ids...) +} + // Mutation returns the VersionMutation object of the builder. func (vc *VersionCreate) Mutation() *VersionMutation { return vc.mutation @@ -627,6 +643,22 @@ func (vc *VersionCreate) createSpec() (*Version, *sqlgraph.CreateSpec) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := vc.mutation.VirustotalResultsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: version.VirustotalResultsTable, + Columns: []string{version.VirustotalResultsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/generated/ent/version_query.go b/generated/ent/version_query.go index cc9dadcb..993a6677 100644 --- a/generated/ent/version_query.go +++ b/generated/ent/version_query.go @@ -17,6 +17,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiondependency" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" ) // VersionQuery is the builder for querying Version entities. @@ -29,6 +30,7 @@ type VersionQuery struct { withMod *ModQuery withDependencies *ModQuery withTargets *VersionTargetQuery + withVirustotalResults *VirustotalResultQuery withVersionDependencies *VersionDependencyQuery modifiers []func(*sql.Selector) // intermediate query (i.e. traversal path). @@ -133,6 +135,28 @@ func (vq *VersionQuery) QueryTargets() *VersionTargetQuery { return query } +// QueryVirustotalResults chains the current query on the "virustotal_results" edge. +func (vq *VersionQuery) QueryVirustotalResults() *VirustotalResultQuery { + query := (&VirustotalResultClient{config: vq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := vq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := vq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(version.Table, version.FieldID, selector), + sqlgraph.To(virustotalresult.Table, virustotalresult.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, version.VirustotalResultsTable, version.VirustotalResultsColumn), + ) + fromU = sqlgraph.SetNeighbors(vq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // QueryVersionDependencies chains the current query on the "version_dependencies" edge. func (vq *VersionQuery) QueryVersionDependencies() *VersionDependencyQuery { query := (&VersionDependencyClient{config: vq.config}).Query() @@ -350,6 +374,7 @@ func (vq *VersionQuery) Clone() *VersionQuery { withMod: vq.withMod.Clone(), withDependencies: vq.withDependencies.Clone(), withTargets: vq.withTargets.Clone(), + withVirustotalResults: vq.withVirustotalResults.Clone(), withVersionDependencies: vq.withVersionDependencies.Clone(), // clone intermediate query. sql: vq.sql.Clone(), @@ -390,6 +415,17 @@ func (vq *VersionQuery) WithTargets(opts ...func(*VersionTargetQuery)) *VersionQ return vq } +// WithVirustotalResults tells the query-builder to eager-load the nodes that are connected to +// the "virustotal_results" edge. The optional arguments are used to configure the query builder of the edge. +func (vq *VersionQuery) WithVirustotalResults(opts ...func(*VirustotalResultQuery)) *VersionQuery { + query := (&VirustotalResultClient{config: vq.config}).Query() + for _, opt := range opts { + opt(query) + } + vq.withVirustotalResults = query + return vq +} + // WithVersionDependencies tells the query-builder to eager-load the nodes that are connected to // the "version_dependencies" edge. The optional arguments are used to configure the query builder of the edge. func (vq *VersionQuery) WithVersionDependencies(opts ...func(*VersionDependencyQuery)) *VersionQuery { @@ -479,10 +515,11 @@ func (vq *VersionQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Vers var ( nodes = []*Version{} _spec = vq.querySpec() - loadedTypes = [4]bool{ + loadedTypes = [5]bool{ vq.withMod != nil, vq.withDependencies != nil, vq.withTargets != nil, + vq.withVirustotalResults != nil, vq.withVersionDependencies != nil, } ) @@ -527,6 +564,15 @@ func (vq *VersionQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Vers return nil, err } } + if query := vq.withVirustotalResults; query != nil { + if err := vq.loadVirustotalResults(ctx, query, nodes, + func(n *Version) { n.Edges.VirustotalResults = []*VirustotalResult{} }, + func(n *Version, e *VirustotalResult) { + n.Edges.VirustotalResults = append(n.Edges.VirustotalResults, e) + }); err != nil { + return nil, err + } + } if query := vq.withVersionDependencies; query != nil { if err := vq.loadVersionDependencies(ctx, query, nodes, func(n *Version) { n.Edges.VersionDependencies = []*VersionDependency{} }, @@ -659,6 +705,36 @@ func (vq *VersionQuery) loadTargets(ctx context.Context, query *VersionTargetQue } return nil } +func (vq *VersionQuery) loadVirustotalResults(ctx context.Context, query *VirustotalResultQuery, nodes []*Version, init func(*Version), assign func(*Version, *VirustotalResult)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[string]*Version) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(virustotalresult.FieldVersionID) + } + query.Where(predicate.VirustotalResult(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(version.VirustotalResultsColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.VersionID + node, ok := nodeids[fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "version_id" returned %v for node %v`, fk, n.ID) + } + assign(node, n) + } + return nil +} func (vq *VersionQuery) loadVersionDependencies(ctx context.Context, query *VersionDependencyQuery, nodes []*Version, init func(*Version), assign func(*Version, *VersionDependency)) error { fks := make([]driver.Value, 0, len(nodes)) nodeids := make(map[string]*Version) diff --git a/generated/ent/version_update.go b/generated/ent/version_update.go index 0cbd1e9d..0dd76ef3 100644 --- a/generated/ent/version_update.go +++ b/generated/ent/version_update.go @@ -15,6 +15,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/ent/predicate" "github.com/satisfactorymodding/smr-api/generated/ent/version" "github.com/satisfactorymodding/smr-api/generated/ent/versiontarget" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" "github.com/satisfactorymodding/smr-api/util" ) @@ -421,6 +422,21 @@ func (vu *VersionUpdate) AddTargets(v ...*VersionTarget) *VersionUpdate { return vu.AddTargetIDs(ids...) } +// AddVirustotalResultIDs adds the "virustotal_results" edge to the VirustotalResult entity by IDs. +func (vu *VersionUpdate) AddVirustotalResultIDs(ids ...string) *VersionUpdate { + vu.mutation.AddVirustotalResultIDs(ids...) + return vu +} + +// AddVirustotalResults adds the "virustotal_results" edges to the VirustotalResult entity. +func (vu *VersionUpdate) AddVirustotalResults(v ...*VirustotalResult) *VersionUpdate { + ids := make([]string, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return vu.AddVirustotalResultIDs(ids...) +} + // Mutation returns the VersionMutation object of the builder. func (vu *VersionUpdate) Mutation() *VersionMutation { return vu.mutation @@ -474,6 +490,27 @@ func (vu *VersionUpdate) RemoveTargets(v ...*VersionTarget) *VersionUpdate { return vu.RemoveTargetIDs(ids...) } +// ClearVirustotalResults clears all "virustotal_results" edges to the VirustotalResult entity. +func (vu *VersionUpdate) ClearVirustotalResults() *VersionUpdate { + vu.mutation.ClearVirustotalResults() + return vu +} + +// RemoveVirustotalResultIDs removes the "virustotal_results" edge to VirustotalResult entities by IDs. +func (vu *VersionUpdate) RemoveVirustotalResultIDs(ids ...string) *VersionUpdate { + vu.mutation.RemoveVirustotalResultIDs(ids...) + return vu +} + +// RemoveVirustotalResults removes "virustotal_results" edges to VirustotalResult entities. +func (vu *VersionUpdate) RemoveVirustotalResults(v ...*VirustotalResult) *VersionUpdate { + ids := make([]string, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return vu.RemoveVirustotalResultIDs(ids...) +} + // Save executes the query and returns the number of nodes affected by the update operation. func (vu *VersionUpdate) Save(ctx context.Context) (int, error) { if err := vu.defaults(); err != nil { @@ -792,6 +829,51 @@ func (vu *VersionUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if vu.mutation.VirustotalResultsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: version.VirustotalResultsTable, + Columns: []string{version.VirustotalResultsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := vu.mutation.RemovedVirustotalResultsIDs(); len(nodes) > 0 && !vu.mutation.VirustotalResultsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: version.VirustotalResultsTable, + Columns: []string{version.VirustotalResultsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := vu.mutation.VirustotalResultsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: version.VirustotalResultsTable, + Columns: []string{version.VirustotalResultsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _spec.AddModifiers(vu.modifiers...) if n, err = sqlgraph.UpdateNodes(ctx, vu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { @@ -1203,6 +1285,21 @@ func (vuo *VersionUpdateOne) AddTargets(v ...*VersionTarget) *VersionUpdateOne { return vuo.AddTargetIDs(ids...) } +// AddVirustotalResultIDs adds the "virustotal_results" edge to the VirustotalResult entity by IDs. +func (vuo *VersionUpdateOne) AddVirustotalResultIDs(ids ...string) *VersionUpdateOne { + vuo.mutation.AddVirustotalResultIDs(ids...) + return vuo +} + +// AddVirustotalResults adds the "virustotal_results" edges to the VirustotalResult entity. +func (vuo *VersionUpdateOne) AddVirustotalResults(v ...*VirustotalResult) *VersionUpdateOne { + ids := make([]string, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return vuo.AddVirustotalResultIDs(ids...) +} + // Mutation returns the VersionMutation object of the builder. func (vuo *VersionUpdateOne) Mutation() *VersionMutation { return vuo.mutation @@ -1256,6 +1353,27 @@ func (vuo *VersionUpdateOne) RemoveTargets(v ...*VersionTarget) *VersionUpdateOn return vuo.RemoveTargetIDs(ids...) } +// ClearVirustotalResults clears all "virustotal_results" edges to the VirustotalResult entity. +func (vuo *VersionUpdateOne) ClearVirustotalResults() *VersionUpdateOne { + vuo.mutation.ClearVirustotalResults() + return vuo +} + +// RemoveVirustotalResultIDs removes the "virustotal_results" edge to VirustotalResult entities by IDs. +func (vuo *VersionUpdateOne) RemoveVirustotalResultIDs(ids ...string) *VersionUpdateOne { + vuo.mutation.RemoveVirustotalResultIDs(ids...) + return vuo +} + +// RemoveVirustotalResults removes "virustotal_results" edges to VirustotalResult entities. +func (vuo *VersionUpdateOne) RemoveVirustotalResults(v ...*VirustotalResult) *VersionUpdateOne { + ids := make([]string, len(v)) + for i := range v { + ids[i] = v[i].ID + } + return vuo.RemoveVirustotalResultIDs(ids...) +} + // Where appends a list predicates to the VersionUpdate builder. func (vuo *VersionUpdateOne) Where(ps ...predicate.Version) *VersionUpdateOne { vuo.mutation.Where(ps...) @@ -1604,6 +1722,51 @@ func (vuo *VersionUpdateOne) sqlSave(ctx context.Context) (_node *Version, err e } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if vuo.mutation.VirustotalResultsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: version.VirustotalResultsTable, + Columns: []string{version.VirustotalResultsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := vuo.mutation.RemovedVirustotalResultsIDs(); len(nodes) > 0 && !vuo.mutation.VirustotalResultsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: version.VirustotalResultsTable, + Columns: []string{version.VirustotalResultsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := vuo.mutation.VirustotalResultsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: version.VirustotalResultsTable, + Columns: []string{version.VirustotalResultsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _spec.AddModifiers(vuo.modifiers...) _node = &Version{config: vuo.config} _spec.Assign = _node.assignValues diff --git a/generated/ent/virustotalresult.go b/generated/ent/virustotalresult.go new file mode 100644 index 00000000..92d084ac --- /dev/null +++ b/generated/ent/virustotalresult.go @@ -0,0 +1,190 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/satisfactorymodding/smr-api/generated/ent/version" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" +) + +// VirustotalResult is the model entity for the VirustotalResult schema. +type VirustotalResult struct { + config `json:"-"` + // ID of the ent. + ID string `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt time.Time `json:"updated_at,omitempty"` + // Safe holds the value of the "safe" field. + Safe bool `json:"safe,omitempty"` + // Hash holds the value of the "hash" field. + Hash string `json:"hash,omitempty"` + // FileName holds the value of the "file_name" field. + FileName string `json:"file_name,omitempty"` + // VersionID holds the value of the "version_id" field. + VersionID string `json:"version_id,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the VirustotalResultQuery when eager-loading is set. + Edges VirustotalResultEdges `json:"edges"` + selectValues sql.SelectValues +} + +// VirustotalResultEdges holds the relations/edges for other nodes in the graph. +type VirustotalResultEdges struct { + // Version holds the value of the version edge. + Version *Version `json:"version,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// VersionOrErr returns the Version value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e VirustotalResultEdges) VersionOrErr() (*Version, error) { + if e.Version != nil { + return e.Version, nil + } else if e.loadedTypes[0] { + return nil, &NotFoundError{label: version.Label} + } + return nil, &NotLoadedError{edge: "version"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*VirustotalResult) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case virustotalresult.FieldSafe: + values[i] = new(sql.NullBool) + case virustotalresult.FieldID, virustotalresult.FieldHash, virustotalresult.FieldFileName, virustotalresult.FieldVersionID: + values[i] = new(sql.NullString) + case virustotalresult.FieldCreatedAt, virustotalresult.FieldUpdatedAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the VirustotalResult fields. +func (vr *VirustotalResult) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case virustotalresult.FieldID: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field id", values[i]) + } else if value.Valid { + vr.ID = value.String + } + case virustotalresult.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + vr.CreatedAt = value.Time + } + case virustotalresult.FieldUpdatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value.Valid { + vr.UpdatedAt = value.Time + } + case virustotalresult.FieldSafe: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field safe", values[i]) + } else if value.Valid { + vr.Safe = value.Bool + } + case virustotalresult.FieldHash: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field hash", values[i]) + } else if value.Valid { + vr.Hash = value.String + } + case virustotalresult.FieldFileName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field file_name", values[i]) + } else if value.Valid { + vr.FileName = value.String + } + case virustotalresult.FieldVersionID: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field version_id", values[i]) + } else if value.Valid { + vr.VersionID = value.String + } + default: + vr.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the VirustotalResult. +// This includes values selected through modifiers, order, etc. +func (vr *VirustotalResult) Value(name string) (ent.Value, error) { + return vr.selectValues.Get(name) +} + +// QueryVersion queries the "version" edge of the VirustotalResult entity. +func (vr *VirustotalResult) QueryVersion() *VersionQuery { + return NewVirustotalResultClient(vr.config).QueryVersion(vr) +} + +// Update returns a builder for updating this VirustotalResult. +// Note that you need to call VirustotalResult.Unwrap() before calling this method if this VirustotalResult +// was returned from a transaction, and the transaction was committed or rolled back. +func (vr *VirustotalResult) Update() *VirustotalResultUpdateOne { + return NewVirustotalResultClient(vr.config).UpdateOne(vr) +} + +// Unwrap unwraps the VirustotalResult entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (vr *VirustotalResult) Unwrap() *VirustotalResult { + _tx, ok := vr.config.driver.(*txDriver) + if !ok { + panic("ent: VirustotalResult is not a transactional entity") + } + vr.config.driver = _tx.drv + return vr +} + +// String implements the fmt.Stringer. +func (vr *VirustotalResult) String() string { + var builder strings.Builder + builder.WriteString("VirustotalResult(") + builder.WriteString(fmt.Sprintf("id=%v, ", vr.ID)) + builder.WriteString("created_at=") + builder.WriteString(vr.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(vr.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("safe=") + builder.WriteString(fmt.Sprintf("%v", vr.Safe)) + builder.WriteString(", ") + builder.WriteString("hash=") + builder.WriteString(vr.Hash) + builder.WriteString(", ") + builder.WriteString("file_name=") + builder.WriteString(vr.FileName) + builder.WriteString(", ") + builder.WriteString("version_id=") + builder.WriteString(vr.VersionID) + builder.WriteByte(')') + return builder.String() +} + +// VirustotalResults is a parsable slice of VirustotalResult. +type VirustotalResults []*VirustotalResult diff --git a/generated/ent/virustotalresult/virustotalresult.go b/generated/ent/virustotalresult/virustotalresult.go new file mode 100644 index 00000000..a7c27e73 --- /dev/null +++ b/generated/ent/virustotalresult/virustotalresult.go @@ -0,0 +1,132 @@ +// Code generated by ent, DO NOT EDIT. + +package virustotalresult + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the virustotalresult type in the database. + Label = "virustotal_result" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldSafe holds the string denoting the safe field in the database. + FieldSafe = "safe" + // FieldHash holds the string denoting the hash field in the database. + FieldHash = "hash" + // FieldFileName holds the string denoting the file_name field in the database. + FieldFileName = "file_name" + // FieldVersionID holds the string denoting the version_id field in the database. + FieldVersionID = "version_id" + // EdgeVersion holds the string denoting the version edge name in mutations. + EdgeVersion = "version" + // Table holds the table name of the virustotalresult in the database. + Table = "virustotal_results" + // VersionTable is the table that holds the version relation/edge. + VersionTable = "virustotal_results" + // VersionInverseTable is the table name for the Version entity. + // It exists in this package in order to avoid circular dependency with the "version" package. + VersionInverseTable = "versions" + // VersionColumn is the table column denoting the version relation/edge. + VersionColumn = "version_id" +) + +// Columns holds all SQL columns for virustotalresult fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldSafe, + FieldHash, + FieldFileName, + FieldVersionID, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() time.Time + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() time.Time + // DefaultSafe holds the default value on creation for the "safe" field. + DefaultSafe bool + // HashValidator is a validator for the "hash" field. It is called by the builders before save. + HashValidator func(string) error + // FileNameValidator is a validator for the "file_name" field. It is called by the builders before save. + FileNameValidator func(string) error + // VersionIDValidator is a validator for the "version_id" field. It is called by the builders before save. + VersionIDValidator func(string) error + // DefaultID holds the default value on creation for the "id" field. + DefaultID func() string +) + +// OrderOption defines the ordering options for the VirustotalResult queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// BySafe orders the results by the safe field. +func BySafe(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldSafe, opts...).ToFunc() +} + +// ByHash orders the results by the hash field. +func ByHash(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldHash, opts...).ToFunc() +} + +// ByFileName orders the results by the file_name field. +func ByFileName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldFileName, opts...).ToFunc() +} + +// ByVersionID orders the results by the version_id field. +func ByVersionID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldVersionID, opts...).ToFunc() +} + +// ByVersionField orders the results by version field. +func ByVersionField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newVersionStep(), sql.OrderByField(field, opts...)) + } +} +func newVersionStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(VersionInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, VersionTable, VersionColumn), + ) +} diff --git a/generated/ent/virustotalresult/where.go b/generated/ent/virustotalresult/where.go new file mode 100644 index 00000000..435f1132 --- /dev/null +++ b/generated/ent/virustotalresult/where.go @@ -0,0 +1,419 @@ +// Code generated by ent, DO NOT EDIT. + +package virustotalresult + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/satisfactorymodding/smr-api/generated/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLTE(FieldID, id)) +} + +// IDEqualFold applies the EqualFold predicate on the ID field. +func IDEqualFold(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEqualFold(FieldID, id)) +} + +// IDContainsFold applies the ContainsFold predicate on the ID field. +func IDContainsFold(id string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldContainsFold(FieldID, id)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldCreatedAt, v)) +} + +// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ. +func UpdatedAt(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// Safe applies equality check predicate on the "safe" field. It's identical to SafeEQ. +func Safe(v bool) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldSafe, v)) +} + +// Hash applies equality check predicate on the "hash" field. It's identical to HashEQ. +func Hash(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldHash, v)) +} + +// FileName applies equality check predicate on the "file_name" field. It's identical to FileNameEQ. +func FileName(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldFileName, v)) +} + +// VersionID applies equality check predicate on the "version_id" field. It's identical to VersionIDEQ. +func VersionID(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldVersionID, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// SafeEQ applies the EQ predicate on the "safe" field. +func SafeEQ(v bool) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldSafe, v)) +} + +// SafeNEQ applies the NEQ predicate on the "safe" field. +func SafeNEQ(v bool) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNEQ(FieldSafe, v)) +} + +// HashEQ applies the EQ predicate on the "hash" field. +func HashEQ(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldHash, v)) +} + +// HashNEQ applies the NEQ predicate on the "hash" field. +func HashNEQ(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNEQ(FieldHash, v)) +} + +// HashIn applies the In predicate on the "hash" field. +func HashIn(vs ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldIn(FieldHash, vs...)) +} + +// HashNotIn applies the NotIn predicate on the "hash" field. +func HashNotIn(vs ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNotIn(FieldHash, vs...)) +} + +// HashGT applies the GT predicate on the "hash" field. +func HashGT(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGT(FieldHash, v)) +} + +// HashGTE applies the GTE predicate on the "hash" field. +func HashGTE(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGTE(FieldHash, v)) +} + +// HashLT applies the LT predicate on the "hash" field. +func HashLT(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLT(FieldHash, v)) +} + +// HashLTE applies the LTE predicate on the "hash" field. +func HashLTE(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLTE(FieldHash, v)) +} + +// HashContains applies the Contains predicate on the "hash" field. +func HashContains(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldContains(FieldHash, v)) +} + +// HashHasPrefix applies the HasPrefix predicate on the "hash" field. +func HashHasPrefix(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldHasPrefix(FieldHash, v)) +} + +// HashHasSuffix applies the HasSuffix predicate on the "hash" field. +func HashHasSuffix(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldHasSuffix(FieldHash, v)) +} + +// HashEqualFold applies the EqualFold predicate on the "hash" field. +func HashEqualFold(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEqualFold(FieldHash, v)) +} + +// HashContainsFold applies the ContainsFold predicate on the "hash" field. +func HashContainsFold(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldContainsFold(FieldHash, v)) +} + +// FileNameEQ applies the EQ predicate on the "file_name" field. +func FileNameEQ(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldFileName, v)) +} + +// FileNameNEQ applies the NEQ predicate on the "file_name" field. +func FileNameNEQ(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNEQ(FieldFileName, v)) +} + +// FileNameIn applies the In predicate on the "file_name" field. +func FileNameIn(vs ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldIn(FieldFileName, vs...)) +} + +// FileNameNotIn applies the NotIn predicate on the "file_name" field. +func FileNameNotIn(vs ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNotIn(FieldFileName, vs...)) +} + +// FileNameGT applies the GT predicate on the "file_name" field. +func FileNameGT(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGT(FieldFileName, v)) +} + +// FileNameGTE applies the GTE predicate on the "file_name" field. +func FileNameGTE(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGTE(FieldFileName, v)) +} + +// FileNameLT applies the LT predicate on the "file_name" field. +func FileNameLT(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLT(FieldFileName, v)) +} + +// FileNameLTE applies the LTE predicate on the "file_name" field. +func FileNameLTE(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLTE(FieldFileName, v)) +} + +// FileNameContains applies the Contains predicate on the "file_name" field. +func FileNameContains(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldContains(FieldFileName, v)) +} + +// FileNameHasPrefix applies the HasPrefix predicate on the "file_name" field. +func FileNameHasPrefix(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldHasPrefix(FieldFileName, v)) +} + +// FileNameHasSuffix applies the HasSuffix predicate on the "file_name" field. +func FileNameHasSuffix(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldHasSuffix(FieldFileName, v)) +} + +// FileNameEqualFold applies the EqualFold predicate on the "file_name" field. +func FileNameEqualFold(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEqualFold(FieldFileName, v)) +} + +// FileNameContainsFold applies the ContainsFold predicate on the "file_name" field. +func FileNameContainsFold(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldContainsFold(FieldFileName, v)) +} + +// VersionIDEQ applies the EQ predicate on the "version_id" field. +func VersionIDEQ(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEQ(FieldVersionID, v)) +} + +// VersionIDNEQ applies the NEQ predicate on the "version_id" field. +func VersionIDNEQ(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNEQ(FieldVersionID, v)) +} + +// VersionIDIn applies the In predicate on the "version_id" field. +func VersionIDIn(vs ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldIn(FieldVersionID, vs...)) +} + +// VersionIDNotIn applies the NotIn predicate on the "version_id" field. +func VersionIDNotIn(vs ...string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldNotIn(FieldVersionID, vs...)) +} + +// VersionIDGT applies the GT predicate on the "version_id" field. +func VersionIDGT(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGT(FieldVersionID, v)) +} + +// VersionIDGTE applies the GTE predicate on the "version_id" field. +func VersionIDGTE(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldGTE(FieldVersionID, v)) +} + +// VersionIDLT applies the LT predicate on the "version_id" field. +func VersionIDLT(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLT(FieldVersionID, v)) +} + +// VersionIDLTE applies the LTE predicate on the "version_id" field. +func VersionIDLTE(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldLTE(FieldVersionID, v)) +} + +// VersionIDContains applies the Contains predicate on the "version_id" field. +func VersionIDContains(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldContains(FieldVersionID, v)) +} + +// VersionIDHasPrefix applies the HasPrefix predicate on the "version_id" field. +func VersionIDHasPrefix(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldHasPrefix(FieldVersionID, v)) +} + +// VersionIDHasSuffix applies the HasSuffix predicate on the "version_id" field. +func VersionIDHasSuffix(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldHasSuffix(FieldVersionID, v)) +} + +// VersionIDEqualFold applies the EqualFold predicate on the "version_id" field. +func VersionIDEqualFold(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldEqualFold(FieldVersionID, v)) +} + +// VersionIDContainsFold applies the ContainsFold predicate on the "version_id" field. +func VersionIDContainsFold(v string) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.FieldContainsFold(FieldVersionID, v)) +} + +// HasVersion applies the HasEdge predicate on the "version" edge. +func HasVersion() predicate.VirustotalResult { + return predicate.VirustotalResult(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, VersionTable, VersionColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasVersionWith applies the HasEdge predicate on the "version" edge with a given conditions (other predicates). +func HasVersionWith(preds ...predicate.Version) predicate.VirustotalResult { + return predicate.VirustotalResult(func(s *sql.Selector) { + step := newVersionStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.VirustotalResult) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.VirustotalResult) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.VirustotalResult) predicate.VirustotalResult { + return predicate.VirustotalResult(sql.NotPredicates(p)) +} diff --git a/generated/ent/virustotalresult_create.go b/generated/ent/virustotalresult_create.go new file mode 100644 index 00000000..605dd04e --- /dev/null +++ b/generated/ent/virustotalresult_create.go @@ -0,0 +1,812 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/satisfactorymodding/smr-api/generated/ent/version" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" +) + +// VirustotalResultCreate is the builder for creating a VirustotalResult entity. +type VirustotalResultCreate struct { + config + mutation *VirustotalResultMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (vrc *VirustotalResultCreate) SetCreatedAt(t time.Time) *VirustotalResultCreate { + vrc.mutation.SetCreatedAt(t) + return vrc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (vrc *VirustotalResultCreate) SetNillableCreatedAt(t *time.Time) *VirustotalResultCreate { + if t != nil { + vrc.SetCreatedAt(*t) + } + return vrc +} + +// SetUpdatedAt sets the "updated_at" field. +func (vrc *VirustotalResultCreate) SetUpdatedAt(t time.Time) *VirustotalResultCreate { + vrc.mutation.SetUpdatedAt(t) + return vrc +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (vrc *VirustotalResultCreate) SetNillableUpdatedAt(t *time.Time) *VirustotalResultCreate { + if t != nil { + vrc.SetUpdatedAt(*t) + } + return vrc +} + +// SetSafe sets the "safe" field. +func (vrc *VirustotalResultCreate) SetSafe(b bool) *VirustotalResultCreate { + vrc.mutation.SetSafe(b) + return vrc +} + +// SetNillableSafe sets the "safe" field if the given value is not nil. +func (vrc *VirustotalResultCreate) SetNillableSafe(b *bool) *VirustotalResultCreate { + if b != nil { + vrc.SetSafe(*b) + } + return vrc +} + +// SetHash sets the "hash" field. +func (vrc *VirustotalResultCreate) SetHash(s string) *VirustotalResultCreate { + vrc.mutation.SetHash(s) + return vrc +} + +// SetFileName sets the "file_name" field. +func (vrc *VirustotalResultCreate) SetFileName(s string) *VirustotalResultCreate { + vrc.mutation.SetFileName(s) + return vrc +} + +// SetVersionID sets the "version_id" field. +func (vrc *VirustotalResultCreate) SetVersionID(s string) *VirustotalResultCreate { + vrc.mutation.SetVersionID(s) + return vrc +} + +// SetID sets the "id" field. +func (vrc *VirustotalResultCreate) SetID(s string) *VirustotalResultCreate { + vrc.mutation.SetID(s) + return vrc +} + +// SetNillableID sets the "id" field if the given value is not nil. +func (vrc *VirustotalResultCreate) SetNillableID(s *string) *VirustotalResultCreate { + if s != nil { + vrc.SetID(*s) + } + return vrc +} + +// SetVersion sets the "version" edge to the Version entity. +func (vrc *VirustotalResultCreate) SetVersion(v *Version) *VirustotalResultCreate { + return vrc.SetVersionID(v.ID) +} + +// Mutation returns the VirustotalResultMutation object of the builder. +func (vrc *VirustotalResultCreate) Mutation() *VirustotalResultMutation { + return vrc.mutation +} + +// Save creates the VirustotalResult in the database. +func (vrc *VirustotalResultCreate) Save(ctx context.Context) (*VirustotalResult, error) { + vrc.defaults() + return withHooks(ctx, vrc.sqlSave, vrc.mutation, vrc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (vrc *VirustotalResultCreate) SaveX(ctx context.Context) *VirustotalResult { + v, err := vrc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (vrc *VirustotalResultCreate) Exec(ctx context.Context) error { + _, err := vrc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (vrc *VirustotalResultCreate) ExecX(ctx context.Context) { + if err := vrc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (vrc *VirustotalResultCreate) defaults() { + if _, ok := vrc.mutation.CreatedAt(); !ok { + v := virustotalresult.DefaultCreatedAt() + vrc.mutation.SetCreatedAt(v) + } + if _, ok := vrc.mutation.UpdatedAt(); !ok { + v := virustotalresult.DefaultUpdatedAt() + vrc.mutation.SetUpdatedAt(v) + } + if _, ok := vrc.mutation.Safe(); !ok { + v := virustotalresult.DefaultSafe + vrc.mutation.SetSafe(v) + } + if _, ok := vrc.mutation.ID(); !ok { + v := virustotalresult.DefaultID() + vrc.mutation.SetID(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (vrc *VirustotalResultCreate) check() error { + if _, ok := vrc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "VirustotalResult.created_at"`)} + } + if _, ok := vrc.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "VirustotalResult.updated_at"`)} + } + if _, ok := vrc.mutation.Safe(); !ok { + return &ValidationError{Name: "safe", err: errors.New(`ent: missing required field "VirustotalResult.safe"`)} + } + if _, ok := vrc.mutation.Hash(); !ok { + return &ValidationError{Name: "hash", err: errors.New(`ent: missing required field "VirustotalResult.hash"`)} + } + if v, ok := vrc.mutation.Hash(); ok { + if err := virustotalresult.HashValidator(v); err != nil { + return &ValidationError{Name: "hash", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.hash": %w`, err)} + } + } + if _, ok := vrc.mutation.FileName(); !ok { + return &ValidationError{Name: "file_name", err: errors.New(`ent: missing required field "VirustotalResult.file_name"`)} + } + if v, ok := vrc.mutation.FileName(); ok { + if err := virustotalresult.FileNameValidator(v); err != nil { + return &ValidationError{Name: "file_name", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.file_name": %w`, err)} + } + } + if _, ok := vrc.mutation.VersionID(); !ok { + return &ValidationError{Name: "version_id", err: errors.New(`ent: missing required field "VirustotalResult.version_id"`)} + } + if v, ok := vrc.mutation.VersionID(); ok { + if err := virustotalresult.VersionIDValidator(v); err != nil { + return &ValidationError{Name: "version_id", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.version_id": %w`, err)} + } + } + if len(vrc.mutation.VersionIDs()) == 0 { + return &ValidationError{Name: "version", err: errors.New(`ent: missing required edge "VirustotalResult.version"`)} + } + return nil +} + +func (vrc *VirustotalResultCreate) sqlSave(ctx context.Context) (*VirustotalResult, error) { + if err := vrc.check(); err != nil { + return nil, err + } + _node, _spec := vrc.createSpec() + if err := sqlgraph.CreateNode(ctx, vrc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != nil { + if id, ok := _spec.ID.Value.(string); ok { + _node.ID = id + } else { + return nil, fmt.Errorf("unexpected VirustotalResult.ID type: %T", _spec.ID.Value) + } + } + vrc.mutation.id = &_node.ID + vrc.mutation.done = true + return _node, nil +} + +func (vrc *VirustotalResultCreate) createSpec() (*VirustotalResult, *sqlgraph.CreateSpec) { + var ( + _node = &VirustotalResult{config: vrc.config} + _spec = sqlgraph.NewCreateSpec(virustotalresult.Table, sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString)) + ) + _spec.OnConflict = vrc.conflict + if id, ok := vrc.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if value, ok := vrc.mutation.CreatedAt(); ok { + _spec.SetField(virustotalresult.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := vrc.mutation.UpdatedAt(); ok { + _spec.SetField(virustotalresult.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := vrc.mutation.Safe(); ok { + _spec.SetField(virustotalresult.FieldSafe, field.TypeBool, value) + _node.Safe = value + } + if value, ok := vrc.mutation.Hash(); ok { + _spec.SetField(virustotalresult.FieldHash, field.TypeString, value) + _node.Hash = value + } + if value, ok := vrc.mutation.FileName(); ok { + _spec.SetField(virustotalresult.FieldFileName, field.TypeString, value) + _node.FileName = value + } + if nodes := vrc.mutation.VersionIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: virustotalresult.VersionTable, + Columns: []string{virustotalresult.VersionColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(version.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.VersionID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.VirustotalResult.Create(). +// SetCreatedAt(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.VirustotalResultUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (vrc *VirustotalResultCreate) OnConflict(opts ...sql.ConflictOption) *VirustotalResultUpsertOne { + vrc.conflict = opts + return &VirustotalResultUpsertOne{ + create: vrc, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.VirustotalResult.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (vrc *VirustotalResultCreate) OnConflictColumns(columns ...string) *VirustotalResultUpsertOne { + vrc.conflict = append(vrc.conflict, sql.ConflictColumns(columns...)) + return &VirustotalResultUpsertOne{ + create: vrc, + } +} + +type ( + // VirustotalResultUpsertOne is the builder for "upsert"-ing + // one VirustotalResult node. + VirustotalResultUpsertOne struct { + create *VirustotalResultCreate + } + + // VirustotalResultUpsert is the "OnConflict" setter. + VirustotalResultUpsert struct { + *sql.UpdateSet + } +) + +// SetUpdatedAt sets the "updated_at" field. +func (u *VirustotalResultUpsert) SetUpdatedAt(v time.Time) *VirustotalResultUpsert { + u.Set(virustotalresult.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *VirustotalResultUpsert) UpdateUpdatedAt() *VirustotalResultUpsert { + u.SetExcluded(virustotalresult.FieldUpdatedAt) + return u +} + +// SetSafe sets the "safe" field. +func (u *VirustotalResultUpsert) SetSafe(v bool) *VirustotalResultUpsert { + u.Set(virustotalresult.FieldSafe, v) + return u +} + +// UpdateSafe sets the "safe" field to the value that was provided on create. +func (u *VirustotalResultUpsert) UpdateSafe() *VirustotalResultUpsert { + u.SetExcluded(virustotalresult.FieldSafe) + return u +} + +// SetHash sets the "hash" field. +func (u *VirustotalResultUpsert) SetHash(v string) *VirustotalResultUpsert { + u.Set(virustotalresult.FieldHash, v) + return u +} + +// UpdateHash sets the "hash" field to the value that was provided on create. +func (u *VirustotalResultUpsert) UpdateHash() *VirustotalResultUpsert { + u.SetExcluded(virustotalresult.FieldHash) + return u +} + +// SetFileName sets the "file_name" field. +func (u *VirustotalResultUpsert) SetFileName(v string) *VirustotalResultUpsert { + u.Set(virustotalresult.FieldFileName, v) + return u +} + +// UpdateFileName sets the "file_name" field to the value that was provided on create. +func (u *VirustotalResultUpsert) UpdateFileName() *VirustotalResultUpsert { + u.SetExcluded(virustotalresult.FieldFileName) + return u +} + +// SetVersionID sets the "version_id" field. +func (u *VirustotalResultUpsert) SetVersionID(v string) *VirustotalResultUpsert { + u.Set(virustotalresult.FieldVersionID, v) + return u +} + +// UpdateVersionID sets the "version_id" field to the value that was provided on create. +func (u *VirustotalResultUpsert) UpdateVersionID() *VirustotalResultUpsert { + u.SetExcluded(virustotalresult.FieldVersionID) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. +// Using this option is equivalent to using: +// +// client.VirustotalResult.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(virustotalresult.FieldID) +// }), +// ). +// Exec(ctx) +func (u *VirustotalResultUpsertOne) UpdateNewValues() *VirustotalResultUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.ID(); exists { + s.SetIgnore(virustotalresult.FieldID) + } + if _, exists := u.create.mutation.CreatedAt(); exists { + s.SetIgnore(virustotalresult.FieldCreatedAt) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.VirustotalResult.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *VirustotalResultUpsertOne) Ignore() *VirustotalResultUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *VirustotalResultUpsertOne) DoNothing() *VirustotalResultUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the VirustotalResultCreate.OnConflict +// documentation for more info. +func (u *VirustotalResultUpsertOne) Update(set func(*VirustotalResultUpsert)) *VirustotalResultUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&VirustotalResultUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *VirustotalResultUpsertOne) SetUpdatedAt(v time.Time) *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *VirustotalResultUpsertOne) UpdateUpdatedAt() *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetSafe sets the "safe" field. +func (u *VirustotalResultUpsertOne) SetSafe(v bool) *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetSafe(v) + }) +} + +// UpdateSafe sets the "safe" field to the value that was provided on create. +func (u *VirustotalResultUpsertOne) UpdateSafe() *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateSafe() + }) +} + +// SetHash sets the "hash" field. +func (u *VirustotalResultUpsertOne) SetHash(v string) *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetHash(v) + }) +} + +// UpdateHash sets the "hash" field to the value that was provided on create. +func (u *VirustotalResultUpsertOne) UpdateHash() *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateHash() + }) +} + +// SetFileName sets the "file_name" field. +func (u *VirustotalResultUpsertOne) SetFileName(v string) *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetFileName(v) + }) +} + +// UpdateFileName sets the "file_name" field to the value that was provided on create. +func (u *VirustotalResultUpsertOne) UpdateFileName() *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateFileName() + }) +} + +// SetVersionID sets the "version_id" field. +func (u *VirustotalResultUpsertOne) SetVersionID(v string) *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetVersionID(v) + }) +} + +// UpdateVersionID sets the "version_id" field to the value that was provided on create. +func (u *VirustotalResultUpsertOne) UpdateVersionID() *VirustotalResultUpsertOne { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateVersionID() + }) +} + +// Exec executes the query. +func (u *VirustotalResultUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for VirustotalResultCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *VirustotalResultUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *VirustotalResultUpsertOne) ID(ctx context.Context) (id string, err error) { + if u.create.driver.Dialect() == dialect.MySQL { + // In case of "ON CONFLICT", there is no way to get back non-numeric ID + // fields from the database since MySQL does not support the RETURNING clause. + return id, errors.New("ent: VirustotalResultUpsertOne.ID is not supported by MySQL driver. Use VirustotalResultUpsertOne.Exec instead") + } + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *VirustotalResultUpsertOne) IDX(ctx context.Context) string { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// VirustotalResultCreateBulk is the builder for creating many VirustotalResult entities in bulk. +type VirustotalResultCreateBulk struct { + config + err error + builders []*VirustotalResultCreate + conflict []sql.ConflictOption +} + +// Save creates the VirustotalResult entities in the database. +func (vrcb *VirustotalResultCreateBulk) Save(ctx context.Context) ([]*VirustotalResult, error) { + if vrcb.err != nil { + return nil, vrcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(vrcb.builders)) + nodes := make([]*VirustotalResult, len(vrcb.builders)) + mutators := make([]Mutator, len(vrcb.builders)) + for i := range vrcb.builders { + func(i int, root context.Context) { + builder := vrcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*VirustotalResultMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, vrcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = vrcb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, vrcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, vrcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (vrcb *VirustotalResultCreateBulk) SaveX(ctx context.Context) []*VirustotalResult { + v, err := vrcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (vrcb *VirustotalResultCreateBulk) Exec(ctx context.Context) error { + _, err := vrcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (vrcb *VirustotalResultCreateBulk) ExecX(ctx context.Context) { + if err := vrcb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.VirustotalResult.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.VirustotalResultUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (vrcb *VirustotalResultCreateBulk) OnConflict(opts ...sql.ConflictOption) *VirustotalResultUpsertBulk { + vrcb.conflict = opts + return &VirustotalResultUpsertBulk{ + create: vrcb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.VirustotalResult.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (vrcb *VirustotalResultCreateBulk) OnConflictColumns(columns ...string) *VirustotalResultUpsertBulk { + vrcb.conflict = append(vrcb.conflict, sql.ConflictColumns(columns...)) + return &VirustotalResultUpsertBulk{ + create: vrcb, + } +} + +// VirustotalResultUpsertBulk is the builder for "upsert"-ing +// a bulk of VirustotalResult nodes. +type VirustotalResultUpsertBulk struct { + create *VirustotalResultCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.VirustotalResult.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(virustotalresult.FieldID) +// }), +// ). +// Exec(ctx) +func (u *VirustotalResultUpsertBulk) UpdateNewValues() *VirustotalResultUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.ID(); exists { + s.SetIgnore(virustotalresult.FieldID) + } + if _, exists := b.mutation.CreatedAt(); exists { + s.SetIgnore(virustotalresult.FieldCreatedAt) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.VirustotalResult.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *VirustotalResultUpsertBulk) Ignore() *VirustotalResultUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *VirustotalResultUpsertBulk) DoNothing() *VirustotalResultUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the VirustotalResultCreateBulk.OnConflict +// documentation for more info. +func (u *VirustotalResultUpsertBulk) Update(set func(*VirustotalResultUpsert)) *VirustotalResultUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&VirustotalResultUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *VirustotalResultUpsertBulk) SetUpdatedAt(v time.Time) *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *VirustotalResultUpsertBulk) UpdateUpdatedAt() *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetSafe sets the "safe" field. +func (u *VirustotalResultUpsertBulk) SetSafe(v bool) *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetSafe(v) + }) +} + +// UpdateSafe sets the "safe" field to the value that was provided on create. +func (u *VirustotalResultUpsertBulk) UpdateSafe() *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateSafe() + }) +} + +// SetHash sets the "hash" field. +func (u *VirustotalResultUpsertBulk) SetHash(v string) *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetHash(v) + }) +} + +// UpdateHash sets the "hash" field to the value that was provided on create. +func (u *VirustotalResultUpsertBulk) UpdateHash() *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateHash() + }) +} + +// SetFileName sets the "file_name" field. +func (u *VirustotalResultUpsertBulk) SetFileName(v string) *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetFileName(v) + }) +} + +// UpdateFileName sets the "file_name" field to the value that was provided on create. +func (u *VirustotalResultUpsertBulk) UpdateFileName() *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateFileName() + }) +} + +// SetVersionID sets the "version_id" field. +func (u *VirustotalResultUpsertBulk) SetVersionID(v string) *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.SetVersionID(v) + }) +} + +// UpdateVersionID sets the "version_id" field to the value that was provided on create. +func (u *VirustotalResultUpsertBulk) UpdateVersionID() *VirustotalResultUpsertBulk { + return u.Update(func(s *VirustotalResultUpsert) { + s.UpdateVersionID() + }) +} + +// Exec executes the query. +func (u *VirustotalResultUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the VirustotalResultCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for VirustotalResultCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *VirustotalResultUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/generated/ent/virustotalresult_delete.go b/generated/ent/virustotalresult_delete.go new file mode 100644 index 00000000..6068d541 --- /dev/null +++ b/generated/ent/virustotalresult_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/satisfactorymodding/smr-api/generated/ent/predicate" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" +) + +// VirustotalResultDelete is the builder for deleting a VirustotalResult entity. +type VirustotalResultDelete struct { + config + hooks []Hook + mutation *VirustotalResultMutation +} + +// Where appends a list predicates to the VirustotalResultDelete builder. +func (vrd *VirustotalResultDelete) Where(ps ...predicate.VirustotalResult) *VirustotalResultDelete { + vrd.mutation.Where(ps...) + return vrd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (vrd *VirustotalResultDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, vrd.sqlExec, vrd.mutation, vrd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (vrd *VirustotalResultDelete) ExecX(ctx context.Context) int { + n, err := vrd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (vrd *VirustotalResultDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(virustotalresult.Table, sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString)) + if ps := vrd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, vrd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + vrd.mutation.done = true + return affected, err +} + +// VirustotalResultDeleteOne is the builder for deleting a single VirustotalResult entity. +type VirustotalResultDeleteOne struct { + vrd *VirustotalResultDelete +} + +// Where appends a list predicates to the VirustotalResultDelete builder. +func (vrdo *VirustotalResultDeleteOne) Where(ps ...predicate.VirustotalResult) *VirustotalResultDeleteOne { + vrdo.vrd.mutation.Where(ps...) + return vrdo +} + +// Exec executes the deletion query. +func (vrdo *VirustotalResultDeleteOne) Exec(ctx context.Context) error { + n, err := vrdo.vrd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{virustotalresult.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (vrdo *VirustotalResultDeleteOne) ExecX(ctx context.Context) { + if err := vrdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/generated/ent/virustotalresult_query.go b/generated/ent/virustotalresult_query.go new file mode 100644 index 00000000..011e4cf3 --- /dev/null +++ b/generated/ent/virustotalresult_query.go @@ -0,0 +1,628 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/satisfactorymodding/smr-api/generated/ent/predicate" + "github.com/satisfactorymodding/smr-api/generated/ent/version" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" +) + +// VirustotalResultQuery is the builder for querying VirustotalResult entities. +type VirustotalResultQuery struct { + config + ctx *QueryContext + order []virustotalresult.OrderOption + inters []Interceptor + predicates []predicate.VirustotalResult + withVersion *VersionQuery + modifiers []func(*sql.Selector) + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the VirustotalResultQuery builder. +func (vrq *VirustotalResultQuery) Where(ps ...predicate.VirustotalResult) *VirustotalResultQuery { + vrq.predicates = append(vrq.predicates, ps...) + return vrq +} + +// Limit the number of records to be returned by this query. +func (vrq *VirustotalResultQuery) Limit(limit int) *VirustotalResultQuery { + vrq.ctx.Limit = &limit + return vrq +} + +// Offset to start from. +func (vrq *VirustotalResultQuery) Offset(offset int) *VirustotalResultQuery { + vrq.ctx.Offset = &offset + return vrq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (vrq *VirustotalResultQuery) Unique(unique bool) *VirustotalResultQuery { + vrq.ctx.Unique = &unique + return vrq +} + +// Order specifies how the records should be ordered. +func (vrq *VirustotalResultQuery) Order(o ...virustotalresult.OrderOption) *VirustotalResultQuery { + vrq.order = append(vrq.order, o...) + return vrq +} + +// QueryVersion chains the current query on the "version" edge. +func (vrq *VirustotalResultQuery) QueryVersion() *VersionQuery { + query := (&VersionClient{config: vrq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := vrq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := vrq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(virustotalresult.Table, virustotalresult.FieldID, selector), + sqlgraph.To(version.Table, version.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, virustotalresult.VersionTable, virustotalresult.VersionColumn), + ) + fromU = sqlgraph.SetNeighbors(vrq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first VirustotalResult entity from the query. +// Returns a *NotFoundError when no VirustotalResult was found. +func (vrq *VirustotalResultQuery) First(ctx context.Context) (*VirustotalResult, error) { + nodes, err := vrq.Limit(1).All(setContextOp(ctx, vrq.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{virustotalresult.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (vrq *VirustotalResultQuery) FirstX(ctx context.Context) *VirustotalResult { + node, err := vrq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first VirustotalResult ID from the query. +// Returns a *NotFoundError when no VirustotalResult ID was found. +func (vrq *VirustotalResultQuery) FirstID(ctx context.Context) (id string, err error) { + var ids []string + if ids, err = vrq.Limit(1).IDs(setContextOp(ctx, vrq.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{virustotalresult.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (vrq *VirustotalResultQuery) FirstIDX(ctx context.Context) string { + id, err := vrq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single VirustotalResult entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one VirustotalResult entity is found. +// Returns a *NotFoundError when no VirustotalResult entities are found. +func (vrq *VirustotalResultQuery) Only(ctx context.Context) (*VirustotalResult, error) { + nodes, err := vrq.Limit(2).All(setContextOp(ctx, vrq.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{virustotalresult.Label} + default: + return nil, &NotSingularError{virustotalresult.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (vrq *VirustotalResultQuery) OnlyX(ctx context.Context) *VirustotalResult { + node, err := vrq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only VirustotalResult ID in the query. +// Returns a *NotSingularError when more than one VirustotalResult ID is found. +// Returns a *NotFoundError when no entities are found. +func (vrq *VirustotalResultQuery) OnlyID(ctx context.Context) (id string, err error) { + var ids []string + if ids, err = vrq.Limit(2).IDs(setContextOp(ctx, vrq.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{virustotalresult.Label} + default: + err = &NotSingularError{virustotalresult.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (vrq *VirustotalResultQuery) OnlyIDX(ctx context.Context) string { + id, err := vrq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of VirustotalResults. +func (vrq *VirustotalResultQuery) All(ctx context.Context) ([]*VirustotalResult, error) { + ctx = setContextOp(ctx, vrq.ctx, ent.OpQueryAll) + if err := vrq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*VirustotalResult, *VirustotalResultQuery]() + return withInterceptors[[]*VirustotalResult](ctx, vrq, qr, vrq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (vrq *VirustotalResultQuery) AllX(ctx context.Context) []*VirustotalResult { + nodes, err := vrq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of VirustotalResult IDs. +func (vrq *VirustotalResultQuery) IDs(ctx context.Context) (ids []string, err error) { + if vrq.ctx.Unique == nil && vrq.path != nil { + vrq.Unique(true) + } + ctx = setContextOp(ctx, vrq.ctx, ent.OpQueryIDs) + if err = vrq.Select(virustotalresult.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (vrq *VirustotalResultQuery) IDsX(ctx context.Context) []string { + ids, err := vrq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (vrq *VirustotalResultQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, vrq.ctx, ent.OpQueryCount) + if err := vrq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, vrq, querierCount[*VirustotalResultQuery](), vrq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (vrq *VirustotalResultQuery) CountX(ctx context.Context) int { + count, err := vrq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (vrq *VirustotalResultQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, vrq.ctx, ent.OpQueryExist) + switch _, err := vrq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (vrq *VirustotalResultQuery) ExistX(ctx context.Context) bool { + exist, err := vrq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the VirustotalResultQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (vrq *VirustotalResultQuery) Clone() *VirustotalResultQuery { + if vrq == nil { + return nil + } + return &VirustotalResultQuery{ + config: vrq.config, + ctx: vrq.ctx.Clone(), + order: append([]virustotalresult.OrderOption{}, vrq.order...), + inters: append([]Interceptor{}, vrq.inters...), + predicates: append([]predicate.VirustotalResult{}, vrq.predicates...), + withVersion: vrq.withVersion.Clone(), + // clone intermediate query. + sql: vrq.sql.Clone(), + path: vrq.path, + } +} + +// WithVersion tells the query-builder to eager-load the nodes that are connected to +// the "version" edge. The optional arguments are used to configure the query builder of the edge. +func (vrq *VirustotalResultQuery) WithVersion(opts ...func(*VersionQuery)) *VirustotalResultQuery { + query := (&VersionClient{config: vrq.config}).Query() + for _, opt := range opts { + opt(query) + } + vrq.withVersion = query + return vrq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.VirustotalResult.Query(). +// GroupBy(virustotalresult.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (vrq *VirustotalResultQuery) GroupBy(field string, fields ...string) *VirustotalResultGroupBy { + vrq.ctx.Fields = append([]string{field}, fields...) + grbuild := &VirustotalResultGroupBy{build: vrq} + grbuild.flds = &vrq.ctx.Fields + grbuild.label = virustotalresult.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// } +// +// client.VirustotalResult.Query(). +// Select(virustotalresult.FieldCreatedAt). +// Scan(ctx, &v) +func (vrq *VirustotalResultQuery) Select(fields ...string) *VirustotalResultSelect { + vrq.ctx.Fields = append(vrq.ctx.Fields, fields...) + sbuild := &VirustotalResultSelect{VirustotalResultQuery: vrq} + sbuild.label = virustotalresult.Label + sbuild.flds, sbuild.scan = &vrq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a VirustotalResultSelect configured with the given aggregations. +func (vrq *VirustotalResultQuery) Aggregate(fns ...AggregateFunc) *VirustotalResultSelect { + return vrq.Select().Aggregate(fns...) +} + +func (vrq *VirustotalResultQuery) prepareQuery(ctx context.Context) error { + for _, inter := range vrq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, vrq); err != nil { + return err + } + } + } + for _, f := range vrq.ctx.Fields { + if !virustotalresult.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if vrq.path != nil { + prev, err := vrq.path(ctx) + if err != nil { + return err + } + vrq.sql = prev + } + return nil +} + +func (vrq *VirustotalResultQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*VirustotalResult, error) { + var ( + nodes = []*VirustotalResult{} + _spec = vrq.querySpec() + loadedTypes = [1]bool{ + vrq.withVersion != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*VirustotalResult).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &VirustotalResult{config: vrq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if len(vrq.modifiers) > 0 { + _spec.Modifiers = vrq.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, vrq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := vrq.withVersion; query != nil { + if err := vrq.loadVersion(ctx, query, nodes, nil, + func(n *VirustotalResult, e *Version) { n.Edges.Version = e }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (vrq *VirustotalResultQuery) loadVersion(ctx context.Context, query *VersionQuery, nodes []*VirustotalResult, init func(*VirustotalResult), assign func(*VirustotalResult, *Version)) error { + ids := make([]string, 0, len(nodes)) + nodeids := make(map[string][]*VirustotalResult) + for i := range nodes { + fk := nodes[i].VersionID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(version.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "version_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (vrq *VirustotalResultQuery) sqlCount(ctx context.Context) (int, error) { + _spec := vrq.querySpec() + if len(vrq.modifiers) > 0 { + _spec.Modifiers = vrq.modifiers + } + _spec.Node.Columns = vrq.ctx.Fields + if len(vrq.ctx.Fields) > 0 { + _spec.Unique = vrq.ctx.Unique != nil && *vrq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, vrq.driver, _spec) +} + +func (vrq *VirustotalResultQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(virustotalresult.Table, virustotalresult.Columns, sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString)) + _spec.From = vrq.sql + if unique := vrq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if vrq.path != nil { + _spec.Unique = true + } + if fields := vrq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, virustotalresult.FieldID) + for i := range fields { + if fields[i] != virustotalresult.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if vrq.withVersion != nil { + _spec.Node.AddColumnOnce(virustotalresult.FieldVersionID) + } + } + if ps := vrq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := vrq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := vrq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := vrq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (vrq *VirustotalResultQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(vrq.driver.Dialect()) + t1 := builder.Table(virustotalresult.Table) + columns := vrq.ctx.Fields + if len(columns) == 0 { + columns = virustotalresult.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if vrq.sql != nil { + selector = vrq.sql + selector.Select(selector.Columns(columns...)...) + } + if vrq.ctx.Unique != nil && *vrq.ctx.Unique { + selector.Distinct() + } + for _, m := range vrq.modifiers { + m(selector) + } + for _, p := range vrq.predicates { + p(selector) + } + for _, p := range vrq.order { + p(selector) + } + if offset := vrq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := vrq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (vrq *VirustotalResultQuery) Modify(modifiers ...func(s *sql.Selector)) *VirustotalResultSelect { + vrq.modifiers = append(vrq.modifiers, modifiers...) + return vrq.Select() +} + +// VirustotalResultGroupBy is the group-by builder for VirustotalResult entities. +type VirustotalResultGroupBy struct { + selector + build *VirustotalResultQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (vrgb *VirustotalResultGroupBy) Aggregate(fns ...AggregateFunc) *VirustotalResultGroupBy { + vrgb.fns = append(vrgb.fns, fns...) + return vrgb +} + +// Scan applies the selector query and scans the result into the given value. +func (vrgb *VirustotalResultGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, vrgb.build.ctx, ent.OpQueryGroupBy) + if err := vrgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*VirustotalResultQuery, *VirustotalResultGroupBy](ctx, vrgb.build, vrgb, vrgb.build.inters, v) +} + +func (vrgb *VirustotalResultGroupBy) sqlScan(ctx context.Context, root *VirustotalResultQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(vrgb.fns)) + for _, fn := range vrgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*vrgb.flds)+len(vrgb.fns)) + for _, f := range *vrgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*vrgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := vrgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// VirustotalResultSelect is the builder for selecting fields of VirustotalResult entities. +type VirustotalResultSelect struct { + *VirustotalResultQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (vrs *VirustotalResultSelect) Aggregate(fns ...AggregateFunc) *VirustotalResultSelect { + vrs.fns = append(vrs.fns, fns...) + return vrs +} + +// Scan applies the selector query and scans the result into the given value. +func (vrs *VirustotalResultSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, vrs.ctx, ent.OpQuerySelect) + if err := vrs.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*VirustotalResultQuery, *VirustotalResultSelect](ctx, vrs.VirustotalResultQuery, vrs, vrs.inters, v) +} + +func (vrs *VirustotalResultSelect) sqlScan(ctx context.Context, root *VirustotalResultQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(vrs.fns)) + for _, fn := range vrs.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*vrs.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := vrs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (vrs *VirustotalResultSelect) Modify(modifiers ...func(s *sql.Selector)) *VirustotalResultSelect { + vrs.modifiers = append(vrs.modifiers, modifiers...) + return vrs +} diff --git a/generated/ent/virustotalresult_update.go b/generated/ent/virustotalresult_update.go new file mode 100644 index 00000000..43b5705d --- /dev/null +++ b/generated/ent/virustotalresult_update.go @@ -0,0 +1,491 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/satisfactorymodding/smr-api/generated/ent/predicate" + "github.com/satisfactorymodding/smr-api/generated/ent/version" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" +) + +// VirustotalResultUpdate is the builder for updating VirustotalResult entities. +type VirustotalResultUpdate struct { + config + hooks []Hook + mutation *VirustotalResultMutation + modifiers []func(*sql.UpdateBuilder) +} + +// Where appends a list predicates to the VirustotalResultUpdate builder. +func (vru *VirustotalResultUpdate) Where(ps ...predicate.VirustotalResult) *VirustotalResultUpdate { + vru.mutation.Where(ps...) + return vru +} + +// SetUpdatedAt sets the "updated_at" field. +func (vru *VirustotalResultUpdate) SetUpdatedAt(t time.Time) *VirustotalResultUpdate { + vru.mutation.SetUpdatedAt(t) + return vru +} + +// SetSafe sets the "safe" field. +func (vru *VirustotalResultUpdate) SetSafe(b bool) *VirustotalResultUpdate { + vru.mutation.SetSafe(b) + return vru +} + +// SetNillableSafe sets the "safe" field if the given value is not nil. +func (vru *VirustotalResultUpdate) SetNillableSafe(b *bool) *VirustotalResultUpdate { + if b != nil { + vru.SetSafe(*b) + } + return vru +} + +// SetHash sets the "hash" field. +func (vru *VirustotalResultUpdate) SetHash(s string) *VirustotalResultUpdate { + vru.mutation.SetHash(s) + return vru +} + +// SetNillableHash sets the "hash" field if the given value is not nil. +func (vru *VirustotalResultUpdate) SetNillableHash(s *string) *VirustotalResultUpdate { + if s != nil { + vru.SetHash(*s) + } + return vru +} + +// SetFileName sets the "file_name" field. +func (vru *VirustotalResultUpdate) SetFileName(s string) *VirustotalResultUpdate { + vru.mutation.SetFileName(s) + return vru +} + +// SetNillableFileName sets the "file_name" field if the given value is not nil. +func (vru *VirustotalResultUpdate) SetNillableFileName(s *string) *VirustotalResultUpdate { + if s != nil { + vru.SetFileName(*s) + } + return vru +} + +// SetVersionID sets the "version_id" field. +func (vru *VirustotalResultUpdate) SetVersionID(s string) *VirustotalResultUpdate { + vru.mutation.SetVersionID(s) + return vru +} + +// SetNillableVersionID sets the "version_id" field if the given value is not nil. +func (vru *VirustotalResultUpdate) SetNillableVersionID(s *string) *VirustotalResultUpdate { + if s != nil { + vru.SetVersionID(*s) + } + return vru +} + +// SetVersion sets the "version" edge to the Version entity. +func (vru *VirustotalResultUpdate) SetVersion(v *Version) *VirustotalResultUpdate { + return vru.SetVersionID(v.ID) +} + +// Mutation returns the VirustotalResultMutation object of the builder. +func (vru *VirustotalResultUpdate) Mutation() *VirustotalResultMutation { + return vru.mutation +} + +// ClearVersion clears the "version" edge to the Version entity. +func (vru *VirustotalResultUpdate) ClearVersion() *VirustotalResultUpdate { + vru.mutation.ClearVersion() + return vru +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (vru *VirustotalResultUpdate) Save(ctx context.Context) (int, error) { + vru.defaults() + return withHooks(ctx, vru.sqlSave, vru.mutation, vru.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (vru *VirustotalResultUpdate) SaveX(ctx context.Context) int { + affected, err := vru.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (vru *VirustotalResultUpdate) Exec(ctx context.Context) error { + _, err := vru.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (vru *VirustotalResultUpdate) ExecX(ctx context.Context) { + if err := vru.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (vru *VirustotalResultUpdate) defaults() { + if _, ok := vru.mutation.UpdatedAt(); !ok { + v := virustotalresult.UpdateDefaultUpdatedAt() + vru.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (vru *VirustotalResultUpdate) check() error { + if v, ok := vru.mutation.Hash(); ok { + if err := virustotalresult.HashValidator(v); err != nil { + return &ValidationError{Name: "hash", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.hash": %w`, err)} + } + } + if v, ok := vru.mutation.FileName(); ok { + if err := virustotalresult.FileNameValidator(v); err != nil { + return &ValidationError{Name: "file_name", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.file_name": %w`, err)} + } + } + if v, ok := vru.mutation.VersionID(); ok { + if err := virustotalresult.VersionIDValidator(v); err != nil { + return &ValidationError{Name: "version_id", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.version_id": %w`, err)} + } + } + if vru.mutation.VersionCleared() && len(vru.mutation.VersionIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "VirustotalResult.version"`) + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (vru *VirustotalResultUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *VirustotalResultUpdate { + vru.modifiers = append(vru.modifiers, modifiers...) + return vru +} + +func (vru *VirustotalResultUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := vru.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(virustotalresult.Table, virustotalresult.Columns, sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString)) + if ps := vru.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := vru.mutation.UpdatedAt(); ok { + _spec.SetField(virustotalresult.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := vru.mutation.Safe(); ok { + _spec.SetField(virustotalresult.FieldSafe, field.TypeBool, value) + } + if value, ok := vru.mutation.Hash(); ok { + _spec.SetField(virustotalresult.FieldHash, field.TypeString, value) + } + if value, ok := vru.mutation.FileName(); ok { + _spec.SetField(virustotalresult.FieldFileName, field.TypeString, value) + } + if vru.mutation.VersionCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: virustotalresult.VersionTable, + Columns: []string{virustotalresult.VersionColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(version.FieldID, field.TypeString), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := vru.mutation.VersionIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: virustotalresult.VersionTable, + Columns: []string{virustotalresult.VersionColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(version.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _spec.AddModifiers(vru.modifiers...) + if n, err = sqlgraph.UpdateNodes(ctx, vru.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{virustotalresult.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + vru.mutation.done = true + return n, nil +} + +// VirustotalResultUpdateOne is the builder for updating a single VirustotalResult entity. +type VirustotalResultUpdateOne struct { + config + fields []string + hooks []Hook + mutation *VirustotalResultMutation + modifiers []func(*sql.UpdateBuilder) +} + +// SetUpdatedAt sets the "updated_at" field. +func (vruo *VirustotalResultUpdateOne) SetUpdatedAt(t time.Time) *VirustotalResultUpdateOne { + vruo.mutation.SetUpdatedAt(t) + return vruo +} + +// SetSafe sets the "safe" field. +func (vruo *VirustotalResultUpdateOne) SetSafe(b bool) *VirustotalResultUpdateOne { + vruo.mutation.SetSafe(b) + return vruo +} + +// SetNillableSafe sets the "safe" field if the given value is not nil. +func (vruo *VirustotalResultUpdateOne) SetNillableSafe(b *bool) *VirustotalResultUpdateOne { + if b != nil { + vruo.SetSafe(*b) + } + return vruo +} + +// SetHash sets the "hash" field. +func (vruo *VirustotalResultUpdateOne) SetHash(s string) *VirustotalResultUpdateOne { + vruo.mutation.SetHash(s) + return vruo +} + +// SetNillableHash sets the "hash" field if the given value is not nil. +func (vruo *VirustotalResultUpdateOne) SetNillableHash(s *string) *VirustotalResultUpdateOne { + if s != nil { + vruo.SetHash(*s) + } + return vruo +} + +// SetFileName sets the "file_name" field. +func (vruo *VirustotalResultUpdateOne) SetFileName(s string) *VirustotalResultUpdateOne { + vruo.mutation.SetFileName(s) + return vruo +} + +// SetNillableFileName sets the "file_name" field if the given value is not nil. +func (vruo *VirustotalResultUpdateOne) SetNillableFileName(s *string) *VirustotalResultUpdateOne { + if s != nil { + vruo.SetFileName(*s) + } + return vruo +} + +// SetVersionID sets the "version_id" field. +func (vruo *VirustotalResultUpdateOne) SetVersionID(s string) *VirustotalResultUpdateOne { + vruo.mutation.SetVersionID(s) + return vruo +} + +// SetNillableVersionID sets the "version_id" field if the given value is not nil. +func (vruo *VirustotalResultUpdateOne) SetNillableVersionID(s *string) *VirustotalResultUpdateOne { + if s != nil { + vruo.SetVersionID(*s) + } + return vruo +} + +// SetVersion sets the "version" edge to the Version entity. +func (vruo *VirustotalResultUpdateOne) SetVersion(v *Version) *VirustotalResultUpdateOne { + return vruo.SetVersionID(v.ID) +} + +// Mutation returns the VirustotalResultMutation object of the builder. +func (vruo *VirustotalResultUpdateOne) Mutation() *VirustotalResultMutation { + return vruo.mutation +} + +// ClearVersion clears the "version" edge to the Version entity. +func (vruo *VirustotalResultUpdateOne) ClearVersion() *VirustotalResultUpdateOne { + vruo.mutation.ClearVersion() + return vruo +} + +// Where appends a list predicates to the VirustotalResultUpdate builder. +func (vruo *VirustotalResultUpdateOne) Where(ps ...predicate.VirustotalResult) *VirustotalResultUpdateOne { + vruo.mutation.Where(ps...) + return vruo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (vruo *VirustotalResultUpdateOne) Select(field string, fields ...string) *VirustotalResultUpdateOne { + vruo.fields = append([]string{field}, fields...) + return vruo +} + +// Save executes the query and returns the updated VirustotalResult entity. +func (vruo *VirustotalResultUpdateOne) Save(ctx context.Context) (*VirustotalResult, error) { + vruo.defaults() + return withHooks(ctx, vruo.sqlSave, vruo.mutation, vruo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (vruo *VirustotalResultUpdateOne) SaveX(ctx context.Context) *VirustotalResult { + node, err := vruo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (vruo *VirustotalResultUpdateOne) Exec(ctx context.Context) error { + _, err := vruo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (vruo *VirustotalResultUpdateOne) ExecX(ctx context.Context) { + if err := vruo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (vruo *VirustotalResultUpdateOne) defaults() { + if _, ok := vruo.mutation.UpdatedAt(); !ok { + v := virustotalresult.UpdateDefaultUpdatedAt() + vruo.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (vruo *VirustotalResultUpdateOne) check() error { + if v, ok := vruo.mutation.Hash(); ok { + if err := virustotalresult.HashValidator(v); err != nil { + return &ValidationError{Name: "hash", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.hash": %w`, err)} + } + } + if v, ok := vruo.mutation.FileName(); ok { + if err := virustotalresult.FileNameValidator(v); err != nil { + return &ValidationError{Name: "file_name", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.file_name": %w`, err)} + } + } + if v, ok := vruo.mutation.VersionID(); ok { + if err := virustotalresult.VersionIDValidator(v); err != nil { + return &ValidationError{Name: "version_id", err: fmt.Errorf(`ent: validator failed for field "VirustotalResult.version_id": %w`, err)} + } + } + if vruo.mutation.VersionCleared() && len(vruo.mutation.VersionIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "VirustotalResult.version"`) + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (vruo *VirustotalResultUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *VirustotalResultUpdateOne { + vruo.modifiers = append(vruo.modifiers, modifiers...) + return vruo +} + +func (vruo *VirustotalResultUpdateOne) sqlSave(ctx context.Context) (_node *VirustotalResult, err error) { + if err := vruo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(virustotalresult.Table, virustotalresult.Columns, sqlgraph.NewFieldSpec(virustotalresult.FieldID, field.TypeString)) + id, ok := vruo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "VirustotalResult.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := vruo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, virustotalresult.FieldID) + for _, f := range fields { + if !virustotalresult.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != virustotalresult.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := vruo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := vruo.mutation.UpdatedAt(); ok { + _spec.SetField(virustotalresult.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := vruo.mutation.Safe(); ok { + _spec.SetField(virustotalresult.FieldSafe, field.TypeBool, value) + } + if value, ok := vruo.mutation.Hash(); ok { + _spec.SetField(virustotalresult.FieldHash, field.TypeString, value) + } + if value, ok := vruo.mutation.FileName(); ok { + _spec.SetField(virustotalresult.FieldFileName, field.TypeString, value) + } + if vruo.mutation.VersionCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: virustotalresult.VersionTable, + Columns: []string{virustotalresult.VersionColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(version.FieldID, field.TypeString), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := vruo.mutation.VersionIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: virustotalresult.VersionTable, + Columns: []string{virustotalresult.VersionColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(version.FieldID, field.TypeString), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _spec.AddModifiers(vruo.modifiers...) + _node = &VirustotalResult{config: vruo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, vruo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{virustotalresult.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + vruo.mutation.done = true + return _node, nil +} diff --git a/generated/generated.go b/generated/generated.go index 92742374..cac5eec2 100644 --- a/generated/generated.go +++ b/generated/generated.go @@ -331,24 +331,25 @@ type ComplexityRoot struct { } Version struct { - Approved func(childComplexity int) int - Changelog func(childComplexity int) int - CreatedAt func(childComplexity int) int - Dependencies func(childComplexity int) int - Downloads func(childComplexity int) int - GameVersion func(childComplexity int) int - Hash func(childComplexity int) int - ID func(childComplexity int) int - Link func(childComplexity int) int - Metadata func(childComplexity int) int - Mod func(childComplexity int) int - ModID func(childComplexity int) int - Size func(childComplexity int) int - SmlVersion func(childComplexity int) int - Stability func(childComplexity int) int - Targets func(childComplexity int) int - UpdatedAt func(childComplexity int) int - Version func(childComplexity int) int + Approved func(childComplexity int) int + Changelog func(childComplexity int) int + CreatedAt func(childComplexity int) int + Dependencies func(childComplexity int) int + Downloads func(childComplexity int) int + GameVersion func(childComplexity int) int + Hash func(childComplexity int) int + ID func(childComplexity int) int + Link func(childComplexity int) int + Metadata func(childComplexity int) int + Mod func(childComplexity int) int + ModID func(childComplexity int) int + Size func(childComplexity int) int + SmlVersion func(childComplexity int) int + Stability func(childComplexity int) int + Targets func(childComplexity int) int + UpdatedAt func(childComplexity int) int + Version func(childComplexity int) int + VirustotalResults func(childComplexity int) int } VersionDependency struct { @@ -363,11 +364,22 @@ type ComplexityRoot struct { VersionTarget struct { Hash func(childComplexity int) int + ID func(childComplexity int) int Link func(childComplexity int) int Size func(childComplexity int) int TargetName func(childComplexity int) int VersionID func(childComplexity int) int } + + VirustotalResult struct { + CreatedAt func(childComplexity int) int + FileName func(childComplexity int) int + Hash func(childComplexity int) int + ID func(childComplexity int) int + Safe func(childComplexity int) int + UpdatedAt func(childComplexity int) int + VersionID func(childComplexity int) int + } } type GetGuidesResolver interface { @@ -498,6 +510,7 @@ type VersionResolver interface { Hash(ctx context.Context, obj *Version) (*string, error) Mod(ctx context.Context, obj *Version) (*Mod, error) Dependencies(ctx context.Context, obj *Version) ([]*VersionDependency, error) + VirustotalResults(ctx context.Context, obj *Version) ([]*VirustotalResult, error) } type VersionDependencyResolver interface { Mod(ctx context.Context, obj *VersionDependency) (*Mod, error) @@ -2209,6 +2222,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Version.Version(childComplexity), true + case "Version.virustotal_results": + if e.complexity.Version.VirustotalResults == nil { + break + } + + return e.complexity.Version.VirustotalResults(childComplexity), true + case "VersionDependency.condition": if e.complexity.VersionDependency.Condition == nil { break @@ -2265,6 +2285,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.VersionTarget.Hash(childComplexity), true + case "VersionTarget.id": + if e.complexity.VersionTarget.ID == nil { + break + } + + return e.complexity.VersionTarget.ID(childComplexity), true + case "VersionTarget.link": if e.complexity.VersionTarget.Link == nil { break @@ -2293,6 +2320,55 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.VersionTarget.VersionID(childComplexity), true + case "VirustotalResult.created_at": + if e.complexity.VirustotalResult.CreatedAt == nil { + break + } + + return e.complexity.VirustotalResult.CreatedAt(childComplexity), true + + case "VirustotalResult.file_name": + if e.complexity.VirustotalResult.FileName == nil { + break + } + + return e.complexity.VirustotalResult.FileName(childComplexity), true + + case "VirustotalResult.hash": + if e.complexity.VirustotalResult.Hash == nil { + break + } + + return e.complexity.VirustotalResult.Hash(childComplexity), true + + case "VirustotalResult.id": + if e.complexity.VirustotalResult.ID == nil { + break + } + + return e.complexity.VirustotalResult.ID(childComplexity), true + + case "VirustotalResult.safe": + if e.complexity.VirustotalResult.Safe == nil { + break + } + + return e.complexity.VirustotalResult.Safe(childComplexity), true + + case "VirustotalResult.updated_at": + if e.complexity.VirustotalResult.UpdatedAt == nil { + break + } + + return e.complexity.VirustotalResult.UpdatedAt(childComplexity), true + + case "VirustotalResult.version_id": + if e.complexity.VirustotalResult.VersionID == nil { + break + } + + return e.complexity.VirustotalResult.VersionID(childComplexity), true + } return 0, false } @@ -2996,6 +3072,7 @@ type Version { mod: Mod! dependencies: [VersionDependency!]! + virustotal_results: [VirustotalResult!]! } type VersionTarget { @@ -3004,6 +3081,7 @@ type VersionTarget { link: String! size: Int hash: String + id: VersionTargetID! } type CreateVersionResponse { @@ -3023,7 +3101,10 @@ type GetMyVersions { type VersionDependency { version_id: VersionID! - mod_id: ModID! @deprecated(reason: "soon will return actual mod id instead of reference. use mod_reference field instead!") + mod_id: ModID! + @deprecated( + reason: "soon will return actual mod id instead of reference. use mod_reference field instead!" + ) condition: String! optional: Boolean! mod_reference: String! @@ -3058,9 +3139,14 @@ input UpdateVersion { extend type Query { getVersion(versionId: VersionID!): Version getVersions(filter: VersionFilter): GetVersions! - getUnapprovedVersions(filter: VersionFilter): GetVersions! @canApproveVersions @isLoggedIn + getUnapprovedVersions(filter: VersionFilter): GetVersions! + @canApproveVersions + @isLoggedIn - checkVersionUploadState(modId: ModID!, versionId: VersionID!): CreateVersionResponse @canEditMod(field: "modId") @isLoggedIn + checkVersionUploadState( + modId: ModID! + versionId: VersionID! + ): CreateVersionResponse @canEditMod(field: "modId") @isLoggedIn getMyVersions(filter: VersionFilter): GetMyVersions! @isLoggedIn getMyUnapprovedVersions(filter: VersionFilter): GetMyVersions! @isLoggedIn @@ -3069,21 +3155,66 @@ extend type Query { ### Mutations extend type Mutation { - createVersion(modId: ModID!): VersionID! @canEditMod(field: "modId") @isLoggedIn - uploadVersionPart(modId: ModID!, versionId: VersionID!, part: Int!, file: Upload!): Boolean! @canEditMod(field: "modId") @isLoggedIn - finalizeCreateVersion(modId: ModID!, versionId: VersionID!, version: NewVersion!): Boolean! @canEditMod(field: "modId") @isLoggedIn - - updateVersion(versionId: VersionID!, version: UpdateVersion!): Version! @canEditVersion(field: "versionId") @isLoggedIn - deleteVersion(versionId: VersionID!): Boolean! @canEditVersion(field: "versionId") @isLoggedIn - - approveVersion(versionId: VersionID!): Boolean! @canApproveVersions @isLoggedIn + createVersion(modId: ModID!): VersionID! + @canEditMod(field: "modId") + @isLoggedIn + uploadVersionPart( + modId: ModID! + versionId: VersionID! + part: Int! + file: Upload! + ): Boolean! @canEditMod(field: "modId") @isLoggedIn + finalizeCreateVersion( + modId: ModID! + versionId: VersionID! + version: NewVersion! + ): Boolean! @canEditMod(field: "modId") @isLoggedIn + + updateVersion(versionId: VersionID!, version: UpdateVersion!): Version! + @canEditVersion(field: "versionId") + @isLoggedIn + deleteVersion(versionId: VersionID!): Boolean! + @canEditVersion(field: "versionId") + @isLoggedIn + + approveVersion(versionId: VersionID!): Boolean! + @canApproveVersions + @isLoggedIn denyVersion(versionId: VersionID!): Boolean! @canApproveVersions @isLoggedIn -}`, BuiltIn: false}, - {Name: "../schemas/version_target.graphql", Input: `enum TargetName { - Windows, - WindowsServer, +} +`, BuiltIn: false}, + {Name: "../schemas/version_target.graphql", Input: `scalar VersionTargetID + +enum TargetName { + Windows + WindowsServer LinuxServer -}`, BuiltIn: false}, +} +`, BuiltIn: false}, + {Name: "../schemas/virustotal_results.graphql", Input: `### Types + +scalar VirustotalHash +scalar VirustotalID + +type VirustotalResult { + id: VirustotalID + hash: VirustotalHash! + safe: Boolean! + file_name: String! + version_id: String! + created_at: Date! + updated_at: Date +} + +enum VirustotalResultFields { + id + hash + safe + version_id + created_at + updated_at +} +`, BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) @@ -4765,6 +4896,8 @@ func (ec *executionContext) fieldContext_CreateVersionResponse_version(_ context return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -5241,6 +5374,8 @@ func (ec *executionContext) fieldContext_GetMyVersions_versions(_ context.Contex return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -5481,6 +5616,8 @@ func (ec *executionContext) fieldContext_GetVersions_versions(_ context.Context, return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -6168,6 +6305,8 @@ func (ec *executionContext) fieldContext_LatestVersions_alpha(_ context.Context, return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -6247,6 +6386,8 @@ func (ec *executionContext) fieldContext_LatestVersions_beta(_ context.Context, return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -6326,6 +6467,8 @@ func (ec *executionContext) fieldContext_LatestVersions_release(_ context.Contex return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -7422,6 +7565,8 @@ func (ec *executionContext) fieldContext_Mod_version(ctx context.Context, field return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -7515,6 +7660,8 @@ func (ec *executionContext) fieldContext_Mod_versions(ctx context.Context, field return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -7748,6 +7895,8 @@ func (ec *executionContext) fieldContext_ModVersion_versions(_ context.Context, return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -10420,6 +10569,8 @@ func (ec *executionContext) fieldContext_Mutation_updateVersion(ctx context.Cont return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -12634,6 +12785,8 @@ func (ec *executionContext) fieldContext_Query_getVersion(ctx context.Context, f return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -16199,6 +16352,8 @@ func (ec *executionContext) fieldContext_Version_targets(_ context.Context, fiel return ec.fieldContext_VersionTarget_size(ctx, field) case "hash": return ec.fieldContext_VersionTarget_hash(ctx, field) + case "id": + return ec.fieldContext_VersionTarget_id(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type VersionTarget", field.Name) }, @@ -16487,6 +16642,66 @@ func (ec *executionContext) fieldContext_Version_dependencies(_ context.Context, return fc, nil } +func (ec *executionContext) _Version_virustotal_results(ctx context.Context, field graphql.CollectedField, obj *Version) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Version_virustotal_results(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.Version().VirustotalResults(rctx, obj) + }) + 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.([]*VirustotalResult) + fc.Result = res + return ec.marshalNVirustotalResult2ᚕᚖgithubᚗcomᚋsatisfactorymoddingᚋsmrᚑapiᚋgeneratedᚐVirustotalResultᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Version_virustotal_results(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Version", + 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_VirustotalResult_id(ctx, field) + case "hash": + return ec.fieldContext_VirustotalResult_hash(ctx, field) + case "safe": + return ec.fieldContext_VirustotalResult_safe(ctx, field) + case "file_name": + return ec.fieldContext_VirustotalResult_file_name(ctx, field) + case "version_id": + return ec.fieldContext_VirustotalResult_version_id(ctx, field) + case "created_at": + return ec.fieldContext_VirustotalResult_created_at(ctx, field) + case "updated_at": + return ec.fieldContext_VirustotalResult_updated_at(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type VirustotalResult", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _VersionDependency_version_id(ctx context.Context, field graphql.CollectedField, obj *VersionDependency) (ret graphql.Marshaler) { fc, err := ec.fieldContext_VersionDependency_version_id(ctx, field) if err != nil { @@ -16874,6 +17089,8 @@ func (ec *executionContext) fieldContext_VersionDependency_version(_ context.Con return ec.fieldContext_Version_mod(ctx, field) case "dependencies": return ec.fieldContext_Version_dependencies(ctx, field) + case "virustotal_results": + return ec.fieldContext_Version_virustotal_results(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Version", field.Name) }, @@ -17095,8 +17312,8 @@ func (ec *executionContext) fieldContext_VersionTarget_hash(_ context.Context, f 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) +func (ec *executionContext) _VersionTarget_id(ctx context.Context, field graphql.CollectedField, obj *VersionTarget) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VersionTarget_id(ctx, field) if err != nil { return graphql.Null } @@ -17109,7 +17326,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -17123,24 +17340,24 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql } res := resTmp.(string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNVersionTargetID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VersionTarget_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__Directive", + Object: "VersionTarget", 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 nil, errors.New("field of type VersionTargetID 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) +func (ec *executionContext) _VirustotalResult_id(ctx context.Context, field graphql.CollectedField, obj *VirustotalResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VirustotalResult_id(ctx, field) if err != nil { return graphql.Null } @@ -17153,7 +17370,7 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description(), nil + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -17164,24 +17381,24 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field } res := resTmp.(*string) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalOVirustotalID2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VirustotalResult_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__Directive", + Object: "VirustotalResult", Field: field, - IsMethod: true, + 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 nil, errors.New("field of type VirustotalID 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) +func (ec *executionContext) _VirustotalResult_hash(ctx context.Context, field graphql.CollectedField, obj *VirustotalResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VirustotalResult_hash(ctx, field) if err != nil { return graphql.Null } @@ -17194,7 +17411,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Locations, nil + return obj.Hash, nil }) if err != nil { ec.Error(ctx, err) @@ -17206,26 +17423,26 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr } return graphql.Null } - res := resTmp.([]string) + res := resTmp.(string) fc.Result = res - return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalNVirustotalHash2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_locations(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VirustotalResult_hash(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__Directive", + Object: "VirustotalResult", 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 nil, errors.New("field of type VirustotalHash 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) +func (ec *executionContext) _VirustotalResult_safe(ctx context.Context, field graphql.CollectedField, obj *VirustotalResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VirustotalResult_safe(ctx, field) if err != nil { return graphql.Null } @@ -17238,7 +17455,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Args, nil + return obj.Safe, nil }) if err != nil { ec.Error(ctx, err) @@ -17250,36 +17467,26 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.([]introspection.InputValue) + res := resTmp.(bool) fc.Result = res - return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_args(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VirustotalResult_safe(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__Directive", + Object: "VirustotalResult", 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 nil, errors.New("field of type Boolean does not have child fields") }, } 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) +func (ec *executionContext) _VirustotalResult_file_name(ctx context.Context, field graphql.CollectedField, obj *VirustotalResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VirustotalResult_file_name(ctx, field) if err != nil { return graphql.Null } @@ -17292,7 +17499,7 @@ func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.IsRepeatable, nil + return obj.FileName, nil }) if err != nil { ec.Error(ctx, err) @@ -17304,26 +17511,26 @@ func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_isRepeatable(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VirustotalResult_file_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__Directive", + Object: "VirustotalResult", 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 nil, errors.New("field of type String 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) +func (ec *executionContext) _VirustotalResult_version_id(ctx context.Context, field graphql.CollectedField, obj *VirustotalResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VirustotalResult_version_id(ctx, field) if err != nil { return graphql.Null } @@ -17336,7 +17543,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return obj.VersionID, nil }) if err != nil { ec.Error(ctx, err) @@ -17353,9 +17560,9 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VirustotalResult_version_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__EnumValue", + Object: "VirustotalResult", Field: field, IsMethod: false, IsResolver: false, @@ -17366,8 +17573,8 @@ func (ec *executionContext) fieldContext___EnumValue_name(_ context.Context, fie 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) +func (ec *executionContext) _VirustotalResult_created_at(ctx context.Context, field graphql.CollectedField, obj *VirustotalResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VirustotalResult_created_at(ctx, field) if err != nil { return graphql.Null } @@ -17380,35 +17587,38 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description(), nil + 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.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalNDate2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VirustotalResult_created_at(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__EnumValue", + Object: "VirustotalResult", Field: field, - IsMethod: true, + 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 nil, errors.New("field of type Date 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) +func (ec *executionContext) _VirustotalResult_updated_at(ctx context.Context, field graphql.CollectedField, obj *VirustotalResult) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_VirustotalResult_updated_at(ctx, field) if err != nil { return graphql.Null } @@ -17421,38 +17631,35 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.IsDeprecated(), nil + 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.(bool) + res := resTmp.(*string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalODate2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_isDeprecated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_VirustotalResult_updated_at(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__EnumValue", + Object: "VirustotalResult", Field: field, - IsMethod: true, + 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 nil, errors.New("field of type Date 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) +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 } @@ -17465,25 +17672,28 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.DeprecationReason(), nil + 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) + res := resTmp.(string) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_deprecationReason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Directive_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__EnumValue", + Object: "__Directive", Field: field, - IsMethod: true, + 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") @@ -17492,8 +17702,8 @@ func (ec *executionContext) fieldContext___EnumValue_deprecationReason(_ context 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) +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 } @@ -17506,28 +17716,25 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return obj.Description(), 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) + res := resTmp.(*string) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Field_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Directive_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "__Field", + Object: "__Directive", Field: field, - IsMethod: false, + 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") @@ -17536,8 +17743,8 @@ func (ec *executionContext) fieldContext___Field_name(_ context.Context, field g 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) +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 } @@ -17550,16 +17757,372 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description(), nil + 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) + res := resTmp.([]string) + fc.Result = res + return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_locations(_ 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(_ 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(_ 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(_ 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(_ 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(_ 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(_ 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(_ 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) } @@ -23306,6 +23869,42 @@ func (ec *executionContext) _Version(ctx context.Context, sel ast.SelectionSet, continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "virustotal_results": + 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._Version_virustotal_results(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) @@ -23485,6 +24084,74 @@ func (ec *executionContext) _VersionTarget(ctx context.Context, sel ast.Selectio out.Values[i] = ec._VersionTarget_size(ctx, field, obj) case "hash": out.Values[i] = ec._VersionTarget_hash(ctx, field, obj) + case "id": + out.Values[i] = ec._VersionTarget_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + 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 virustotalResultImplementors = []string{"VirustotalResult"} + +func (ec *executionContext) _VirustotalResult(ctx context.Context, sel ast.SelectionSet, obj *VirustotalResult) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, virustotalResultImplementors) + + 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("VirustotalResult") + case "id": + out.Values[i] = ec._VirustotalResult_id(ctx, field, obj) + case "hash": + out.Values[i] = ec._VirustotalResult_hash(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "safe": + out.Values[i] = ec._VirustotalResult_safe(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "file_name": + out.Values[i] = ec._VirustotalResult_file_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "version_id": + out.Values[i] = ec._VirustotalResult_version_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "created_at": + out.Values[i] = ec._VirustotalResult_created_at(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "updated_at": + out.Values[i] = ec._VirustotalResult_updated_at(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -25191,6 +25858,90 @@ func (ec *executionContext) marshalNVersionTarget2ᚕᚖgithubᚗcomᚋsatisfact return ret } +func (ec *executionContext) unmarshalNVersionTargetID2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNVersionTargetID2string(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) unmarshalNVirustotalHash2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNVirustotalHash2string(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) marshalNVirustotalResult2ᚕᚖgithubᚗcomᚋsatisfactorymoddingᚋsmrᚑapiᚋgeneratedᚐVirustotalResultᚄ(ctx context.Context, sel ast.SelectionSet, v []*VirustotalResult) 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.marshalNVirustotalResult2ᚖgithubᚗcomᚋsatisfactorymoddingᚋsmrᚑapiᚋgeneratedᚐVirustotalResult(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) marshalNVirustotalResult2ᚖgithubᚗcomᚋsatisfactorymoddingᚋsmrᚑapiᚋgeneratedᚐVirustotalResult(ctx context.Context, sel ast.SelectionSet, v *VirustotalResult) 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._VirustotalResult(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) } @@ -25944,6 +26695,22 @@ func (ec *executionContext) marshalOVersionTarget2ᚖgithubᚗcomᚋsatisfactory return ec._VersionTarget(ctx, sel, v) } +func (ec *executionContext) unmarshalOVirustotalID2ᚖ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) marshalOVirustotalID2ᚖ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 diff --git a/generated/models_gen.go b/generated/models_gen.go index 6487fc53..854232cd 100644 --- a/generated/models_gen.go +++ b/generated/models_gen.go @@ -288,24 +288,25 @@ type UserSession struct { } type Version struct { - ID string `json:"id"` - ModID string `json:"mod_id"` - Version string `json:"version"` - SmlVersion string `json:"sml_version"` - GameVersion string `json:"game_version"` - Changelog string `json:"changelog"` - Downloads int `json:"downloads"` - Stability VersionStabilities `json:"stability"` - Approved bool `json:"approved"` - UpdatedAt string `json:"updated_at"` - CreatedAt string `json:"created_at"` - Link string `json:"link"` - Targets []*VersionTarget `json:"targets"` - Metadata *string `json:"metadata,omitempty"` - Size *int `json:"size,omitempty"` - Hash *string `json:"hash,omitempty"` - Mod *Mod `json:"mod"` - Dependencies []*VersionDependency `json:"dependencies"` + ID string `json:"id"` + ModID string `json:"mod_id"` + Version string `json:"version"` + SmlVersion string `json:"sml_version"` + GameVersion string `json:"game_version"` + Changelog string `json:"changelog"` + Downloads int `json:"downloads"` + Stability VersionStabilities `json:"stability"` + Approved bool `json:"approved"` + UpdatedAt string `json:"updated_at"` + CreatedAt string `json:"created_at"` + Link string `json:"link"` + Targets []*VersionTarget `json:"targets"` + Metadata *string `json:"metadata,omitempty"` + Size *int `json:"size,omitempty"` + Hash *string `json:"hash,omitempty"` + Mod *Mod `json:"mod"` + Dependencies []*VersionDependency `json:"dependencies"` + VirustotalResults []*VirustotalResult `json:"virustotal_results"` } type VersionDependency struct { @@ -324,6 +325,17 @@ type VersionTarget struct { Link string `json:"link"` Size *int `json:"size,omitempty"` Hash *string `json:"hash,omitempty"` + ID string `json:"id"` +} + +type VirustotalResult struct { + ID *string `json:"id,omitempty"` + Hash string `json:"hash"` + Safe bool `json:"safe"` + FileName string `json:"file_name"` + VersionID string `json:"version_id"` + CreatedAt string `json:"created_at"` + UpdatedAt *string `json:"updated_at,omitempty"` } type AnnouncementImportance string @@ -730,3 +742,52 @@ func (e *VersionStabilities) UnmarshalGQL(v interface{}) error { func (e VersionStabilities) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } + +type VirustotalResultFields string + +const ( + VirustotalResultFieldsID VirustotalResultFields = "id" + VirustotalResultFieldsHash VirustotalResultFields = "hash" + VirustotalResultFieldsSafe VirustotalResultFields = "safe" + VirustotalResultFieldsVersionID VirustotalResultFields = "version_id" + VirustotalResultFieldsCreatedAt VirustotalResultFields = "created_at" + VirustotalResultFieldsUpdatedAt VirustotalResultFields = "updated_at" +) + +var AllVirustotalResultFields = []VirustotalResultFields{ + VirustotalResultFieldsID, + VirustotalResultFieldsHash, + VirustotalResultFieldsSafe, + VirustotalResultFieldsVersionID, + VirustotalResultFieldsCreatedAt, + VirustotalResultFieldsUpdatedAt, +} + +func (e VirustotalResultFields) IsValid() bool { + switch e { + case VirustotalResultFieldsID, VirustotalResultFieldsHash, VirustotalResultFieldsSafe, VirustotalResultFieldsVersionID, VirustotalResultFieldsCreatedAt, VirustotalResultFieldsUpdatedAt: + return true + } + return false +} + +func (e VirustotalResultFields) String() string { + return string(e) +} + +func (e *VirustotalResultFields) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = VirustotalResultFields(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid VirustotalResultFields", str) + } + return nil +} + +func (e VirustotalResultFields) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/gql/resolver_versions.go b/gql/resolver_versions.go index 895c07ca..6ad6fdc3 100644 --- a/gql/resolver_versions.go +++ b/gql/resolver_versions.go @@ -23,6 +23,7 @@ import ( "github.com/satisfactorymodding/smr-api/generated/conv" "github.com/satisfactorymodding/smr-api/generated/ent" "github.com/satisfactorymodding/smr-api/generated/ent/version" + "github.com/satisfactorymodding/smr-api/generated/ent/virustotalresult" "github.com/satisfactorymodding/smr-api/integrations" "github.com/satisfactorymodding/smr-api/models" "github.com/satisfactorymodding/smr-api/redis" @@ -328,6 +329,16 @@ func (r *versionResolver) Mod(ctx context.Context, obj *generated.Version) (*gen return (*conv.ModImpl)(nil).Convert(mod), nil } +func (r *versionResolver) VirustotalResults(ctx context.Context, obj *generated.Version) ([]*generated.VirustotalResult, error) { + query := db.From(ctx).VirustotalResult.Query() + + result, err := query.Where(virustotalresult.VersionID(obj.ID)).All(ctx) + if err != nil { + return nil, err + } + return (*conv.VirustotalResultImpl)(nil).ConvertSlice(result), nil +} + func (r *versionResolver) Hash(_ context.Context, obj *generated.Version) (*string, error) { hash := "" diff --git a/gqlgen.yml b/gqlgen.yml index 7cb5235f..6c7e830e 100755 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -74,6 +74,8 @@ models: resolver: true sml_version: resolver: true + virustotal_results: + resolver: true VersionTarget: fields: diff --git a/migrations/sql/20240924122249_create_mod_virustotal_table.down.sql b/migrations/sql/20240924122249_create_mod_virustotal_table.down.sql new file mode 100644 index 00000000..7bf5023b --- /dev/null +++ b/migrations/sql/20240924122249_create_mod_virustotal_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS virustotal_results; \ No newline at end of file diff --git a/migrations/sql/20240924122249_create_mod_virustotal_table.up.sql b/migrations/sql/20240924122249_create_mod_virustotal_table.up.sql new file mode 100644 index 00000000..81e5f757 --- /dev/null +++ b/migrations/sql/20240924122249_create_mod_virustotal_table.up.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS virustotal_results ( + id varchar(14) NOT NULL, + hash varchar(64) NOT NULL, + safe boolean DEFAULT false, + version_id varchar(14) NOT NULL, + file_name varchar NOT NULL DEFAULT 'foobar'::varchar, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone, + CONSTRAINT virustotal_results_pkey PRIMARY KEY (id), + CONSTRAINT virustotal_results_hash_version_id_key UNIQUE (hash, version_id), + CONSTRAINT virustotal_results_version_id_fkey FOREIGN KEY (version_id) REFERENCES versions (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION NOT VALID +); +CREATE INDEX IF NOT EXISTS virustotal_results_safe_idx ON virustotal_results USING btree (safe ASC NULLS LAST) WITH (deduplicate_items = True); +CREATE INDEX IF NOT EXISTS virustotal_results_hash_idx ON virustotal_results USING btree (hash ASC NULLS LAST) WITH (deduplicate_items = True); \ No newline at end of file diff --git a/migrations/sql/atlas.sum b/migrations/sql/atlas.sum index 4b30de7e..88134066 100644 --- a/migrations/sql/atlas.sum +++ b/migrations/sql/atlas.sum @@ -1,4 +1,4 @@ -h1:2EEkTJ5/cFJukKW9EvHqF3JZQyc3QpeBvHJsZBnAH9U= +h1:eiiJFwkS9I2BVX5adGSdj32yS6gFdu9SU93XBgyuO0s= 000001_create_initial_tables.down.sql h1:QcXXwE8ir3PM3vZjQfBihY55WiuLYjN8pbbk/L6U+bs= 000001_create_initial_tables.up.sql h1:EfAqETefs7TW9BDVS4ukiB7wUFs+HQzVdc3qHhdAFd4= 000002_create_user_group_table.down.sql h1:uJjRbQ3H7yvPGNXLD5iSPmderEoWhCNGdsqN8yqBIRY= @@ -71,3 +71,5 @@ h1:2EEkTJ5/cFJukKW9EvHqF3JZQyc3QpeBvHJsZBnAH9U= 20240823233610_add_mod_toggles.up.sql h1:GuKMUrlGo1PppjX0uiw3OTyi2nziRI+o/LVtWfcjyLc= 20240826153722_add_thumbhash.down.sql h1:FN73gi6XvAkodHxFuE4oDU73FfchoyonlyroQTrwCW0= 20240826153722_add_thumbhash.up.sql h1:7a9d40zpOnKMamxW14ql3WFXiwXD4O6AjwMlAOVE7ik= +20240924122249_create_mod_virustotal_table.down.sql h1:yswdR7UzblErcw3T0eRFZIT+5OCIyV4p5kuSh+jpu80= +20240924122249_create_mod_virustotal_table.up.sql h1:f4Le5wSVX6fPOL3/R5s0CK6RQ972Bw6sI0R6eadO+/4= diff --git a/proto/parser/parser.pb.go b/proto/parser/parser.pb.go index 8e95c2d3..3a8de1ff 100644 --- a/proto/parser/parser.pb.go +++ b/proto/parser/parser.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v4.25.4 +// protoc-gen-go v1.32.0 +// protoc v3.21.12 // source: parser/parser.proto package parser @@ -166,7 +166,7 @@ func file_parser_parser_proto_rawDescGZIP() []byte { } var file_parser_parser_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_parser_parser_proto_goTypes = []any{ +var file_parser_parser_proto_goTypes = []interface{}{ (*ParseRequest)(nil), // 0: ParseRequest (*AssetResponse)(nil), // 1: AssetResponse } @@ -186,7 +186,7 @@ func file_parser_parser_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_parser_parser_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_parser_parser_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ParseRequest); i { case 0: return &v.state @@ -198,7 +198,7 @@ func file_parser_parser_proto_init() { return nil } } - file_parser_parser_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_parser_parser_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AssetResponse); i { case 0: return &v.state diff --git a/proto/parser/parser_grpc.pb.go b/proto/parser/parser_grpc.pb.go index fcdbb7b3..892490c2 100644 --- a/proto/parser/parser_grpc.pb.go +++ b/proto/parser/parser_grpc.pb.go @@ -1,8 +1,4 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.4 -// source: parser/parser.proto package parser @@ -15,13 +11,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 -const ( - Parser_Parse_FullMethodName = "/Parser/Parse" -) - // ParserClient is the client API for Parser service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -38,7 +29,7 @@ func NewParserClient(cc grpc.ClientConnInterface) ParserClient { } func (c *parserClient) Parse(ctx context.Context, in *ParseRequest, opts ...grpc.CallOption) (Parser_ParseClient, error) { - stream, err := c.cc.NewStream(ctx, &Parser_ServiceDesc.Streams[0], Parser_Parse_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &_Parser_serviceDesc.Streams[0], "/Parser/Parse", opts...) if err != nil { return nil, err } @@ -93,8 +84,8 @@ type UnsafeParserServer interface { mustEmbedUnimplementedParserServer() } -func RegisterParserServer(s grpc.ServiceRegistrar, srv ParserServer) { - s.RegisterService(&Parser_ServiceDesc, srv) +func RegisterParserServer(s *grpc.Server, srv ParserServer) { + s.RegisterService(&_Parser_serviceDesc, srv) } func _Parser_Parse_Handler(srv interface{}, stream grpc.ServerStream) error { @@ -118,10 +109,7 @@ func (x *parserParseServer) Send(m *AssetResponse) error { return x.ServerStream.SendMsg(m) } -// Parser_ServiceDesc is the grpc.ServiceDesc for Parser service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var Parser_ServiceDesc = grpc.ServiceDesc{ +var _Parser_serviceDesc = grpc.ServiceDesc{ ServiceName: "Parser", HandlerType: (*ParserServer)(nil), Methods: []grpc.MethodDesc{}, diff --git a/schemas/version.graphql b/schemas/version.graphql index f4e78b46..658dd1fa 100755 --- a/schemas/version.graphql +++ b/schemas/version.graphql @@ -40,6 +40,7 @@ type Version { mod: Mod! dependencies: [VersionDependency!]! + virustotal_results: [VirustotalResult!]! } type VersionTarget { @@ -48,6 +49,7 @@ type VersionTarget { link: String! size: Int hash: String + id: VersionTargetID! } type CreateVersionResponse { @@ -67,7 +69,10 @@ type GetMyVersions { type VersionDependency { version_id: VersionID! - mod_id: ModID! @deprecated(reason: "soon will return actual mod id instead of reference. use mod_reference field instead!") + mod_id: ModID! + @deprecated( + reason: "soon will return actual mod id instead of reference. use mod_reference field instead!" + ) condition: String! optional: Boolean! mod_reference: String! @@ -102,9 +107,14 @@ input UpdateVersion { extend type Query { getVersion(versionId: VersionID!): Version getVersions(filter: VersionFilter): GetVersions! - getUnapprovedVersions(filter: VersionFilter): GetVersions! @canApproveVersions @isLoggedIn + getUnapprovedVersions(filter: VersionFilter): GetVersions! + @canApproveVersions + @isLoggedIn - checkVersionUploadState(modId: ModID!, versionId: VersionID!): CreateVersionResponse @canEditMod(field: "modId") @isLoggedIn + checkVersionUploadState( + modId: ModID! + versionId: VersionID! + ): CreateVersionResponse @canEditMod(field: "modId") @isLoggedIn getMyVersions(filter: VersionFilter): GetMyVersions! @isLoggedIn getMyUnapprovedVersions(filter: VersionFilter): GetMyVersions! @isLoggedIn @@ -113,13 +123,30 @@ extend type Query { ### Mutations extend type Mutation { - createVersion(modId: ModID!): VersionID! @canEditMod(field: "modId") @isLoggedIn - uploadVersionPart(modId: ModID!, versionId: VersionID!, part: Int!, file: Upload!): Boolean! @canEditMod(field: "modId") @isLoggedIn - finalizeCreateVersion(modId: ModID!, versionId: VersionID!, version: NewVersion!): Boolean! @canEditMod(field: "modId") @isLoggedIn - - updateVersion(versionId: VersionID!, version: UpdateVersion!): Version! @canEditVersion(field: "versionId") @isLoggedIn - deleteVersion(versionId: VersionID!): Boolean! @canEditVersion(field: "versionId") @isLoggedIn - - approveVersion(versionId: VersionID!): Boolean! @canApproveVersions @isLoggedIn + createVersion(modId: ModID!): VersionID! + @canEditMod(field: "modId") + @isLoggedIn + uploadVersionPart( + modId: ModID! + versionId: VersionID! + part: Int! + file: Upload! + ): Boolean! @canEditMod(field: "modId") @isLoggedIn + finalizeCreateVersion( + modId: ModID! + versionId: VersionID! + version: NewVersion! + ): Boolean! @canEditMod(field: "modId") @isLoggedIn + + updateVersion(versionId: VersionID!, version: UpdateVersion!): Version! + @canEditVersion(field: "versionId") + @isLoggedIn + deleteVersion(versionId: VersionID!): Boolean! + @canEditVersion(field: "versionId") + @isLoggedIn + + approveVersion(versionId: VersionID!): Boolean! + @canApproveVersions + @isLoggedIn denyVersion(versionId: VersionID!): Boolean! @canApproveVersions @isLoggedIn -} \ No newline at end of file +} diff --git a/schemas/version_target.graphql b/schemas/version_target.graphql index 2d77e3d1..df7c5392 100644 --- a/schemas/version_target.graphql +++ b/schemas/version_target.graphql @@ -1,5 +1,7 @@ +scalar VersionTargetID + enum TargetName { - Windows, - WindowsServer, + Windows + WindowsServer LinuxServer -} \ No newline at end of file +} diff --git a/schemas/virustotal_results.graphql b/schemas/virustotal_results.graphql new file mode 100644 index 00000000..a88d47c2 --- /dev/null +++ b/schemas/virustotal_results.graphql @@ -0,0 +1,23 @@ +### Types + +scalar VirustotalHash +scalar VirustotalID + +type VirustotalResult { + id: VirustotalID + hash: VirustotalHash! + safe: Boolean! + file_name: String! + version_id: String! + created_at: Date! + updated_at: Date +} + +enum VirustotalResultFields { + id + hash + safe + version_id + created_at + updated_at +} diff --git a/validation/virustotal.go b/validation/virustotal.go index fe25eabb..03366312 100644 --- a/validation/virustotal.go +++ b/validation/virustotal.go @@ -2,6 +2,7 @@ package validation import ( "context" + "crypto/sha256" "fmt" "io" "log/slog" @@ -15,6 +16,8 @@ import ( var client *vt.Client +var analysisURL = "https://www.virustotal.com/gui/file/%s" + func InitializeVirusTotal() { client = vt.NewClient(viper.GetString("virustotal.key")) @@ -31,22 +34,42 @@ type AnalysisResults struct { } `json:"stats,omitempty"` Status string `json:"status"` } `json:"attributes,omitempty"` + Meta struct { + FileInfo struct { + SHA256 string `json:"sha256"` + } `json:"file_info"` + } `json:"meta"` +} + +type PreviousAnalysisResults struct { + Attributes struct { + Stats *struct { + Suspicious *int `json:"suspicious,omitempty"` + Malicious *int `json:"malicious,omitempty"` + } `json:"last_analysis_stats,omitempty"` + } `json:"attributes,omitempty"` +} + +type ScanResult struct { + Safe bool + Hash *string + FileName string } -func ScanFiles(ctx context.Context, files []io.Reader, names []string) (bool, error) { +func ScanFiles(ctx context.Context, files []io.Reader, names []string) ([]ScanResult, error) { errs, gctx := errgroup.WithContext(ctx) fileCount := len(files) - c := make(chan bool) + c := make(chan ScanResult) for i := range fileCount { count := i errs.Go(func() error { - ok, err := scanFile(gctx, files[count], names[count]) + scanResult, err := scanFile(gctx, files[count], names[count]) if err != nil { - return fmt.Errorf("failed to scan file: %w", err) + return fmt.Errorf("failed to scan %s: %w", names[count], err) } - c <- ok + c <- *scanResult return nil }) } @@ -54,63 +77,97 @@ func ScanFiles(ctx context.Context, files []io.Reader, names []string) (bool, er _ = errs.Wait() close(c) }() - - success := true + results := make([]ScanResult, 0, 100) for res := range c { - if !res { - success = false - break - } + results = append(results, res) } if err := errs.Wait(); err != nil { - return false, fmt.Errorf("failed to scan file: %w", err) + return nil, fmt.Errorf("failed to scan files: %w", err) } - return success, nil + return results, nil } -func scanFile(ctx context.Context, file io.Reader, name string) (bool, error) { - scan, err := client.NewFileScanner().Scan(file, name, nil) - if err != nil { - return false, fmt.Errorf("failed to scan file: %w", err) +func scanFile(ctx context.Context, file io.Reader, name string) (*ScanResult, error) { + scanResult := ScanResult{ + Safe: false, + FileName: name, } - analysisID := scan.ID() + hash := sha256.New() + if _, err := io.Copy(hash, file); err != nil { + return nil, fmt.Errorf("failed to generate hash for file %w", err) + } - slox.Info(ctx, "uploaded virus scan", slog.String("file", name), slog.String("analysis_id", analysisID)) + checksum := hash.Sum(nil) + var previousAnalysisResults PreviousAnalysisResults - for { - time.Sleep(time.Second * 15) + _, err := client.GetData(vt.URL("files/%x", checksum), &previousAnalysisResults) - var target AnalysisResults - _, err = client.GetData(vt.URL("analyses/%s", analysisID), &target) + alreadyScanned := false + analysisID := "" + + if err == nil { + alreadyScanned = true + slox.Info(ctx, "file already scanned, skipping upload", slog.String("file", name)) + hash := fmt.Sprintf("%x", checksum) + scanResult.Hash = &hash + } else { + scan, err := client.NewFileScanner().Scan(file, name, nil) if err != nil { - return false, fmt.Errorf("failed to get analysis results: %w", err) + return &scanResult, fmt.Errorf("failed to scan file: %w", err) } + analysisID := scan.ID() + slox.Info(ctx, "uploaded virus scan", slog.String("file", name), slog.String("analysis_id", analysisID)) + } - if target.Attributes.Status != "completed" { - continue - } + for { + var analysisResults AnalysisResults + var malicious int + var suspicious int - if target.Attributes.Stats == nil { - slox.Error(ctx, "no stats available", slog.Any("err", err), slog.String("file", name)) - return false, nil - } + if !alreadyScanned { + time.Sleep(time.Second * 15) - if target.Attributes.Stats.Malicious == nil || target.Attributes.Stats.Suspicious == nil { - slox.Error(ctx, "unable to determine malicious or suspicious file", slog.Any("err", err), slog.String("file", name)) - return false, nil + _, err = client.GetData(vt.URL("analyses/%s", analysisID), &analysisResults) + if err != nil { + scanResult.Safe = false + return nil, fmt.Errorf("failed to get analysis results: %w", err) + } + scanResult.Hash = &analysisResults.Meta.FileInfo.SHA256 + + if !alreadyScanned && analysisResults.Attributes.Status != "completed" { + continue + } + + if analysisResults.Attributes.Stats == nil { + slox.Error(ctx, "no stats available", slog.Any("err", err), slog.String("file", name)) + scanResult.Safe = false + return &scanResult, nil + } + + if analysisResults.Attributes.Stats.Malicious == nil || analysisResults.Attributes.Stats.Suspicious == nil { + slox.Error(ctx, "unable to determine malicious or suspicious file", slog.Any("err", err), slog.String("file", name)) + scanResult.Safe = false + return &scanResult, nil + } + malicious = *analysisResults.Attributes.Stats.Malicious + suspicious = *analysisResults.Attributes.Stats.Suspicious + } else { + malicious = *previousAnalysisResults.Attributes.Stats.Malicious + suspicious = *previousAnalysisResults.Attributes.Stats.Suspicious } // Why 1? Well because some company made a shitty AI and it flags random mods. - if *target.Attributes.Stats.Malicious > 1 || *target.Attributes.Stats.Suspicious > 1 { + if malicious > 1 || suspicious > 1 { slox.Error(ctx, "suspicious or malicious file found", slog.Any("err", err), slog.String("file", name)) - return false, nil + scanResult.Safe = false + return &scanResult, nil } break } - return true, nil + return &scanResult, nil } diff --git a/workflows/versionupload/scan_mod_on_virus_total.go b/workflows/versionupload/scan_mod_on_virus_total.go index 61c06c27..d06fc507 100644 --- a/workflows/versionupload/scan_mod_on_virus_total.go +++ b/workflows/versionupload/scan_mod_on_virus_total.go @@ -15,6 +15,7 @@ import ( "go.opentelemetry.io/otel/codes" "github.com/satisfactorymodding/smr-api/db" + "github.com/satisfactorymodding/smr-api/generated/ent" "github.com/satisfactorymodding/smr-api/storage" "github.com/satisfactorymodding/smr-api/validation" ) @@ -70,7 +71,30 @@ func (*A) ScanModOnVirusTotalActivity(ctx context.Context, args ScanModOnVirusTo } } - success, err := validation.ScanFiles(ctx, toScan, names) + scanResults, err := validation.ScanFiles(ctx, toScan, names) + if err != nil { + span.SetStatus(codes.Error, err.Error()) + span.RecordError(err) + return false, err + } + + success := true + + for _, scanResult := range scanResults { + if !scanResult.Safe { + success = false + slox.Warn(ctx, "mod failed to pass virus scan", slog.String("mod", args.ModID), slog.String("version", args.VersionID)) + } + } + _, err = db.From(ctx).VirustotalResult.MapCreateBulk(scanResults, + func(c *ent.VirustotalResultCreate, i int) { + c.SetSafe(scanResults[i].Safe). + SetVersionID(args.VersionID). + SetFileName(scanResults[i].FileName). + OnConflict(). + DoNothing() + }, + ).Save(ctx) if err != nil { span.SetStatus(codes.Error, err.Error()) span.RecordError(err) @@ -78,7 +102,6 @@ func (*A) ScanModOnVirusTotalActivity(ctx context.Context, args ScanModOnVirusTo } if !success { - slox.Warn(ctx, "mod failed to pass virus scan", slog.String("mod", args.ModID), slog.String("version", args.VersionID)) return false, nil }