From e98f6d4943c3e9913bb56088b037f11c8de85363 Mon Sep 17 00:00:00 2001 From: Jonathan Howard Date: Thu, 16 Jan 2025 12:08:27 -0600 Subject: [PATCH] refactor: embed UUIDMixin into ProtoMessageMixin, auto-generate UUID fields Signed-off-by: Jonathan Howard --- backends/ent/backend.go | 6 +- backends/ent/store.go | 39 +- go.mod | 2 +- go.sum | 4 +- internal/backends/ent/client.go | 30 +- .../backends/ent/documenttype/documenttype.go | 7 + internal/backends/ent/documenttype_create.go | 13 +- internal/backends/ent/edgetype/edgetype.go | 7 + internal/backends/ent/edgetype_create.go | 13 +- internal/backends/ent/entc.go | 1 + .../externalreference/externalreference.go | 7 + .../backends/ent/externalreference_create.go | 13 +- internal/backends/ent/intercept/intercept.go | 574 ++++++++++++++++++ internal/backends/ent/metadata/metadata.go | 7 + internal/backends/ent/metadata_create.go | 10 +- .../20250116180706_embed_uuid_mixin.sql | 20 + .../backends/ent/migrate/migrations/atlas.sum | 3 +- internal/backends/ent/migrate/schema.go | 20 +- internal/backends/ent/node/node.go | 7 + internal/backends/ent/node_create.go | 15 +- internal/backends/ent/node_update.go | 12 +- internal/backends/ent/nodelist/nodelist.go | 7 + internal/backends/ent/nodelist_create.go | 10 +- internal/backends/ent/person/person.go | 7 + internal/backends/ent/person_create.go | 13 +- internal/backends/ent/property/property.go | 7 + internal/backends/ent/property_create.go | 13 +- internal/backends/ent/runtime.go | 226 +------ internal/backends/ent/runtime/runtime.go | 246 +++++++- internal/backends/ent/schema/document_type.go | 1 - internal/backends/ent/schema/edge_type.go | 1 - .../backends/ent/schema/external_reference.go | 1 - internal/backends/ent/schema/metadata.go | 1 - internal/backends/ent/schema/mixin.go | 62 +- internal/backends/ent/schema/node.go | 1 - internal/backends/ent/schema/node_list.go | 1 - internal/backends/ent/schema/person.go | 1 - internal/backends/ent/schema/property.go | 1 - internal/backends/ent/schema/source_data.go | 1 - internal/backends/ent/schema/tool.go | 1 - .../backends/ent/sourcedata/sourcedata.go | 7 + internal/backends/ent/sourcedata_create.go | 13 +- internal/backends/ent/tool/tool.go | 7 + internal/backends/ent/tool_create.go | 13 +- 44 files changed, 1121 insertions(+), 330 deletions(-) create mode 100644 internal/backends/ent/intercept/intercept.go create mode 100644 internal/backends/ent/migrate/migrations/20250116180706_embed_uuid_mixin.sql diff --git a/backends/ent/backend.go b/backends/ent/backend.go index f85f79e..e784dcc 100644 --- a/backends/ent/backend.go +++ b/backends/ent/backend.go @@ -12,12 +12,14 @@ import ( "fmt" "slices" + "entgo.io/ent/dialect" "entgo.io/ent/dialect/sql/schema" sqlite "github.com/glebarez/go-sqlite" "github.com/protobom/protobom/pkg/storage" "github.com/protobom/storage/internal/backends/ent" "github.com/protobom/storage/internal/backends/ent/migrate" + _ "github.com/protobom/storage/internal/backends/ent/runtime" // Prevents circular imports in generated code ) // Backend implements the protobom.pkg.storage.Backend interface. @@ -53,7 +55,7 @@ func (backend *Backend) InitClient() error { } // Register the SQLite driver as "sqlite3". - if !slices.Contains(sql.Drivers(), "sqlite3") { + if !slices.Contains(sql.Drivers(), dialect.SQLite) { sqlite.RegisterAsSQLITE3() } @@ -62,7 +64,7 @@ func (backend *Backend) InitClient() error { clientOpts = append(clientOpts, ent.Debug()) } - client, err := ent.Open("sqlite3", backend.Options.DatabaseFile+dsnParams, clientOpts...) + client, err := ent.Open(dialect.SQLite, backend.Options.DatabaseFile+dsnParams, clientOpts...) if err != nil { return fmt.Errorf("failed opening connection to sqlite: %w", err) } diff --git a/backends/ent/store.go b/backends/ent/store.go index ed361de..1059d64 100644 --- a/backends/ent/store.go +++ b/backends/ent/store.go @@ -120,15 +120,9 @@ func (backend *Backend) saveAnnotations(annotations ...*ent.Annotation) TxFunc { func (backend *Backend) saveDocumentTypes(docTypes []*sbom.DocumentType) TxFunc { return func(tx *ent.Tx) error { for _, docType := range docTypes { - id, err := GenerateUUID(docType) - if err != nil { - return err - } - typeName := documenttype.Type(docType.GetType().String()) newDocType := tx.DocumentType.Create(). - SetID(id). SetProtoMessage(docType). SetNillableType(&typeName). SetNillableName(docType.Name). //nolint:protogetter @@ -154,14 +148,8 @@ func (backend *Backend) saveEdges(edges []*sbom.Edge) TxFunc { //nolint:gocognit } for _, edge := range edges { - edgeID, err := GenerateUUID(edge) - if err != nil { - return fmt.Errorf("generating UUID: %w", err) - } - for _, toID := range edge.GetTo() { newEdgeType := tx.EdgeType.Create(). - SetID(edgeID). SetProtoMessage(edge). SetType(edgetype.Type(edge.GetType().String())). SetFromID(nativeIDMap[edge.GetFrom()]). @@ -195,7 +183,6 @@ func (backend *Backend) saveExternalReferences(refs []*sbom.ExternalReference, o } newRef := tx.ExternalReference.Create(). - SetID(extRefID). SetProtoMessage(ref). SetURL(ref.GetUrl()). SetComment(ref.GetComment()). @@ -296,14 +283,13 @@ func (backend *Backend) saveIdentifiers(idents map[int32]string, opts ...func(*e } func (backend *Backend) saveMetadata(metadata *sbom.Metadata) TxFunc { - mdUUID, err := GenerateUUID(metadata) + id, err := GenerateUUID(metadata) if err != nil { return nil } return func(tx *ent.Tx) error { newMetadata := tx.Metadata.Create(). - SetID(mdUUID). SetNativeID(metadata.GetId()). SetProtoMessage(metadata). SetVersion(metadata.GetVersion()). @@ -317,7 +303,7 @@ func (backend *Backend) saveMetadata(metadata *sbom.Metadata) TxFunc { return fmt.Errorf("saving metadata: %w", err) } - backend.ctx = context.WithValue(backend.ctx, metadataIDKey{}, mdUUID) + backend.ctx = context.WithValue(backend.ctx, metadataIDKey{}, id) for _, fn := range []TxFunc{ backend.savePersons(metadata.GetAuthors()), @@ -342,7 +328,6 @@ func (backend *Backend) saveNodeList(nodeList *sbom.NodeList) TxFunc { } newNodeList := tx.NodeList.Create(). - SetID(id). SetProtoMessage(nodeList). SetRootElements(nodeList.GetRootElements()) @@ -383,7 +368,6 @@ func (backend *Backend) saveNodes(nodes []*sbom.Node) TxFunc { //nolint:funlen,g backend.ctx = context.WithValue(backend.ctx, nodeIDKey{}, nodeID) newNode := tx.Node.Create(). - SetID(nodeID). SetNativeID(srcNode.GetId()). SetProtoMessage(srcNode). SetAttribution(srcNode.GetAttribution()). @@ -459,7 +443,6 @@ func (backend *Backend) savePersons(persons []*sbom.Person) TxFunc { //nolint:go } newPerson := tx.Person.Create(). - SetID(id). SetProtoMessage(person). SetName(person.GetName()). SetEmail(person.GetEmail()). @@ -496,13 +479,7 @@ func (backend *Backend) saveProperties(properties []*sbom.Property, nodeID uuid. builders := []*ent.PropertyCreate{} for _, prop := range properties { - id, err := GenerateUUID(prop) - if err != nil { - return err - } - newProp := tx.Property.Create(). - SetID(id). SetProtoMessage(prop). SetNodeID(nodeID). SetName(prop.GetName()). @@ -554,13 +531,7 @@ func (backend *Backend) savePurposes(purposes []sbom.Purpose, nodeID uuid.UUID) func (backend *Backend) saveSourceData(sourceData *sbom.SourceData) TxFunc { return func(tx *ent.Tx) error { - id, err := GenerateUUID(sourceData) - if err != nil { - return err - } - newSourceData := tx.SourceData.Create(). - SetID(id). SetProtoMessage(sourceData). SetFormat(sourceData.GetFormat()). SetHashes(sourceData.GetHashes()). @@ -583,13 +554,7 @@ func (backend *Backend) saveTools(tools []*sbom.Tool) TxFunc { builders := []*ent.ToolCreate{} for _, tool := range tools { - id, err := GenerateUUID(tool) - if err != nil { - return err - } - newTool := tx.Tool.Create(). - SetID(id). SetProtoMessage(tool). SetName(tool.GetName()). SetVersion(tool.GetVersion()). diff --git a/go.mod b/go.mod index 4416438..b8b8e81 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/google/uuid v1.6.0 github.com/protobom/protobom v0.5.0 github.com/stretchr/testify v1.10.0 - google.golang.org/protobuf v1.36.2 + google.golang.org/protobuf v1.36.1 ) require ( diff --git a/go.sum b/go.sum index e1eb2f8..87298ec 100644 --- a/go.sum +++ b/go.sum @@ -110,8 +110,8 @@ golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU= -google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/backends/ent/client.go b/internal/backends/ent/client.go index 9f71707..8d6ecea 100644 --- a/internal/backends/ent/client.go +++ b/internal/backends/ent/client.go @@ -817,7 +817,8 @@ func (c *DocumentTypeClient) QueryMetadata(dt *DocumentType) *MetadataQuery { // Hooks returns the client hooks. func (c *DocumentTypeClient) Hooks() []Hook { - return c.hooks.DocumentType + hooks := c.hooks.DocumentType + return append(hooks[:len(hooks):len(hooks)], documenttype.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -1014,7 +1015,8 @@ func (c *EdgeTypeClient) QueryNodeLists(et *EdgeType) *NodeListQuery { // Hooks returns the client hooks. func (c *EdgeTypeClient) Hooks() []Hook { - return c.hooks.EdgeType + hooks := c.hooks.EdgeType + return append(hooks[:len(hooks):len(hooks)], edgetype.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -1195,7 +1197,8 @@ func (c *ExternalReferenceClient) QueryNodes(er *ExternalReference) *NodeQuery { // Hooks returns the client hooks. func (c *ExternalReferenceClient) Hooks() []Hook { - return c.hooks.ExternalReference + hooks := c.hooks.ExternalReference + return append(hooks[:len(hooks):len(hooks)], externalreference.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -1754,7 +1757,8 @@ func (c *MetadataClient) QuerySourceData(m *Metadata) *SourceDataQuery { // Hooks returns the client hooks. func (c *MetadataClient) Hooks() []Hook { - return c.hooks.Metadata + hooks := c.hooks.Metadata + return append(hooks[:len(hooks):len(hooks)], metadata.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -2095,7 +2099,8 @@ func (c *NodeClient) QueryEdgeTypes(n *Node) *EdgeTypeQuery { // Hooks returns the client hooks. func (c *NodeClient) Hooks() []Hook { - return c.hooks.Node + hooks := c.hooks.Node + return append(hooks[:len(hooks):len(hooks)], node.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -2276,7 +2281,8 @@ func (c *NodeListClient) QueryNodes(nl *NodeList) *NodeQuery { // Hooks returns the client hooks. func (c *NodeListClient) Hooks() []Hook { - return c.hooks.NodeList + hooks := c.hooks.NodeList + return append(hooks[:len(hooks):len(hooks)], nodelist.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -2489,7 +2495,8 @@ func (c *PersonClient) QueryNode(pe *Person) *NodeQuery { // Hooks returns the client hooks. func (c *PersonClient) Hooks() []Hook { - return c.hooks.Person + hooks := c.hooks.Person + return append(hooks[:len(hooks):len(hooks)], person.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -2654,7 +2661,8 @@ func (c *PropertyClient) QueryNode(pr *Property) *NodeQuery { // Hooks returns the client hooks. func (c *PropertyClient) Hooks() []Hook { - return c.hooks.Property + hooks := c.hooks.Property + return append(hooks[:len(hooks):len(hooks)], property.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -2984,7 +2992,8 @@ func (c *SourceDataClient) QueryMetadata(sd *SourceData) *MetadataQuery { // Hooks returns the client hooks. func (c *SourceDataClient) Hooks() []Hook { - return c.hooks.SourceData + hooks := c.hooks.SourceData + return append(hooks[:len(hooks):len(hooks)], sourcedata.Hooks[:]...) } // Interceptors returns the client interceptors. @@ -3149,7 +3158,8 @@ func (c *ToolClient) QueryMetadata(t *Tool) *MetadataQuery { // Hooks returns the client hooks. func (c *ToolClient) Hooks() []Hook { - return c.hooks.Tool + hooks := c.hooks.Tool + return append(hooks[:len(hooks):len(hooks)], tool.Hooks[:]...) } // Interceptors returns the client interceptors. diff --git a/internal/backends/ent/documenttype/documenttype.go b/internal/backends/ent/documenttype/documenttype.go index 8606313..6211ad8 100644 --- a/internal/backends/ent/documenttype/documenttype.go +++ b/internal/backends/ent/documenttype/documenttype.go @@ -10,6 +10,7 @@ package documenttype import ( "fmt" + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -75,7 +76,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/documenttype_create.go b/internal/backends/ent/documenttype_create.go index 6c54684..50d2e24 100644 --- a/internal/backends/ent/documenttype_create.go +++ b/internal/backends/ent/documenttype_create.go @@ -138,7 +138,9 @@ func (dtc *DocumentTypeCreate) Mutation() *DocumentTypeMutation { // Save creates the DocumentType in the database. func (dtc *DocumentTypeCreate) Save(ctx context.Context) (*DocumentType, error) { - dtc.defaults() + if err := dtc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, dtc.sqlSave, dtc.mutation, dtc.hooks) } @@ -165,15 +167,22 @@ func (dtc *DocumentTypeCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (dtc *DocumentTypeCreate) defaults() { +func (dtc *DocumentTypeCreate) defaults() error { if _, ok := dtc.mutation.DocumentID(); !ok { + if documenttype.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized documenttype.DefaultDocumentID (forgotten import ent/runtime?)") + } v := documenttype.DefaultDocumentID() dtc.mutation.SetDocumentID(v) } if _, ok := dtc.mutation.ID(); !ok { + if documenttype.DefaultID == nil { + return fmt.Errorf("ent: uninitialized documenttype.DefaultID (forgotten import ent/runtime?)") + } v := documenttype.DefaultID() dtc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/edgetype/edgetype.go b/internal/backends/ent/edgetype/edgetype.go index 6d37400..906bac9 100644 --- a/internal/backends/ent/edgetype/edgetype.go +++ b/internal/backends/ent/edgetype/edgetype.go @@ -10,6 +10,7 @@ package edgetype import ( "fmt" + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -94,7 +95,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/edgetype_create.go b/internal/backends/ent/edgetype_create.go index 34ac647..4184658 100644 --- a/internal/backends/ent/edgetype_create.go +++ b/internal/backends/ent/edgetype_create.go @@ -133,7 +133,9 @@ func (etc *EdgeTypeCreate) Mutation() *EdgeTypeMutation { // Save creates the EdgeType in the database. func (etc *EdgeTypeCreate) Save(ctx context.Context) (*EdgeType, error) { - etc.defaults() + if err := etc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, etc.sqlSave, etc.mutation, etc.hooks) } @@ -160,15 +162,22 @@ func (etc *EdgeTypeCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (etc *EdgeTypeCreate) defaults() { +func (etc *EdgeTypeCreate) defaults() error { if _, ok := etc.mutation.DocumentID(); !ok { + if edgetype.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized edgetype.DefaultDocumentID (forgotten import ent/runtime?)") + } v := edgetype.DefaultDocumentID() etc.mutation.SetDocumentID(v) } if _, ok := etc.mutation.ID(); !ok { + if edgetype.DefaultID == nil { + return fmt.Errorf("ent: uninitialized edgetype.DefaultID (forgotten import ent/runtime?)") + } v := edgetype.DefaultID() etc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/entc.go b/internal/backends/ent/entc.go index a6b02e2..971e36a 100644 --- a/internal/backends/ent/entc.go +++ b/internal/backends/ent/entc.go @@ -23,6 +23,7 @@ func main() { if err := entc.Generate("./schema", &gen.Config{ Features: []gen.Feature{ gen.FeatureExecQuery, + gen.FeatureIntercept, gen.FeatureUpsert, gen.FeatureVersionedMigration, }, diff --git a/internal/backends/ent/externalreference/externalreference.go b/internal/backends/ent/externalreference/externalreference.go index 4bc7c10..4653be1 100644 --- a/internal/backends/ent/externalreference/externalreference.go +++ b/internal/backends/ent/externalreference/externalreference.go @@ -10,6 +10,7 @@ package externalreference import ( "fmt" + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -89,7 +90,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/externalreference_create.go b/internal/backends/ent/externalreference_create.go index b2d838b..c64ba12 100644 --- a/internal/backends/ent/externalreference_create.go +++ b/internal/backends/ent/externalreference_create.go @@ -140,7 +140,9 @@ func (erc *ExternalReferenceCreate) Mutation() *ExternalReferenceMutation { // Save creates the ExternalReference in the database. func (erc *ExternalReferenceCreate) Save(ctx context.Context) (*ExternalReference, error) { - erc.defaults() + if err := erc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, erc.sqlSave, erc.mutation, erc.hooks) } @@ -167,15 +169,22 @@ func (erc *ExternalReferenceCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (erc *ExternalReferenceCreate) defaults() { +func (erc *ExternalReferenceCreate) defaults() error { if _, ok := erc.mutation.DocumentID(); !ok { + if externalreference.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized externalreference.DefaultDocumentID (forgotten import ent/runtime?)") + } v := externalreference.DefaultDocumentID() erc.mutation.SetDocumentID(v) } if _, ok := erc.mutation.ID(); !ok { + if externalreference.DefaultID == nil { + return fmt.Errorf("ent: uninitialized externalreference.DefaultID (forgotten import ent/runtime?)") + } v := externalreference.DefaultID() erc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/intercept/intercept.go b/internal/backends/ent/intercept/intercept.go new file mode 100644 index 0000000..12e5f39 --- /dev/null +++ b/internal/backends/ent/intercept/intercept.go @@ -0,0 +1,574 @@ +// Code generated by ent, DO NOT EDIT. +// -------------------------------------------------------------- +// SPDX-FileCopyrightText: Copyright © 2024 The Protobom Authors +// SPDX-FileType: SOURCE +// SPDX-License-Identifier: Apache-2.0 +// -------------------------------------------------------------- + +package intercept + +import ( + "context" + "fmt" + + "entgo.io/ent/dialect/sql" + "github.com/protobom/storage/internal/backends/ent" + "github.com/protobom/storage/internal/backends/ent/annotation" + "github.com/protobom/storage/internal/backends/ent/document" + "github.com/protobom/storage/internal/backends/ent/documenttype" + "github.com/protobom/storage/internal/backends/ent/edgetype" + "github.com/protobom/storage/internal/backends/ent/externalreference" + "github.com/protobom/storage/internal/backends/ent/hashesentry" + "github.com/protobom/storage/internal/backends/ent/identifiersentry" + "github.com/protobom/storage/internal/backends/ent/metadata" + "github.com/protobom/storage/internal/backends/ent/node" + "github.com/protobom/storage/internal/backends/ent/nodelist" + "github.com/protobom/storage/internal/backends/ent/person" + "github.com/protobom/storage/internal/backends/ent/predicate" + "github.com/protobom/storage/internal/backends/ent/property" + "github.com/protobom/storage/internal/backends/ent/purpose" + "github.com/protobom/storage/internal/backends/ent/sourcedata" + "github.com/protobom/storage/internal/backends/ent/tool" +) + +// The Query interface represents an operation that queries a graph. +// By using this interface, users can write generic code that manipulates +// query builders of different types. +type Query interface { + // Type returns the string representation of the query type. + Type() string + // Limit the number of records to be returned by this query. + Limit(int) + // Offset to start from. + Offset(int) + // Unique configures the query builder to filter duplicate records. + Unique(bool) + // Order specifies how the records should be ordered. + Order(...func(*sql.Selector)) + // WhereP appends storage-level predicates to the query builder. Using this method, users + // can use type-assertion to append predicates that do not depend on any generated package. + WhereP(...func(*sql.Selector)) +} + +// The Func type is an adapter that allows ordinary functions to be used as interceptors. +// Unlike traversal functions, interceptors are skipped during graph traversals. Note that the +// implementation of Func is different from the one defined in entgo.io/ent.InterceptFunc. +type Func func(context.Context, Query) error + +// Intercept calls f(ctx, q) and then applied the next Querier. +func (f Func) Intercept(next ent.Querier) ent.Querier { + return ent.QuerierFunc(func(ctx context.Context, q ent.Query) (ent.Value, error) { + query, err := NewQuery(q) + if err != nil { + return nil, err + } + if err := f(ctx, query); err != nil { + return nil, err + } + return next.Query(ctx, q) + }) +} + +// The TraverseFunc type is an adapter to allow the use of ordinary function as Traverser. +// If f is a function with the appropriate signature, TraverseFunc(f) is a Traverser that calls f. +type TraverseFunc func(context.Context, Query) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseFunc) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseFunc) Traverse(ctx context.Context, q ent.Query) error { + query, err := NewQuery(q) + if err != nil { + return err + } + return f(ctx, query) +} + +// The AnnotationFunc type is an adapter to allow the use of ordinary function as a Querier. +type AnnotationFunc func(context.Context, *ent.AnnotationQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f AnnotationFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.AnnotationQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.AnnotationQuery", q) +} + +// The TraverseAnnotation type is an adapter to allow the use of ordinary function as Traverser. +type TraverseAnnotation func(context.Context, *ent.AnnotationQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseAnnotation) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseAnnotation) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.AnnotationQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.AnnotationQuery", q) +} + +// The DocumentFunc type is an adapter to allow the use of ordinary function as a Querier. +type DocumentFunc func(context.Context, *ent.DocumentQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f DocumentFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.DocumentQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.DocumentQuery", q) +} + +// The TraverseDocument type is an adapter to allow the use of ordinary function as Traverser. +type TraverseDocument func(context.Context, *ent.DocumentQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseDocument) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseDocument) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.DocumentQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.DocumentQuery", q) +} + +// The DocumentTypeFunc type is an adapter to allow the use of ordinary function as a Querier. +type DocumentTypeFunc func(context.Context, *ent.DocumentTypeQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f DocumentTypeFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.DocumentTypeQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.DocumentTypeQuery", q) +} + +// The TraverseDocumentType type is an adapter to allow the use of ordinary function as Traverser. +type TraverseDocumentType func(context.Context, *ent.DocumentTypeQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseDocumentType) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseDocumentType) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.DocumentTypeQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.DocumentTypeQuery", q) +} + +// The EdgeTypeFunc type is an adapter to allow the use of ordinary function as a Querier. +type EdgeTypeFunc func(context.Context, *ent.EdgeTypeQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f EdgeTypeFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.EdgeTypeQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.EdgeTypeQuery", q) +} + +// The TraverseEdgeType type is an adapter to allow the use of ordinary function as Traverser. +type TraverseEdgeType func(context.Context, *ent.EdgeTypeQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseEdgeType) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseEdgeType) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.EdgeTypeQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.EdgeTypeQuery", q) +} + +// The ExternalReferenceFunc type is an adapter to allow the use of ordinary function as a Querier. +type ExternalReferenceFunc func(context.Context, *ent.ExternalReferenceQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f ExternalReferenceFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.ExternalReferenceQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.ExternalReferenceQuery", q) +} + +// The TraverseExternalReference type is an adapter to allow the use of ordinary function as Traverser. +type TraverseExternalReference func(context.Context, *ent.ExternalReferenceQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseExternalReference) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseExternalReference) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ExternalReferenceQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.ExternalReferenceQuery", q) +} + +// The HashesEntryFunc type is an adapter to allow the use of ordinary function as a Querier. +type HashesEntryFunc func(context.Context, *ent.HashesEntryQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f HashesEntryFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.HashesEntryQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.HashesEntryQuery", q) +} + +// The TraverseHashesEntry type is an adapter to allow the use of ordinary function as Traverser. +type TraverseHashesEntry func(context.Context, *ent.HashesEntryQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseHashesEntry) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseHashesEntry) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.HashesEntryQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.HashesEntryQuery", q) +} + +// The IdentifiersEntryFunc type is an adapter to allow the use of ordinary function as a Querier. +type IdentifiersEntryFunc func(context.Context, *ent.IdentifiersEntryQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f IdentifiersEntryFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.IdentifiersEntryQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.IdentifiersEntryQuery", q) +} + +// The TraverseIdentifiersEntry type is an adapter to allow the use of ordinary function as Traverser. +type TraverseIdentifiersEntry func(context.Context, *ent.IdentifiersEntryQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseIdentifiersEntry) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseIdentifiersEntry) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.IdentifiersEntryQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.IdentifiersEntryQuery", q) +} + +// The MetadataFunc type is an adapter to allow the use of ordinary function as a Querier. +type MetadataFunc func(context.Context, *ent.MetadataQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f MetadataFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.MetadataQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.MetadataQuery", q) +} + +// The TraverseMetadata type is an adapter to allow the use of ordinary function as Traverser. +type TraverseMetadata func(context.Context, *ent.MetadataQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseMetadata) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseMetadata) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.MetadataQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.MetadataQuery", q) +} + +// The NodeFunc type is an adapter to allow the use of ordinary function as a Querier. +type NodeFunc func(context.Context, *ent.NodeQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f NodeFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.NodeQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.NodeQuery", q) +} + +// The TraverseNode type is an adapter to allow the use of ordinary function as Traverser. +type TraverseNode func(context.Context, *ent.NodeQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseNode) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseNode) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.NodeQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.NodeQuery", q) +} + +// The NodeListFunc type is an adapter to allow the use of ordinary function as a Querier. +type NodeListFunc func(context.Context, *ent.NodeListQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f NodeListFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.NodeListQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.NodeListQuery", q) +} + +// The TraverseNodeList type is an adapter to allow the use of ordinary function as Traverser. +type TraverseNodeList func(context.Context, *ent.NodeListQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseNodeList) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseNodeList) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.NodeListQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.NodeListQuery", q) +} + +// The PersonFunc type is an adapter to allow the use of ordinary function as a Querier. +type PersonFunc func(context.Context, *ent.PersonQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f PersonFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.PersonQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.PersonQuery", q) +} + +// The TraversePerson type is an adapter to allow the use of ordinary function as Traverser. +type TraversePerson func(context.Context, *ent.PersonQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraversePerson) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraversePerson) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.PersonQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.PersonQuery", q) +} + +// The PropertyFunc type is an adapter to allow the use of ordinary function as a Querier. +type PropertyFunc func(context.Context, *ent.PropertyQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f PropertyFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.PropertyQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.PropertyQuery", q) +} + +// The TraverseProperty type is an adapter to allow the use of ordinary function as Traverser. +type TraverseProperty func(context.Context, *ent.PropertyQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseProperty) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseProperty) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.PropertyQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.PropertyQuery", q) +} + +// The PurposeFunc type is an adapter to allow the use of ordinary function as a Querier. +type PurposeFunc func(context.Context, *ent.PurposeQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f PurposeFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.PurposeQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.PurposeQuery", q) +} + +// The TraversePurpose type is an adapter to allow the use of ordinary function as Traverser. +type TraversePurpose func(context.Context, *ent.PurposeQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraversePurpose) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraversePurpose) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.PurposeQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.PurposeQuery", q) +} + +// The SourceDataFunc type is an adapter to allow the use of ordinary function as a Querier. +type SourceDataFunc func(context.Context, *ent.SourceDataQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f SourceDataFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.SourceDataQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.SourceDataQuery", q) +} + +// The TraverseSourceData type is an adapter to allow the use of ordinary function as Traverser. +type TraverseSourceData func(context.Context, *ent.SourceDataQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseSourceData) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseSourceData) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.SourceDataQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.SourceDataQuery", q) +} + +// The ToolFunc type is an adapter to allow the use of ordinary function as a Querier. +type ToolFunc func(context.Context, *ent.ToolQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f ToolFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.ToolQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.ToolQuery", q) +} + +// The TraverseTool type is an adapter to allow the use of ordinary function as Traverser. +type TraverseTool func(context.Context, *ent.ToolQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseTool) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseTool) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ToolQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.ToolQuery", q) +} + +// NewQuery returns the generic Query interface for the given typed query. +func NewQuery(q ent.Query) (Query, error) { + switch q := q.(type) { + case *ent.AnnotationQuery: + return &query[*ent.AnnotationQuery, predicate.Annotation, annotation.OrderOption]{typ: ent.TypeAnnotation, tq: q}, nil + case *ent.DocumentQuery: + return &query[*ent.DocumentQuery, predicate.Document, document.OrderOption]{typ: ent.TypeDocument, tq: q}, nil + case *ent.DocumentTypeQuery: + return &query[*ent.DocumentTypeQuery, predicate.DocumentType, documenttype.OrderOption]{typ: ent.TypeDocumentType, tq: q}, nil + case *ent.EdgeTypeQuery: + return &query[*ent.EdgeTypeQuery, predicate.EdgeType, edgetype.OrderOption]{typ: ent.TypeEdgeType, tq: q}, nil + case *ent.ExternalReferenceQuery: + return &query[*ent.ExternalReferenceQuery, predicate.ExternalReference, externalreference.OrderOption]{typ: ent.TypeExternalReference, tq: q}, nil + case *ent.HashesEntryQuery: + return &query[*ent.HashesEntryQuery, predicate.HashesEntry, hashesentry.OrderOption]{typ: ent.TypeHashesEntry, tq: q}, nil + case *ent.IdentifiersEntryQuery: + return &query[*ent.IdentifiersEntryQuery, predicate.IdentifiersEntry, identifiersentry.OrderOption]{typ: ent.TypeIdentifiersEntry, tq: q}, nil + case *ent.MetadataQuery: + return &query[*ent.MetadataQuery, predicate.Metadata, metadata.OrderOption]{typ: ent.TypeMetadata, tq: q}, nil + case *ent.NodeQuery: + return &query[*ent.NodeQuery, predicate.Node, node.OrderOption]{typ: ent.TypeNode, tq: q}, nil + case *ent.NodeListQuery: + return &query[*ent.NodeListQuery, predicate.NodeList, nodelist.OrderOption]{typ: ent.TypeNodeList, tq: q}, nil + case *ent.PersonQuery: + return &query[*ent.PersonQuery, predicate.Person, person.OrderOption]{typ: ent.TypePerson, tq: q}, nil + case *ent.PropertyQuery: + return &query[*ent.PropertyQuery, predicate.Property, property.OrderOption]{typ: ent.TypeProperty, tq: q}, nil + case *ent.PurposeQuery: + return &query[*ent.PurposeQuery, predicate.Purpose, purpose.OrderOption]{typ: ent.TypePurpose, tq: q}, nil + case *ent.SourceDataQuery: + return &query[*ent.SourceDataQuery, predicate.SourceData, sourcedata.OrderOption]{typ: ent.TypeSourceData, tq: q}, nil + case *ent.ToolQuery: + return &query[*ent.ToolQuery, predicate.Tool, tool.OrderOption]{typ: ent.TypeTool, tq: q}, nil + default: + return nil, fmt.Errorf("unknown query type %T", q) + } +} + +type query[T any, P ~func(*sql.Selector), R ~func(*sql.Selector)] struct { + typ string + tq interface { + Limit(int) T + Offset(int) T + Unique(bool) T + Order(...R) T + Where(...P) T + } +} + +func (q query[T, P, R]) Type() string { + return q.typ +} + +func (q query[T, P, R]) Limit(limit int) { + q.tq.Limit(limit) +} + +func (q query[T, P, R]) Offset(offset int) { + q.tq.Offset(offset) +} + +func (q query[T, P, R]) Unique(unique bool) { + q.tq.Unique(unique) +} + +func (q query[T, P, R]) Order(orders ...func(*sql.Selector)) { + rs := make([]R, len(orders)) + for i := range orders { + rs[i] = orders[i] + } + q.tq.Order(rs...) +} + +func (q query[T, P, R]) WhereP(ps ...func(*sql.Selector)) { + p := make([]P, len(ps)) + for i := range ps { + p[i] = ps[i] + } + q.tq.Where(p...) +} diff --git a/internal/backends/ent/metadata/metadata.go b/internal/backends/ent/metadata/metadata.go index 9e3e3a3..99ffe58 100644 --- a/internal/backends/ent/metadata/metadata.go +++ b/internal/backends/ent/metadata/metadata.go @@ -8,6 +8,7 @@ package metadata import ( + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -100,7 +101,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // NativeIDValidator is a validator for the "native_id" field. It is called by the builders before save. NativeIDValidator func(string) error // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/metadata_create.go b/internal/backends/ent/metadata_create.go index ad95a4e..eb58f18 100644 --- a/internal/backends/ent/metadata_create.go +++ b/internal/backends/ent/metadata_create.go @@ -163,7 +163,9 @@ func (mc *MetadataCreate) Mutation() *MetadataMutation { // Save creates the Metadata in the database. func (mc *MetadataCreate) Save(ctx context.Context) (*Metadata, error) { - mc.defaults() + if err := mc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, mc.sqlSave, mc.mutation, mc.hooks) } @@ -190,11 +192,15 @@ func (mc *MetadataCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (mc *MetadataCreate) defaults() { +func (mc *MetadataCreate) defaults() error { if _, ok := mc.mutation.ID(); !ok { + if metadata.DefaultID == nil { + return fmt.Errorf("ent: uninitialized metadata.DefaultID (forgotten import ent/runtime?)") + } v := metadata.DefaultID() mc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/migrate/migrations/20250116180706_embed_uuid_mixin.sql b/internal/backends/ent/migrate/migrations/20250116180706_embed_uuid_mixin.sql new file mode 100644 index 0000000..266ebdb --- /dev/null +++ b/internal/backends/ent/migrate/migrations/20250116180706_embed_uuid_mixin.sql @@ -0,0 +1,20 @@ +-- Create index "document_types_proto_message_key" to table: "document_types" +CREATE UNIQUE INDEX `document_types_proto_message_key` ON `document_types` (`proto_message`); +-- Create index "nodes_proto_message_key" to table: "nodes" +CREATE UNIQUE INDEX `nodes_proto_message_key` ON `nodes` (`proto_message`); +-- Create index "persons_proto_message_key" to table: "persons" +CREATE UNIQUE INDEX `persons_proto_message_key` ON `persons` (`proto_message`); +-- Create index "tools_proto_message_key" to table: "tools" +CREATE UNIQUE INDEX `tools_proto_message_key` ON `tools` (`proto_message`); +-- Create index "properties_proto_message_key" to table: "properties" +CREATE UNIQUE INDEX `properties_proto_message_key` ON `properties` (`proto_message`); +-- Create index "source_data_proto_message_key" to table: "source_data" +CREATE UNIQUE INDEX `source_data_proto_message_key` ON `source_data` (`proto_message`); +-- Create index "edge_types_proto_message_key" to table: "edge_types" +CREATE UNIQUE INDEX `edge_types_proto_message_key` ON `edge_types` (`proto_message`); +-- Create index "external_references_proto_message_key" to table: "external_references" +CREATE UNIQUE INDEX `external_references_proto_message_key` ON `external_references` (`proto_message`); +-- Create index "metadata_proto_message_key" to table: "metadata" +CREATE UNIQUE INDEX `metadata_proto_message_key` ON `metadata` (`proto_message`); +-- Create index "node_lists_proto_message_key" to table: "node_lists" +CREATE UNIQUE INDEX `node_lists_proto_message_key` ON `node_lists` (`proto_message`); diff --git a/internal/backends/ent/migrate/migrations/atlas.sum b/internal/backends/ent/migrate/migrations/atlas.sum index 9804b9a..16024c0 100644 --- a/internal/backends/ent/migrate/migrations/atlas.sum +++ b/internal/backends/ent/migrate/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:lIrfcCk+LYFBqsFjGSqZ9QnvvS8jecCevrYZdG6GdDk= +h1:FilEZAOzP6rpZ/6QLfIYAESM3YKn+OUaJwmca7ToIRM= 20241016141529_initial.sql h1:cZ5Nr+1kj075buwWNz8SHKlRSFaV3L0dzpT9htnXQY4= 20241101155047_store_protos.sql h1:ALraUjMTZaPGDf+y7IXSLp/LRVWXP3rG6kKQb3ZJf5I= 20241109194036_ext_ref_type_fix.sql h1:hvLOKWxV23ea20Po7TLLx0VVfevihIQmR2Ft9nX2Nis= @@ -9,3 +9,4 @@ h1:lIrfcCk+LYFBqsFjGSqZ9QnvvS8jecCevrYZdG6GdDk= 20250111195106_hashes_entries.sql h1:xjufIpuHDOznA58+Uk7sIDgtA7lDHTynVtui/iXYFJk= 20250111195831_identifiers_entries.sql h1:t+6QoPwVYJFuXnS8zPiFeL3F/NvQorfgi5sAxGcEn6c= 20250116171940_annotations_nillable_document_id.sql h1:m7rHNc6tZKrgqTH2QWYJ6x7cZheeS1r3pihYyHATV8U= +20250116180706_embed_uuid_mixin.sql h1:ZYkxRXC/nkJslenl3XH2yGfeqWPyFuzLMsIImlOOOok= diff --git a/internal/backends/ent/migrate/schema.go b/internal/backends/ent/migrate/schema.go index eed0bbb..fd791b5 100644 --- a/internal/backends/ent/migrate/schema.go +++ b/internal/backends/ent/migrate/schema.go @@ -116,7 +116,7 @@ var ( // DocumentTypesColumns holds the columns for the "document_types" table. DocumentTypesColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "type", Type: field.TypeEnum, Nullable: true, Enums: []string{"OTHER", "DESIGN", "SOURCE", "BUILD", "ANALYZED", "DEPLOYED", "RUNTIME", "DISCOVERY", "DECOMISSION"}}, {Name: "name", Type: field.TypeString, Nullable: true}, {Name: "description", Type: field.TypeString, Nullable: true}, @@ -153,7 +153,7 @@ var ( // EdgeTypesColumns holds the columns for the "edge_types" table. EdgeTypesColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "type", Type: field.TypeEnum, Enums: []string{"UNKNOWN", "amends", "ancestor", "buildDependency", "buildTool", "contains", "contained_by", "copy", "dataFile", "dependencyManifest", "dependsOn", "dependencyOf", "descendant", "describes", "describedBy", "devDependency", "devTool", "distributionArtifact", "documentation", "dynamicLink", "example", "expandedFromArchive", "fileAdded", "fileDeleted", "fileModified", "generates", "generatedFrom", "metafile", "optionalComponent", "optionalDependency", "other", "packages", "patch", "prerequisite", "prerequisiteFor", "providedDependency", "requirementFor", "runtimeDependency", "specificationFor", "staticLink", "test", "testCase", "testDependency", "testTool", "variant"}}, {Name: "document_id", Type: field.TypeUUID, Nullable: true}, {Name: "node_id", Type: field.TypeUUID}, @@ -200,7 +200,7 @@ var ( // ExternalReferencesColumns holds the columns for the "external_references" table. ExternalReferencesColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "url", Type: field.TypeString}, {Name: "comment", Type: field.TypeString}, {Name: "authority", Type: field.TypeString, Nullable: true}, @@ -280,7 +280,7 @@ var ( // MetadataColumns holds the columns for the "metadata" table. MetadataColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "native_id", Type: field.TypeString}, {Name: "version", Type: field.TypeString}, {Name: "name", Type: field.TypeString}, @@ -303,7 +303,7 @@ var ( // NodesColumns holds the columns for the "nodes" table. NodesColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "native_id", Type: field.TypeString}, {Name: "node_list_id", Type: field.TypeUUID, Nullable: true}, {Name: "type", Type: field.TypeEnum, Enums: []string{"PACKAGE", "FILE"}}, @@ -351,7 +351,7 @@ var ( // NodeListsColumns holds the columns for the "node_lists" table. NodeListsColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "root_elements", Type: field.TypeJSON}, } // NodeListsTable holds the schema information for the "node_lists" table. @@ -363,7 +363,7 @@ var ( // PersonsColumns holds the columns for the "persons" table. PersonsColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "name", Type: field.TypeString}, {Name: "is_org", Type: field.TypeBool}, {Name: "email", Type: field.TypeString}, @@ -434,7 +434,7 @@ var ( // PropertiesColumns holds the columns for the "properties" table. PropertiesColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "name", Type: field.TypeString}, {Name: "data", Type: field.TypeString}, {Name: "node_id", Type: field.TypeUUID, Nullable: true}, @@ -504,7 +504,7 @@ var ( // SourceDataColumns holds the columns for the "source_data" table. SourceDataColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "format", Type: field.TypeString}, {Name: "size", Type: field.TypeInt64}, {Name: "uri", Type: field.TypeString, Nullable: true}, @@ -542,7 +542,7 @@ var ( // ToolsColumns holds the columns for the "tools" table. ToolsColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID, Unique: true}, - {Name: "proto_message", Type: field.TypeBytes}, + {Name: "proto_message", Type: field.TypeBytes, Unique: true}, {Name: "name", Type: field.TypeString}, {Name: "version", Type: field.TypeString}, {Name: "vendor", Type: field.TypeString}, diff --git a/internal/backends/ent/node/node.go b/internal/backends/ent/node/node.go index caca165..e2d773b 100644 --- a/internal/backends/ent/node/node.go +++ b/internal/backends/ent/node/node.go @@ -10,6 +10,7 @@ package node import ( "fmt" + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -228,7 +229,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // NativeIDValidator is a validator for the "native_id" field. It is called by the builders before save. diff --git a/internal/backends/ent/node_create.go b/internal/backends/ent/node_create.go index 4c2f4db..af8fe2d 100644 --- a/internal/backends/ent/node_create.go +++ b/internal/backends/ent/node_create.go @@ -400,7 +400,9 @@ func (nc *NodeCreate) Mutation() *NodeMutation { // Save creates the Node in the database. func (nc *NodeCreate) Save(ctx context.Context) (*Node, error) { - nc.defaults() + if err := nc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, nc.sqlSave, nc.mutation, nc.hooks) } @@ -427,15 +429,22 @@ func (nc *NodeCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (nc *NodeCreate) defaults() { +func (nc *NodeCreate) defaults() error { if _, ok := nc.mutation.DocumentID(); !ok { + if node.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized node.DefaultDocumentID (forgotten import ent/runtime?)") + } v := node.DefaultDocumentID() nc.mutation.SetDocumentID(v) } if _, ok := nc.mutation.ID(); !ok { + if node.DefaultID == nil { + return fmt.Errorf("ent: uninitialized node.DefaultID (forgotten import ent/runtime?)") + } v := node.DefaultID() nc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. @@ -749,7 +758,7 @@ func (nc *NodeCreate) createSpec() (*Node, *sqlgraph.CreateSpec) { edge.Target.Nodes = append(edge.Target.Nodes, k) } createE := &EdgeTypeCreate{config: nc.config, mutation: newEdgeTypeMutation(nc.config, OpCreate)} - createE.defaults() + _ = createE.defaults() _, specE := createE.createSpec() edge.Target.Fields = specE.Fields if specE.ID.Value != nil { diff --git a/internal/backends/ent/node_update.go b/internal/backends/ent/node_update.go index 419f90b..37c23c8 100644 --- a/internal/backends/ent/node_update.go +++ b/internal/backends/ent/node_update.go @@ -1125,7 +1125,7 @@ func (nu *NodeUpdate) sqlSave(ctx context.Context) (n int, err error) { }, } createE := &EdgeTypeCreate{config: nu.config, mutation: newEdgeTypeMutation(nu.config, OpCreate)} - createE.defaults() + _ = createE.defaults() _, specE := createE.createSpec() edge.Target.Fields = specE.Fields if specE.ID.Value != nil { @@ -1148,7 +1148,7 @@ func (nu *NodeUpdate) sqlSave(ctx context.Context) (n int, err error) { edge.Target.Nodes = append(edge.Target.Nodes, k) } createE := &EdgeTypeCreate{config: nu.config, mutation: newEdgeTypeMutation(nu.config, OpCreate)} - createE.defaults() + _ = createE.defaults() _, specE := createE.createSpec() edge.Target.Fields = specE.Fields if specE.ID.Value != nil { @@ -1171,7 +1171,7 @@ func (nu *NodeUpdate) sqlSave(ctx context.Context) (n int, err error) { edge.Target.Nodes = append(edge.Target.Nodes, k) } createE := &EdgeTypeCreate{config: nu.config, mutation: newEdgeTypeMutation(nu.config, OpCreate)} - createE.defaults() + _ = createE.defaults() _, specE := createE.createSpec() edge.Target.Fields = specE.Fields if specE.ID.Value != nil { @@ -2580,7 +2580,7 @@ func (nuo *NodeUpdateOne) sqlSave(ctx context.Context) (_node *Node, err error) }, } createE := &EdgeTypeCreate{config: nuo.config, mutation: newEdgeTypeMutation(nuo.config, OpCreate)} - createE.defaults() + _ = createE.defaults() _, specE := createE.createSpec() edge.Target.Fields = specE.Fields if specE.ID.Value != nil { @@ -2603,7 +2603,7 @@ func (nuo *NodeUpdateOne) sqlSave(ctx context.Context) (_node *Node, err error) edge.Target.Nodes = append(edge.Target.Nodes, k) } createE := &EdgeTypeCreate{config: nuo.config, mutation: newEdgeTypeMutation(nuo.config, OpCreate)} - createE.defaults() + _ = createE.defaults() _, specE := createE.createSpec() edge.Target.Fields = specE.Fields if specE.ID.Value != nil { @@ -2626,7 +2626,7 @@ func (nuo *NodeUpdateOne) sqlSave(ctx context.Context) (_node *Node, err error) edge.Target.Nodes = append(edge.Target.Nodes, k) } createE := &EdgeTypeCreate{config: nuo.config, mutation: newEdgeTypeMutation(nuo.config, OpCreate)} - createE.defaults() + _ = createE.defaults() _, specE := createE.createSpec() edge.Target.Fields = specE.Fields if specE.ID.Value != nil { diff --git a/internal/backends/ent/nodelist/nodelist.go b/internal/backends/ent/nodelist/nodelist.go index fcfa1d5..cb4c81f 100644 --- a/internal/backends/ent/nodelist/nodelist.go +++ b/internal/backends/ent/nodelist/nodelist.go @@ -8,6 +8,7 @@ package nodelist import ( + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -75,7 +76,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultID holds the default value on creation for the "id" field. DefaultID func() uuid.UUID ) diff --git a/internal/backends/ent/nodelist_create.go b/internal/backends/ent/nodelist_create.go index 5fedd2a..d63ba25 100644 --- a/internal/backends/ent/nodelist_create.go +++ b/internal/backends/ent/nodelist_create.go @@ -106,7 +106,9 @@ func (nlc *NodeListCreate) Mutation() *NodeListMutation { // Save creates the NodeList in the database. func (nlc *NodeListCreate) Save(ctx context.Context) (*NodeList, error) { - nlc.defaults() + if err := nlc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, nlc.sqlSave, nlc.mutation, nlc.hooks) } @@ -133,11 +135,15 @@ func (nlc *NodeListCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (nlc *NodeListCreate) defaults() { +func (nlc *NodeListCreate) defaults() error { if _, ok := nlc.mutation.ID(); !ok { + if nodelist.DefaultID == nil { + return fmt.Errorf("ent: uninitialized nodelist.DefaultID (forgotten import ent/runtime?)") + } v := nodelist.DefaultID() nlc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/person/person.go b/internal/backends/ent/person/person.go index 96bdfac..d7bbe1e 100644 --- a/internal/backends/ent/person/person.go +++ b/internal/backends/ent/person/person.go @@ -8,6 +8,7 @@ package person import ( + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -115,7 +116,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/person_create.go b/internal/backends/ent/person_create.go index 4f2582b..77b8b2e 100644 --- a/internal/backends/ent/person_create.go +++ b/internal/backends/ent/person_create.go @@ -180,7 +180,9 @@ func (pc *PersonCreate) Mutation() *PersonMutation { // Save creates the Person in the database. func (pc *PersonCreate) Save(ctx context.Context) (*Person, error) { - pc.defaults() + if err := pc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, pc.sqlSave, pc.mutation, pc.hooks) } @@ -207,15 +209,22 @@ func (pc *PersonCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (pc *PersonCreate) defaults() { +func (pc *PersonCreate) defaults() error { if _, ok := pc.mutation.DocumentID(); !ok { + if person.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized person.DefaultDocumentID (forgotten import ent/runtime?)") + } v := person.DefaultDocumentID() pc.mutation.SetDocumentID(v) } if _, ok := pc.mutation.ID(); !ok { + if person.DefaultID == nil { + return fmt.Errorf("ent: uninitialized person.DefaultID (forgotten import ent/runtime?)") + } v := person.DefaultID() pc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/property/property.go b/internal/backends/ent/property/property.go index 1b6effd..35d7392 100644 --- a/internal/backends/ent/property/property.go +++ b/internal/backends/ent/property/property.go @@ -8,6 +8,7 @@ package property import ( + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -70,7 +71,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/property_create.go b/internal/backends/ent/property_create.go index 521caa9..559210d 100644 --- a/internal/backends/ent/property_create.go +++ b/internal/backends/ent/property_create.go @@ -108,7 +108,9 @@ func (pc *PropertyCreate) Mutation() *PropertyMutation { // Save creates the Property in the database. func (pc *PropertyCreate) Save(ctx context.Context) (*Property, error) { - pc.defaults() + if err := pc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, pc.sqlSave, pc.mutation, pc.hooks) } @@ -135,15 +137,22 @@ func (pc *PropertyCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (pc *PropertyCreate) defaults() { +func (pc *PropertyCreate) defaults() error { if _, ok := pc.mutation.DocumentID(); !ok { + if property.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized property.DefaultDocumentID (forgotten import ent/runtime?)") + } v := property.DefaultDocumentID() pc.mutation.SetDocumentID(v) } if _, ok := pc.mutation.ID(); !ok { + if property.DefaultID == nil { + return fmt.Errorf("ent: uninitialized property.DefaultID (forgotten import ent/runtime?)") + } v := property.DefaultID() pc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/runtime.go b/internal/backends/ent/runtime.go index 5f0f101..d538a81 100644 --- a/internal/backends/ent/runtime.go +++ b/internal/backends/ent/runtime.go @@ -7,228 +7,4 @@ package ent -import ( - "github.com/google/uuid" - "github.com/protobom/storage/internal/backends/ent/annotation" - "github.com/protobom/storage/internal/backends/ent/document" - "github.com/protobom/storage/internal/backends/ent/documenttype" - "github.com/protobom/storage/internal/backends/ent/edgetype" - "github.com/protobom/storage/internal/backends/ent/externalreference" - "github.com/protobom/storage/internal/backends/ent/hashesentry" - "github.com/protobom/storage/internal/backends/ent/identifiersentry" - "github.com/protobom/storage/internal/backends/ent/metadata" - "github.com/protobom/storage/internal/backends/ent/node" - "github.com/protobom/storage/internal/backends/ent/nodelist" - "github.com/protobom/storage/internal/backends/ent/person" - "github.com/protobom/storage/internal/backends/ent/property" - "github.com/protobom/storage/internal/backends/ent/purpose" - "github.com/protobom/storage/internal/backends/ent/schema" - "github.com/protobom/storage/internal/backends/ent/sourcedata" - "github.com/protobom/storage/internal/backends/ent/tool" -) - -// The init function reads all schema descriptors with runtime code -// (default values, validators, hooks and policies) and stitches it -// to their package variables. -func init() { - annotationFields := schema.Annotation{}.Fields() - _ = annotationFields - // annotationDescIsUnique is the schema descriptor for is_unique field. - annotationDescIsUnique := annotationFields[4].Descriptor() - // annotation.DefaultIsUnique holds the default value on creation for the is_unique field. - annotation.DefaultIsUnique = annotationDescIsUnique.Default.(bool) - documentMixin := schema.Document{}.Mixin() - documentMixinFields0 := documentMixin[0].Fields() - _ = documentMixinFields0 - documentFields := schema.Document{}.Fields() - _ = documentFields - // documentDescID is the schema descriptor for id field. - documentDescID := documentMixinFields0[0].Descriptor() - // document.DefaultID holds the default value on creation for the id field. - document.DefaultID = documentDescID.Default.(func() uuid.UUID) - documenttypeMixin := schema.DocumentType{}.Mixin() - documenttypeMixinFields0 := documenttypeMixin[0].Fields() - _ = documenttypeMixinFields0 - documenttypeMixinFields2 := documenttypeMixin[2].Fields() - _ = documenttypeMixinFields2 - documenttypeFields := schema.DocumentType{}.Fields() - _ = documenttypeFields - // documenttypeDescDocumentID is the schema descriptor for document_id field. - documenttypeDescDocumentID := documenttypeMixinFields0[0].Descriptor() - // documenttype.DefaultDocumentID holds the default value on creation for the document_id field. - documenttype.DefaultDocumentID = documenttypeDescDocumentID.Default.(func() uuid.UUID) - // documenttypeDescID is the schema descriptor for id field. - documenttypeDescID := documenttypeMixinFields2[0].Descriptor() - // documenttype.DefaultID holds the default value on creation for the id field. - documenttype.DefaultID = documenttypeDescID.Default.(func() uuid.UUID) - edgetypeMixin := schema.EdgeType{}.Mixin() - edgetypeMixinFields0 := edgetypeMixin[0].Fields() - _ = edgetypeMixinFields0 - edgetypeMixinFields2 := edgetypeMixin[2].Fields() - _ = edgetypeMixinFields2 - edgetypeFields := schema.EdgeType{}.Fields() - _ = edgetypeFields - // edgetypeDescDocumentID is the schema descriptor for document_id field. - edgetypeDescDocumentID := edgetypeMixinFields0[0].Descriptor() - // edgetype.DefaultDocumentID holds the default value on creation for the document_id field. - edgetype.DefaultDocumentID = edgetypeDescDocumentID.Default.(func() uuid.UUID) - // edgetypeDescID is the schema descriptor for id field. - edgetypeDescID := edgetypeMixinFields2[0].Descriptor() - // edgetype.DefaultID holds the default value on creation for the id field. - edgetype.DefaultID = edgetypeDescID.Default.(func() uuid.UUID) - externalreferenceMixin := schema.ExternalReference{}.Mixin() - externalreferenceMixinFields0 := externalreferenceMixin[0].Fields() - _ = externalreferenceMixinFields0 - externalreferenceMixinFields2 := externalreferenceMixin[2].Fields() - _ = externalreferenceMixinFields2 - externalreferenceFields := schema.ExternalReference{}.Fields() - _ = externalreferenceFields - // externalreferenceDescDocumentID is the schema descriptor for document_id field. - externalreferenceDescDocumentID := externalreferenceMixinFields0[0].Descriptor() - // externalreference.DefaultDocumentID holds the default value on creation for the document_id field. - externalreference.DefaultDocumentID = externalreferenceDescDocumentID.Default.(func() uuid.UUID) - // externalreferenceDescID is the schema descriptor for id field. - externalreferenceDescID := externalreferenceMixinFields2[0].Descriptor() - // externalreference.DefaultID holds the default value on creation for the id field. - externalreference.DefaultID = externalreferenceDescID.Default.(func() uuid.UUID) - hashesentryMixin := schema.HashesEntry{}.Mixin() - hashesentryMixinFields0 := hashesentryMixin[0].Fields() - _ = hashesentryMixinFields0 - hashesentryMixinFields1 := hashesentryMixin[1].Fields() - _ = hashesentryMixinFields1 - hashesentryFields := schema.HashesEntry{}.Fields() - _ = hashesentryFields - // hashesentryDescDocumentID is the schema descriptor for document_id field. - hashesentryDescDocumentID := hashesentryMixinFields0[0].Descriptor() - // hashesentry.DefaultDocumentID holds the default value on creation for the document_id field. - hashesentry.DefaultDocumentID = hashesentryDescDocumentID.Default.(func() uuid.UUID) - // hashesentryDescID is the schema descriptor for id field. - hashesentryDescID := hashesentryMixinFields1[0].Descriptor() - // hashesentry.DefaultID holds the default value on creation for the id field. - hashesentry.DefaultID = hashesentryDescID.Default.(func() uuid.UUID) - identifiersentryMixin := schema.IdentifiersEntry{}.Mixin() - identifiersentryMixinFields0 := identifiersentryMixin[0].Fields() - _ = identifiersentryMixinFields0 - identifiersentryMixinFields1 := identifiersentryMixin[1].Fields() - _ = identifiersentryMixinFields1 - identifiersentryFields := schema.IdentifiersEntry{}.Fields() - _ = identifiersentryFields - // identifiersentryDescDocumentID is the schema descriptor for document_id field. - identifiersentryDescDocumentID := identifiersentryMixinFields0[0].Descriptor() - // identifiersentry.DefaultDocumentID holds the default value on creation for the document_id field. - identifiersentry.DefaultDocumentID = identifiersentryDescDocumentID.Default.(func() uuid.UUID) - // identifiersentryDescID is the schema descriptor for id field. - identifiersentryDescID := identifiersentryMixinFields1[0].Descriptor() - // identifiersentry.DefaultID holds the default value on creation for the id field. - identifiersentry.DefaultID = identifiersentryDescID.Default.(func() uuid.UUID) - metadataMixin := schema.Metadata{}.Mixin() - metadataMixinFields1 := metadataMixin[1].Fields() - _ = metadataMixinFields1 - metadataFields := schema.Metadata{}.Fields() - _ = metadataFields - // metadataDescNativeID is the schema descriptor for native_id field. - metadataDescNativeID := metadataFields[0].Descriptor() - // metadata.NativeIDValidator is a validator for the "native_id" field. It is called by the builders before save. - metadata.NativeIDValidator = metadataDescNativeID.Validators[0].(func(string) error) - // metadataDescID is the schema descriptor for id field. - metadataDescID := metadataMixinFields1[0].Descriptor() - // metadata.DefaultID holds the default value on creation for the id field. - metadata.DefaultID = metadataDescID.Default.(func() uuid.UUID) - nodeMixin := schema.Node{}.Mixin() - nodeMixinFields0 := nodeMixin[0].Fields() - _ = nodeMixinFields0 - nodeMixinFields2 := nodeMixin[2].Fields() - _ = nodeMixinFields2 - nodeFields := schema.Node{}.Fields() - _ = nodeFields - // nodeDescDocumentID is the schema descriptor for document_id field. - nodeDescDocumentID := nodeMixinFields0[0].Descriptor() - // node.DefaultDocumentID holds the default value on creation for the document_id field. - node.DefaultDocumentID = nodeDescDocumentID.Default.(func() uuid.UUID) - // nodeDescNativeID is the schema descriptor for native_id field. - nodeDescNativeID := nodeFields[0].Descriptor() - // node.NativeIDValidator is a validator for the "native_id" field. It is called by the builders before save. - node.NativeIDValidator = nodeDescNativeID.Validators[0].(func(string) error) - // nodeDescID is the schema descriptor for id field. - nodeDescID := nodeMixinFields2[0].Descriptor() - // node.DefaultID holds the default value on creation for the id field. - node.DefaultID = nodeDescID.Default.(func() uuid.UUID) - nodelistMixin := schema.NodeList{}.Mixin() - nodelistMixinFields1 := nodelistMixin[1].Fields() - _ = nodelistMixinFields1 - nodelistFields := schema.NodeList{}.Fields() - _ = nodelistFields - // nodelistDescID is the schema descriptor for id field. - nodelistDescID := nodelistMixinFields1[0].Descriptor() - // nodelist.DefaultID holds the default value on creation for the id field. - nodelist.DefaultID = nodelistDescID.Default.(func() uuid.UUID) - personMixin := schema.Person{}.Mixin() - personMixinFields0 := personMixin[0].Fields() - _ = personMixinFields0 - personMixinFields2 := personMixin[2].Fields() - _ = personMixinFields2 - personFields := schema.Person{}.Fields() - _ = personFields - // personDescDocumentID is the schema descriptor for document_id field. - personDescDocumentID := personMixinFields0[0].Descriptor() - // person.DefaultDocumentID holds the default value on creation for the document_id field. - person.DefaultDocumentID = personDescDocumentID.Default.(func() uuid.UUID) - // personDescID is the schema descriptor for id field. - personDescID := personMixinFields2[0].Descriptor() - // person.DefaultID holds the default value on creation for the id field. - person.DefaultID = personDescID.Default.(func() uuid.UUID) - propertyMixin := schema.Property{}.Mixin() - propertyMixinFields0 := propertyMixin[0].Fields() - _ = propertyMixinFields0 - propertyMixinFields2 := propertyMixin[2].Fields() - _ = propertyMixinFields2 - propertyFields := schema.Property{}.Fields() - _ = propertyFields - // propertyDescDocumentID is the schema descriptor for document_id field. - propertyDescDocumentID := propertyMixinFields0[0].Descriptor() - // property.DefaultDocumentID holds the default value on creation for the document_id field. - property.DefaultDocumentID = propertyDescDocumentID.Default.(func() uuid.UUID) - // propertyDescID is the schema descriptor for id field. - propertyDescID := propertyMixinFields2[0].Descriptor() - // property.DefaultID holds the default value on creation for the id field. - property.DefaultID = propertyDescID.Default.(func() uuid.UUID) - purposeMixin := schema.Purpose{}.Mixin() - purposeMixinFields0 := purposeMixin[0].Fields() - _ = purposeMixinFields0 - purposeFields := schema.Purpose{}.Fields() - _ = purposeFields - // purposeDescDocumentID is the schema descriptor for document_id field. - purposeDescDocumentID := purposeMixinFields0[0].Descriptor() - // purpose.DefaultDocumentID holds the default value on creation for the document_id field. - purpose.DefaultDocumentID = purposeDescDocumentID.Default.(func() uuid.UUID) - sourcedataMixin := schema.SourceData{}.Mixin() - sourcedataMixinFields0 := sourcedataMixin[0].Fields() - _ = sourcedataMixinFields0 - sourcedataMixinFields2 := sourcedataMixin[2].Fields() - _ = sourcedataMixinFields2 - sourcedataFields := schema.SourceData{}.Fields() - _ = sourcedataFields - // sourcedataDescDocumentID is the schema descriptor for document_id field. - sourcedataDescDocumentID := sourcedataMixinFields0[0].Descriptor() - // sourcedata.DefaultDocumentID holds the default value on creation for the document_id field. - sourcedata.DefaultDocumentID = sourcedataDescDocumentID.Default.(func() uuid.UUID) - // sourcedataDescID is the schema descriptor for id field. - sourcedataDescID := sourcedataMixinFields2[0].Descriptor() - // sourcedata.DefaultID holds the default value on creation for the id field. - sourcedata.DefaultID = sourcedataDescID.Default.(func() uuid.UUID) - toolMixin := schema.Tool{}.Mixin() - toolMixinFields0 := toolMixin[0].Fields() - _ = toolMixinFields0 - toolMixinFields2 := toolMixin[2].Fields() - _ = toolMixinFields2 - toolFields := schema.Tool{}.Fields() - _ = toolFields - // toolDescDocumentID is the schema descriptor for document_id field. - toolDescDocumentID := toolMixinFields0[0].Descriptor() - // tool.DefaultDocumentID holds the default value on creation for the document_id field. - tool.DefaultDocumentID = toolDescDocumentID.Default.(func() uuid.UUID) - // toolDescID is the schema descriptor for id field. - toolDescID := toolMixinFields2[0].Descriptor() - // tool.DefaultID holds the default value on creation for the id field. - tool.DefaultID = toolDescID.Default.(func() uuid.UUID) -} +// The schema-stitching logic is generated in github.com/protobom/storage/internal/backends/ent/runtime/runtime.go diff --git a/internal/backends/ent/runtime/runtime.go b/internal/backends/ent/runtime/runtime.go index 3022427..220fa7d 100644 --- a/internal/backends/ent/runtime/runtime.go +++ b/internal/backends/ent/runtime/runtime.go @@ -7,7 +7,251 @@ package runtime -// The schema-stitching logic is generated in github.com/protobom/storage/internal/backends/ent/runtime.go +import ( + "github.com/google/uuid" + "github.com/protobom/storage/internal/backends/ent/annotation" + "github.com/protobom/storage/internal/backends/ent/document" + "github.com/protobom/storage/internal/backends/ent/documenttype" + "github.com/protobom/storage/internal/backends/ent/edgetype" + "github.com/protobom/storage/internal/backends/ent/externalreference" + "github.com/protobom/storage/internal/backends/ent/hashesentry" + "github.com/protobom/storage/internal/backends/ent/identifiersentry" + "github.com/protobom/storage/internal/backends/ent/metadata" + "github.com/protobom/storage/internal/backends/ent/node" + "github.com/protobom/storage/internal/backends/ent/nodelist" + "github.com/protobom/storage/internal/backends/ent/person" + "github.com/protobom/storage/internal/backends/ent/property" + "github.com/protobom/storage/internal/backends/ent/purpose" + "github.com/protobom/storage/internal/backends/ent/schema" + "github.com/protobom/storage/internal/backends/ent/sourcedata" + "github.com/protobom/storage/internal/backends/ent/tool" +) + +// The init function reads all schema descriptors with runtime code +// (default values, validators, hooks and policies) and stitches it +// to their package variables. +func init() { + annotationFields := schema.Annotation{}.Fields() + _ = annotationFields + // annotationDescIsUnique is the schema descriptor for is_unique field. + annotationDescIsUnique := annotationFields[4].Descriptor() + // annotation.DefaultIsUnique holds the default value on creation for the is_unique field. + annotation.DefaultIsUnique = annotationDescIsUnique.Default.(bool) + documentMixin := schema.Document{}.Mixin() + documentMixinFields0 := documentMixin[0].Fields() + _ = documentMixinFields0 + documentFields := schema.Document{}.Fields() + _ = documentFields + // documentDescID is the schema descriptor for id field. + documentDescID := documentMixinFields0[0].Descriptor() + // document.DefaultID holds the default value on creation for the id field. + document.DefaultID = documentDescID.Default.(func() uuid.UUID) + documenttypeMixin := schema.DocumentType{}.Mixin() + documenttypeMixinHooks1 := documenttypeMixin[1].Hooks() + documenttype.Hooks[0] = documenttypeMixinHooks1[0] + documenttypeMixinFields0 := documenttypeMixin[0].Fields() + _ = documenttypeMixinFields0 + documenttypeMixinFields1 := documenttypeMixin[1].Fields() + _ = documenttypeMixinFields1 + documenttypeFields := schema.DocumentType{}.Fields() + _ = documenttypeFields + // documenttypeDescDocumentID is the schema descriptor for document_id field. + documenttypeDescDocumentID := documenttypeMixinFields0[0].Descriptor() + // documenttype.DefaultDocumentID holds the default value on creation for the document_id field. + documenttype.DefaultDocumentID = documenttypeDescDocumentID.Default.(func() uuid.UUID) + // documenttypeDescID is the schema descriptor for id field. + documenttypeDescID := documenttypeMixinFields1[0].Descriptor() + // documenttype.DefaultID holds the default value on creation for the id field. + documenttype.DefaultID = documenttypeDescID.Default.(func() uuid.UUID) + edgetypeMixin := schema.EdgeType{}.Mixin() + edgetypeMixinHooks1 := edgetypeMixin[1].Hooks() + edgetype.Hooks[0] = edgetypeMixinHooks1[0] + edgetypeMixinFields0 := edgetypeMixin[0].Fields() + _ = edgetypeMixinFields0 + edgetypeMixinFields1 := edgetypeMixin[1].Fields() + _ = edgetypeMixinFields1 + edgetypeFields := schema.EdgeType{}.Fields() + _ = edgetypeFields + // edgetypeDescDocumentID is the schema descriptor for document_id field. + edgetypeDescDocumentID := edgetypeMixinFields0[0].Descriptor() + // edgetype.DefaultDocumentID holds the default value on creation for the document_id field. + edgetype.DefaultDocumentID = edgetypeDescDocumentID.Default.(func() uuid.UUID) + // edgetypeDescID is the schema descriptor for id field. + edgetypeDescID := edgetypeMixinFields1[0].Descriptor() + // edgetype.DefaultID holds the default value on creation for the id field. + edgetype.DefaultID = edgetypeDescID.Default.(func() uuid.UUID) + externalreferenceMixin := schema.ExternalReference{}.Mixin() + externalreferenceMixinHooks1 := externalreferenceMixin[1].Hooks() + externalreference.Hooks[0] = externalreferenceMixinHooks1[0] + externalreferenceMixinFields0 := externalreferenceMixin[0].Fields() + _ = externalreferenceMixinFields0 + externalreferenceMixinFields1 := externalreferenceMixin[1].Fields() + _ = externalreferenceMixinFields1 + externalreferenceFields := schema.ExternalReference{}.Fields() + _ = externalreferenceFields + // externalreferenceDescDocumentID is the schema descriptor for document_id field. + externalreferenceDescDocumentID := externalreferenceMixinFields0[0].Descriptor() + // externalreference.DefaultDocumentID holds the default value on creation for the document_id field. + externalreference.DefaultDocumentID = externalreferenceDescDocumentID.Default.(func() uuid.UUID) + // externalreferenceDescID is the schema descriptor for id field. + externalreferenceDescID := externalreferenceMixinFields1[0].Descriptor() + // externalreference.DefaultID holds the default value on creation for the id field. + externalreference.DefaultID = externalreferenceDescID.Default.(func() uuid.UUID) + hashesentryMixin := schema.HashesEntry{}.Mixin() + hashesentryMixinFields0 := hashesentryMixin[0].Fields() + _ = hashesentryMixinFields0 + hashesentryMixinFields1 := hashesentryMixin[1].Fields() + _ = hashesentryMixinFields1 + hashesentryFields := schema.HashesEntry{}.Fields() + _ = hashesentryFields + // hashesentryDescDocumentID is the schema descriptor for document_id field. + hashesentryDescDocumentID := hashesentryMixinFields0[0].Descriptor() + // hashesentry.DefaultDocumentID holds the default value on creation for the document_id field. + hashesentry.DefaultDocumentID = hashesentryDescDocumentID.Default.(func() uuid.UUID) + // hashesentryDescID is the schema descriptor for id field. + hashesentryDescID := hashesentryMixinFields1[0].Descriptor() + // hashesentry.DefaultID holds the default value on creation for the id field. + hashesentry.DefaultID = hashesentryDescID.Default.(func() uuid.UUID) + identifiersentryMixin := schema.IdentifiersEntry{}.Mixin() + identifiersentryMixinFields0 := identifiersentryMixin[0].Fields() + _ = identifiersentryMixinFields0 + identifiersentryMixinFields1 := identifiersentryMixin[1].Fields() + _ = identifiersentryMixinFields1 + identifiersentryFields := schema.IdentifiersEntry{}.Fields() + _ = identifiersentryFields + // identifiersentryDescDocumentID is the schema descriptor for document_id field. + identifiersentryDescDocumentID := identifiersentryMixinFields0[0].Descriptor() + // identifiersentry.DefaultDocumentID holds the default value on creation for the document_id field. + identifiersentry.DefaultDocumentID = identifiersentryDescDocumentID.Default.(func() uuid.UUID) + // identifiersentryDescID is the schema descriptor for id field. + identifiersentryDescID := identifiersentryMixinFields1[0].Descriptor() + // identifiersentry.DefaultID holds the default value on creation for the id field. + identifiersentry.DefaultID = identifiersentryDescID.Default.(func() uuid.UUID) + metadataMixin := schema.Metadata{}.Mixin() + metadataMixinHooks0 := metadataMixin[0].Hooks() + metadata.Hooks[0] = metadataMixinHooks0[0] + metadataMixinFields0 := metadataMixin[0].Fields() + _ = metadataMixinFields0 + metadataFields := schema.Metadata{}.Fields() + _ = metadataFields + // metadataDescNativeID is the schema descriptor for native_id field. + metadataDescNativeID := metadataFields[0].Descriptor() + // metadata.NativeIDValidator is a validator for the "native_id" field. It is called by the builders before save. + metadata.NativeIDValidator = metadataDescNativeID.Validators[0].(func(string) error) + // metadataDescID is the schema descriptor for id field. + metadataDescID := metadataMixinFields0[0].Descriptor() + // metadata.DefaultID holds the default value on creation for the id field. + metadata.DefaultID = metadataDescID.Default.(func() uuid.UUID) + nodeMixin := schema.Node{}.Mixin() + nodeMixinHooks1 := nodeMixin[1].Hooks() + node.Hooks[0] = nodeMixinHooks1[0] + nodeMixinFields0 := nodeMixin[0].Fields() + _ = nodeMixinFields0 + nodeMixinFields1 := nodeMixin[1].Fields() + _ = nodeMixinFields1 + nodeFields := schema.Node{}.Fields() + _ = nodeFields + // nodeDescDocumentID is the schema descriptor for document_id field. + nodeDescDocumentID := nodeMixinFields0[0].Descriptor() + // node.DefaultDocumentID holds the default value on creation for the document_id field. + node.DefaultDocumentID = nodeDescDocumentID.Default.(func() uuid.UUID) + // nodeDescNativeID is the schema descriptor for native_id field. + nodeDescNativeID := nodeFields[0].Descriptor() + // node.NativeIDValidator is a validator for the "native_id" field. It is called by the builders before save. + node.NativeIDValidator = nodeDescNativeID.Validators[0].(func(string) error) + // nodeDescID is the schema descriptor for id field. + nodeDescID := nodeMixinFields1[0].Descriptor() + // node.DefaultID holds the default value on creation for the id field. + node.DefaultID = nodeDescID.Default.(func() uuid.UUID) + nodelistMixin := schema.NodeList{}.Mixin() + nodelistMixinHooks0 := nodelistMixin[0].Hooks() + nodelist.Hooks[0] = nodelistMixinHooks0[0] + nodelistMixinFields0 := nodelistMixin[0].Fields() + _ = nodelistMixinFields0 + nodelistFields := schema.NodeList{}.Fields() + _ = nodelistFields + // nodelistDescID is the schema descriptor for id field. + nodelistDescID := nodelistMixinFields0[0].Descriptor() + // nodelist.DefaultID holds the default value on creation for the id field. + nodelist.DefaultID = nodelistDescID.Default.(func() uuid.UUID) + personMixin := schema.Person{}.Mixin() + personMixinHooks1 := personMixin[1].Hooks() + person.Hooks[0] = personMixinHooks1[0] + personMixinFields0 := personMixin[0].Fields() + _ = personMixinFields0 + personMixinFields1 := personMixin[1].Fields() + _ = personMixinFields1 + personFields := schema.Person{}.Fields() + _ = personFields + // personDescDocumentID is the schema descriptor for document_id field. + personDescDocumentID := personMixinFields0[0].Descriptor() + // person.DefaultDocumentID holds the default value on creation for the document_id field. + person.DefaultDocumentID = personDescDocumentID.Default.(func() uuid.UUID) + // personDescID is the schema descriptor for id field. + personDescID := personMixinFields1[0].Descriptor() + // person.DefaultID holds the default value on creation for the id field. + person.DefaultID = personDescID.Default.(func() uuid.UUID) + propertyMixin := schema.Property{}.Mixin() + propertyMixinHooks1 := propertyMixin[1].Hooks() + property.Hooks[0] = propertyMixinHooks1[0] + propertyMixinFields0 := propertyMixin[0].Fields() + _ = propertyMixinFields0 + propertyMixinFields1 := propertyMixin[1].Fields() + _ = propertyMixinFields1 + propertyFields := schema.Property{}.Fields() + _ = propertyFields + // propertyDescDocumentID is the schema descriptor for document_id field. + propertyDescDocumentID := propertyMixinFields0[0].Descriptor() + // property.DefaultDocumentID holds the default value on creation for the document_id field. + property.DefaultDocumentID = propertyDescDocumentID.Default.(func() uuid.UUID) + // propertyDescID is the schema descriptor for id field. + propertyDescID := propertyMixinFields1[0].Descriptor() + // property.DefaultID holds the default value on creation for the id field. + property.DefaultID = propertyDescID.Default.(func() uuid.UUID) + purposeMixin := schema.Purpose{}.Mixin() + purposeMixinFields0 := purposeMixin[0].Fields() + _ = purposeMixinFields0 + purposeFields := schema.Purpose{}.Fields() + _ = purposeFields + // purposeDescDocumentID is the schema descriptor for document_id field. + purposeDescDocumentID := purposeMixinFields0[0].Descriptor() + // purpose.DefaultDocumentID holds the default value on creation for the document_id field. + purpose.DefaultDocumentID = purposeDescDocumentID.Default.(func() uuid.UUID) + sourcedataMixin := schema.SourceData{}.Mixin() + sourcedataMixinHooks1 := sourcedataMixin[1].Hooks() + sourcedata.Hooks[0] = sourcedataMixinHooks1[0] + sourcedataMixinFields0 := sourcedataMixin[0].Fields() + _ = sourcedataMixinFields0 + sourcedataMixinFields1 := sourcedataMixin[1].Fields() + _ = sourcedataMixinFields1 + sourcedataFields := schema.SourceData{}.Fields() + _ = sourcedataFields + // sourcedataDescDocumentID is the schema descriptor for document_id field. + sourcedataDescDocumentID := sourcedataMixinFields0[0].Descriptor() + // sourcedata.DefaultDocumentID holds the default value on creation for the document_id field. + sourcedata.DefaultDocumentID = sourcedataDescDocumentID.Default.(func() uuid.UUID) + // sourcedataDescID is the schema descriptor for id field. + sourcedataDescID := sourcedataMixinFields1[0].Descriptor() + // sourcedata.DefaultID holds the default value on creation for the id field. + sourcedata.DefaultID = sourcedataDescID.Default.(func() uuid.UUID) + toolMixin := schema.Tool{}.Mixin() + toolMixinHooks1 := toolMixin[1].Hooks() + tool.Hooks[0] = toolMixinHooks1[0] + toolMixinFields0 := toolMixin[0].Fields() + _ = toolMixinFields0 + toolMixinFields1 := toolMixin[1].Fields() + _ = toolMixinFields1 + toolFields := schema.Tool{}.Fields() + _ = toolFields + // toolDescDocumentID is the schema descriptor for document_id field. + toolDescDocumentID := toolMixinFields0[0].Descriptor() + // tool.DefaultDocumentID holds the default value on creation for the document_id field. + tool.DefaultDocumentID = toolDescDocumentID.Default.(func() uuid.UUID) + // toolDescID is the schema descriptor for id field. + toolDescID := toolMixinFields1[0].Descriptor() + // tool.DefaultID holds the default value on creation for the id field. + tool.DefaultID = toolDescID.Default.(func() uuid.UUID) +} const ( Version = "v0.14.1" // Version of ent codegen. diff --git a/internal/backends/ent/schema/document_type.go b/internal/backends/ent/schema/document_type.go index 5c37963..2d98144 100644 --- a/internal/backends/ent/schema/document_type.go +++ b/internal/backends/ent/schema/document_type.go @@ -23,7 +23,6 @@ func (DocumentType) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.DocumentType]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/edge_type.go b/internal/backends/ent/schema/edge_type.go index 748d922..d801d00 100644 --- a/internal/backends/ent/schema/edge_type.go +++ b/internal/backends/ent/schema/edge_type.go @@ -24,7 +24,6 @@ func (EdgeType) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.Edge]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/external_reference.go b/internal/backends/ent/schema/external_reference.go index 9ea88ec..05a58cc 100644 --- a/internal/backends/ent/schema/external_reference.go +++ b/internal/backends/ent/schema/external_reference.go @@ -22,7 +22,6 @@ func (ExternalReference) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.ExternalReference]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/metadata.go b/internal/backends/ent/schema/metadata.go index 87b4dc3..cab10e4 100644 --- a/internal/backends/ent/schema/metadata.go +++ b/internal/backends/ent/schema/metadata.go @@ -22,7 +22,6 @@ type Metadata struct { func (Metadata) Mixin() []ent.Mixin { return []ent.Mixin{ ProtoMessageMixin[*sbom.Metadata]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/mixin.go b/internal/backends/ent/schema/mixin.go index 7f60b64..8a2f79f 100644 --- a/internal/backends/ent/schema/mixin.go +++ b/internal/backends/ent/schema/mixin.go @@ -7,6 +7,10 @@ package schema import ( + "context" + "crypto/sha256" + "fmt" + "entgo.io/ent" "entgo.io/ent/dialect/entsql" "entgo.io/ent/schema" @@ -16,8 +20,12 @@ import ( "github.com/google/uuid" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/protobom/storage/internal/backends/ent/hook" ) +const protoMessageField = "proto_message" + type ( // DocumentMixin adds the `document` edge and corresponding `document_id` edge field. DocumentMixin struct { @@ -26,7 +34,7 @@ type ( // ProtoMessageMixin adds the `proto_message` field containing the wire format bytes. ProtoMessageMixin[T proto.Message] struct { - mixin.Schema + UUIDMixin } // UUIDMixin replaces the default integer `id` field with a generated UUID. @@ -60,11 +68,22 @@ func (DocumentMixin) Edges() []ent.Edge { } } -func (ProtoMessageMixin[T]) Fields() []ent.Field { +func (pmm ProtoMessageMixin[T]) Fields() []ent.Field { var goType T - return []ent.Field{ - field.Bytes("proto_message").GoType(goType).Nillable().Immutable(), + return append( + pmm.UUIDMixin.Fields(), + field.Bytes(protoMessageField). + GoType(goType). + Nillable(). + Unique(). + Immutable(), + ) +} + +func (ProtoMessageMixin[T]) Hooks() []ent.Hook { + return []ent.Hook{ + hook.On(uuidHook, ent.OpCreate|ent.OpUpdate|ent.OpUpdateOne), } } @@ -89,3 +108,38 @@ func enumValues(enum protoreflect.Enum) []string { return values } + +func uuidHook(next ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(ctx context.Context, mutation ent.Mutation) (ent.Value, error) { + // Get the value of the `proto_message` field being set as part of this mutation. + value, fieldSet := mutation.Field(protoMessageField) + + // Assert that the value of the field has type `proto.Message`. + protoMessage, ok := value.(proto.Message) + if !(fieldSet && ok) { + return next.Mutate(ctx, mutation) + } + + // Deterministically generate the wire-format encoding of the protobuf message. + data, err := proto.MarshalOptions{Deterministic: true}.Marshal(protoMessage) + if err != nil { + return mutation, fmt.Errorf("marshaling proto: %w", err) + } + + // Generate a UUID by hashing the wire-format bytes of the protobuf message. + uuidHash := uuid.NewHash(sha256.New(), uuid.Max, data, int(uuid.Max.Version())) + + type IDMutation interface { + ent.Mutation + SetID(uuid.UUID) + } + + // Set the generated UUID as the value to be inserted as part of this mutation. + if mut, ok := any(mutation).(IDMutation); ok { + mut.SetID(uuidHash) + mutation = mut + } + + return next.Mutate(ctx, mutation) + }) +} diff --git a/internal/backends/ent/schema/node.go b/internal/backends/ent/schema/node.go index 619a285..40148d4 100644 --- a/internal/backends/ent/schema/node.go +++ b/internal/backends/ent/schema/node.go @@ -24,7 +24,6 @@ func (Node) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.Node]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/node_list.go b/internal/backends/ent/schema/node_list.go index 5bb81c9..75c3696 100644 --- a/internal/backends/ent/schema/node_list.go +++ b/internal/backends/ent/schema/node_list.go @@ -21,7 +21,6 @@ type NodeList struct { func (NodeList) Mixin() []ent.Mixin { return []ent.Mixin{ ProtoMessageMixin[*sbom.NodeList]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/person.go b/internal/backends/ent/schema/person.go index 80fc035..1b9ea59 100644 --- a/internal/backends/ent/schema/person.go +++ b/internal/backends/ent/schema/person.go @@ -24,7 +24,6 @@ func (Person) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.Person]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/property.go b/internal/backends/ent/schema/property.go index 7d85a9c..8c577f4 100644 --- a/internal/backends/ent/schema/property.go +++ b/internal/backends/ent/schema/property.go @@ -23,7 +23,6 @@ func (Property) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.Property]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/source_data.go b/internal/backends/ent/schema/source_data.go index 5abb86b..5ad9856 100644 --- a/internal/backends/ent/schema/source_data.go +++ b/internal/backends/ent/schema/source_data.go @@ -23,7 +23,6 @@ func (SourceData) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.SourceData]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/schema/tool.go b/internal/backends/ent/schema/tool.go index c9712f6..c5efb6b 100644 --- a/internal/backends/ent/schema/tool.go +++ b/internal/backends/ent/schema/tool.go @@ -23,7 +23,6 @@ func (Tool) Mixin() []ent.Mixin { return []ent.Mixin{ DocumentMixin{}, ProtoMessageMixin[*sbom.Tool]{}, - UUIDMixin{}, } } diff --git a/internal/backends/ent/sourcedata/sourcedata.go b/internal/backends/ent/sourcedata/sourcedata.go index 3cec1d3..a2e4f4a 100644 --- a/internal/backends/ent/sourcedata/sourcedata.go +++ b/internal/backends/ent/sourcedata/sourcedata.go @@ -8,6 +8,7 @@ package sourcedata import ( + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -76,7 +77,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/sourcedata_create.go b/internal/backends/ent/sourcedata_create.go index 69f7bc1..1265656 100644 --- a/internal/backends/ent/sourcedata_create.go +++ b/internal/backends/ent/sourcedata_create.go @@ -120,7 +120,9 @@ func (sdc *SourceDataCreate) Mutation() *SourceDataMutation { // Save creates the SourceData in the database. func (sdc *SourceDataCreate) Save(ctx context.Context) (*SourceData, error) { - sdc.defaults() + if err := sdc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, sdc.sqlSave, sdc.mutation, sdc.hooks) } @@ -147,15 +149,22 @@ func (sdc *SourceDataCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (sdc *SourceDataCreate) defaults() { +func (sdc *SourceDataCreate) defaults() error { if _, ok := sdc.mutation.DocumentID(); !ok { + if sourcedata.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized sourcedata.DefaultDocumentID (forgotten import ent/runtime?)") + } v := sourcedata.DefaultDocumentID() sdc.mutation.SetDocumentID(v) } if _, ok := sdc.mutation.ID(); !ok { + if sourcedata.DefaultID == nil { + return fmt.Errorf("ent: uninitialized sourcedata.DefaultID (forgotten import ent/runtime?)") + } v := sourcedata.DefaultID() sdc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder. diff --git a/internal/backends/ent/tool/tool.go b/internal/backends/ent/tool/tool.go index 341a845..398f4bb 100644 --- a/internal/backends/ent/tool/tool.go +++ b/internal/backends/ent/tool/tool.go @@ -8,6 +8,7 @@ package tool import ( + "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" @@ -73,7 +74,13 @@ func ValidColumn(column string) bool { return false } +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/protobom/storage/internal/backends/ent/runtime" var ( + Hooks [1]ent.Hook // DefaultDocumentID holds the default value on creation for the "document_id" field. DefaultDocumentID func() uuid.UUID // DefaultID holds the default value on creation for the "id" field. diff --git a/internal/backends/ent/tool_create.go b/internal/backends/ent/tool_create.go index b4b4079..e65ce3d 100644 --- a/internal/backends/ent/tool_create.go +++ b/internal/backends/ent/tool_create.go @@ -114,7 +114,9 @@ func (tc *ToolCreate) Mutation() *ToolMutation { // Save creates the Tool in the database. func (tc *ToolCreate) Save(ctx context.Context) (*Tool, error) { - tc.defaults() + if err := tc.defaults(); err != nil { + return nil, err + } return withHooks(ctx, tc.sqlSave, tc.mutation, tc.hooks) } @@ -141,15 +143,22 @@ func (tc *ToolCreate) ExecX(ctx context.Context) { } // defaults sets the default values of the builder before save. -func (tc *ToolCreate) defaults() { +func (tc *ToolCreate) defaults() error { if _, ok := tc.mutation.DocumentID(); !ok { + if tool.DefaultDocumentID == nil { + return fmt.Errorf("ent: uninitialized tool.DefaultDocumentID (forgotten import ent/runtime?)") + } v := tool.DefaultDocumentID() tc.mutation.SetDocumentID(v) } if _, ok := tc.mutation.ID(); !ok { + if tool.DefaultID == nil { + return fmt.Errorf("ent: uninitialized tool.DefaultID (forgotten import ent/runtime?)") + } v := tool.DefaultID() tc.mutation.SetID(v) } + return nil } // check runs all checks and user-defined validators on the builder.