From bc5d937c7f1b73f01ed397eba2615e60b1da8eb0 Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Sat, 10 Sep 2022 17:06:59 -0800 Subject: [PATCH] add attachments type and repository --- backend/app/api/docs/docs.go | 149 ++++ backend/app/api/docs/swagger.json | 149 ++++ backend/app/api/docs/swagger.yaml | 112 +++ backend/ent/attachment.go | 197 +++++ backend/ent/attachment/attachment.go | 112 +++ backend/ent/attachment/where.go | 349 ++++++++ backend/ent/attachment_create.go | 402 +++++++++ backend/ent/attachment_delete.go | 115 +++ backend/ent/attachment_query.go | 683 +++++++++++++++ backend/ent/attachment_update.go | 587 +++++++++++++ backend/ent/client.go | 163 +++- backend/ent/config.go | 1 + backend/ent/document.go | 18 +- backend/ent/document/document.go | 9 + backend/ent/document/where.go | 28 + backend/ent/document_create.go | 35 + backend/ent/document_query.go | 77 +- backend/ent/document_update.go | 181 ++++ backend/ent/ent.go | 2 + backend/ent/hook/hook.go | 13 + backend/ent/item.go | 18 +- backend/ent/item/item.go | 9 + backend/ent/item/where.go | 28 + backend/ent/item_create.go | 35 + backend/ent/item_query.go | 117 ++- backend/ent/item_update.go | 181 ++++ backend/ent/migrate/schema.go | 32 + backend/ent/mutation.go | 807 +++++++++++++++++- backend/ent/predicate/predicate.go | 3 + backend/ent/runtime.go | 20 + backend/ent/schema/attachment.go | 42 + backend/ent/schema/document.go | 4 + backend/ent/schema/item.go | 11 +- backend/ent/tx.go | 5 +- .../internal/repo/repo_item_attachments.go | 44 + .../repo/repo_item_attachments_test.go | 133 +++ backend/internal/repo/repo_items.go | 3 + backend/internal/repo/repo_items_test.go | 22 +- backend/internal/repo/repos_all.go | 34 +- backend/internal/types/document_types.go | 11 +- backend/internal/types/item_types.go | 8 + 41 files changed, 4844 insertions(+), 105 deletions(-) create mode 100644 backend/ent/attachment.go create mode 100644 backend/ent/attachment/attachment.go create mode 100644 backend/ent/attachment/where.go create mode 100644 backend/ent/attachment_create.go create mode 100644 backend/ent/attachment_delete.go create mode 100644 backend/ent/attachment_query.go create mode 100644 backend/ent/attachment_update.go create mode 100644 backend/ent/schema/attachment.go create mode 100644 backend/internal/repo/repo_item_attachments.go create mode 100644 backend/internal/repo/repo_item_attachments_test.go diff --git a/backend/app/api/docs/docs.go b/backend/app/api/docs/docs.go index 0982e99..7c479c2 100644 --- a/backend/app/api/docs/docs.go +++ b/backend/app/api/docs/docs.go @@ -788,6 +788,44 @@ const docTemplate = `{ } }, "definitions": { + "ent.Attachment": { + "type": "object", + "properties": { + "created_at": { + "description": "CreatedAt holds the value of the \"created_at\" field.", + "type": "string" + }, + "edges": { + "description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the AttachmentQuery when eager-loading is set.", + "$ref": "#/definitions/ent.AttachmentEdges" + }, + "id": { + "description": "ID of the ent.", + "type": "string" + }, + "type": { + "description": "Type holds the value of the \"type\" field.", + "type": "string" + }, + "updated_at": { + "description": "UpdatedAt holds the value of the \"updated_at\" field.", + "type": "string" + } + } + }, + "ent.AttachmentEdges": { + "type": "object", + "properties": { + "document": { + "description": "Document holds the value of the document edge.", + "$ref": "#/definitions/ent.Document" + }, + "item": { + "description": "Item holds the value of the item edge.", + "$ref": "#/definitions/ent.Item" + } + } + }, "ent.AuthTokens": { "type": "object", "properties": { @@ -829,6 +867,103 @@ const docTemplate = `{ } } }, + "ent.Document": { + "type": "object", + "properties": { + "created_at": { + "description": "CreatedAt holds the value of the \"created_at\" field.", + "type": "string" + }, + "edges": { + "description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the DocumentQuery when eager-loading is set.", + "$ref": "#/definitions/ent.DocumentEdges" + }, + "id": { + "description": "ID of the ent.", + "type": "string" + }, + "path": { + "description": "Path holds the value of the \"path\" field.", + "type": "string" + }, + "title": { + "description": "Title holds the value of the \"title\" field.", + "type": "string" + }, + "updated_at": { + "description": "UpdatedAt holds the value of the \"updated_at\" field.", + "type": "string" + } + } + }, + "ent.DocumentEdges": { + "type": "object", + "properties": { + "attachments": { + "description": "Attachments holds the value of the attachments edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.Attachment" + } + }, + "document_tokens": { + "description": "DocumentTokens holds the value of the document_tokens edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.DocumentToken" + } + }, + "group": { + "description": "Group holds the value of the group edge.", + "$ref": "#/definitions/ent.Group" + } + } + }, + "ent.DocumentToken": { + "type": "object", + "properties": { + "created_at": { + "description": "CreatedAt holds the value of the \"created_at\" field.", + "type": "string" + }, + "edges": { + "description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the DocumentTokenQuery when eager-loading is set.", + "$ref": "#/definitions/ent.DocumentTokenEdges" + }, + "expires_at": { + "description": "ExpiresAt holds the value of the \"expires_at\" field.", + "type": "string" + }, + "id": { + "description": "ID of the ent.", + "type": "string" + }, + "token": { + "description": "Token holds the value of the \"token\" field.", + "type": "array", + "items": { + "type": "integer" + } + }, + "updated_at": { + "description": "UpdatedAt holds the value of the \"updated_at\" field.", + "type": "string" + }, + "uses": { + "description": "Uses holds the value of the \"uses\" field.", + "type": "integer" + } + } + }, + "ent.DocumentTokenEdges": { + "type": "object", + "properties": { + "document": { + "description": "Document holds the value of the document edge.", + "$ref": "#/definitions/ent.Document" + } + } + }, "ent.Group": { "type": "object", "properties": { @@ -861,6 +996,13 @@ const docTemplate = `{ "ent.GroupEdges": { "type": "object", "properties": { + "documents": { + "description": "Documents holds the value of the documents edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.Document" + } + }, "items": { "description": "Items holds the value of the items edge.", "type": "array", @@ -979,6 +1121,13 @@ const docTemplate = `{ "ent.ItemEdges": { "type": "object", "properties": { + "attachments": { + "description": "Attachments holds the value of the attachments edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.Attachment" + } + }, "fields": { "description": "Fields holds the value of the fields edge.", "type": "array", diff --git a/backend/app/api/docs/swagger.json b/backend/app/api/docs/swagger.json index a8e0318..be5f31d 100644 --- a/backend/app/api/docs/swagger.json +++ b/backend/app/api/docs/swagger.json @@ -780,6 +780,44 @@ } }, "definitions": { + "ent.Attachment": { + "type": "object", + "properties": { + "created_at": { + "description": "CreatedAt holds the value of the \"created_at\" field.", + "type": "string" + }, + "edges": { + "description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the AttachmentQuery when eager-loading is set.", + "$ref": "#/definitions/ent.AttachmentEdges" + }, + "id": { + "description": "ID of the ent.", + "type": "string" + }, + "type": { + "description": "Type holds the value of the \"type\" field.", + "type": "string" + }, + "updated_at": { + "description": "UpdatedAt holds the value of the \"updated_at\" field.", + "type": "string" + } + } + }, + "ent.AttachmentEdges": { + "type": "object", + "properties": { + "document": { + "description": "Document holds the value of the document edge.", + "$ref": "#/definitions/ent.Document" + }, + "item": { + "description": "Item holds the value of the item edge.", + "$ref": "#/definitions/ent.Item" + } + } + }, "ent.AuthTokens": { "type": "object", "properties": { @@ -821,6 +859,103 @@ } } }, + "ent.Document": { + "type": "object", + "properties": { + "created_at": { + "description": "CreatedAt holds the value of the \"created_at\" field.", + "type": "string" + }, + "edges": { + "description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the DocumentQuery when eager-loading is set.", + "$ref": "#/definitions/ent.DocumentEdges" + }, + "id": { + "description": "ID of the ent.", + "type": "string" + }, + "path": { + "description": "Path holds the value of the \"path\" field.", + "type": "string" + }, + "title": { + "description": "Title holds the value of the \"title\" field.", + "type": "string" + }, + "updated_at": { + "description": "UpdatedAt holds the value of the \"updated_at\" field.", + "type": "string" + } + } + }, + "ent.DocumentEdges": { + "type": "object", + "properties": { + "attachments": { + "description": "Attachments holds the value of the attachments edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.Attachment" + } + }, + "document_tokens": { + "description": "DocumentTokens holds the value of the document_tokens edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.DocumentToken" + } + }, + "group": { + "description": "Group holds the value of the group edge.", + "$ref": "#/definitions/ent.Group" + } + } + }, + "ent.DocumentToken": { + "type": "object", + "properties": { + "created_at": { + "description": "CreatedAt holds the value of the \"created_at\" field.", + "type": "string" + }, + "edges": { + "description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the DocumentTokenQuery when eager-loading is set.", + "$ref": "#/definitions/ent.DocumentTokenEdges" + }, + "expires_at": { + "description": "ExpiresAt holds the value of the \"expires_at\" field.", + "type": "string" + }, + "id": { + "description": "ID of the ent.", + "type": "string" + }, + "token": { + "description": "Token holds the value of the \"token\" field.", + "type": "array", + "items": { + "type": "integer" + } + }, + "updated_at": { + "description": "UpdatedAt holds the value of the \"updated_at\" field.", + "type": "string" + }, + "uses": { + "description": "Uses holds the value of the \"uses\" field.", + "type": "integer" + } + } + }, + "ent.DocumentTokenEdges": { + "type": "object", + "properties": { + "document": { + "description": "Document holds the value of the document edge.", + "$ref": "#/definitions/ent.Document" + } + } + }, "ent.Group": { "type": "object", "properties": { @@ -853,6 +988,13 @@ "ent.GroupEdges": { "type": "object", "properties": { + "documents": { + "description": "Documents holds the value of the documents edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.Document" + } + }, "items": { "description": "Items holds the value of the items edge.", "type": "array", @@ -971,6 +1113,13 @@ "ent.ItemEdges": { "type": "object", "properties": { + "attachments": { + "description": "Attachments holds the value of the attachments edge.", + "type": "array", + "items": { + "$ref": "#/definitions/ent.Attachment" + } + }, "fields": { "description": "Fields holds the value of the fields edge.", "type": "array", diff --git a/backend/app/api/docs/swagger.yaml b/backend/app/api/docs/swagger.yaml index cfa5bf5..57a0218 100644 --- a/backend/app/api/docs/swagger.yaml +++ b/backend/app/api/docs/swagger.yaml @@ -1,5 +1,34 @@ basePath: /api definitions: + ent.Attachment: + properties: + created_at: + description: CreatedAt holds the value of the "created_at" field. + type: string + edges: + $ref: '#/definitions/ent.AttachmentEdges' + description: |- + Edges holds the relations/edges for other nodes in the graph. + The values are being populated by the AttachmentQuery when eager-loading is set. + id: + description: ID of the ent. + type: string + type: + description: Type holds the value of the "type" field. + type: string + updated_at: + description: UpdatedAt holds the value of the "updated_at" field. + type: string + type: object + ent.AttachmentEdges: + properties: + document: + $ref: '#/definitions/ent.Document' + description: Document holds the value of the document edge. + item: + $ref: '#/definitions/ent.Item' + description: Item holds the value of the item edge. + type: object ent.AuthTokens: properties: created_at: @@ -31,6 +60,79 @@ definitions: $ref: '#/definitions/ent.User' description: User holds the value of the user edge. type: object + ent.Document: + properties: + created_at: + description: CreatedAt holds the value of the "created_at" field. + type: string + edges: + $ref: '#/definitions/ent.DocumentEdges' + description: |- + Edges holds the relations/edges for other nodes in the graph. + The values are being populated by the DocumentQuery when eager-loading is set. + id: + description: ID of the ent. + type: string + path: + description: Path holds the value of the "path" field. + type: string + title: + description: Title holds the value of the "title" field. + type: string + updated_at: + description: UpdatedAt holds the value of the "updated_at" field. + type: string + type: object + ent.DocumentEdges: + properties: + attachments: + description: Attachments holds the value of the attachments edge. + items: + $ref: '#/definitions/ent.Attachment' + type: array + document_tokens: + description: DocumentTokens holds the value of the document_tokens edge. + items: + $ref: '#/definitions/ent.DocumentToken' + type: array + group: + $ref: '#/definitions/ent.Group' + description: Group holds the value of the group edge. + type: object + ent.DocumentToken: + properties: + created_at: + description: CreatedAt holds the value of the "created_at" field. + type: string + edges: + $ref: '#/definitions/ent.DocumentTokenEdges' + description: |- + Edges holds the relations/edges for other nodes in the graph. + The values are being populated by the DocumentTokenQuery when eager-loading is set. + expires_at: + description: ExpiresAt holds the value of the "expires_at" field. + type: string + id: + description: ID of the ent. + type: string + token: + description: Token holds the value of the "token" field. + items: + type: integer + type: array + updated_at: + description: UpdatedAt holds the value of the "updated_at" field. + type: string + uses: + description: Uses holds the value of the "uses" field. + type: integer + type: object + ent.DocumentTokenEdges: + properties: + document: + $ref: '#/definitions/ent.Document' + description: Document holds the value of the document edge. + type: object ent.Group: properties: created_at: @@ -56,6 +158,11 @@ definitions: type: object ent.GroupEdges: properties: + documents: + description: Documents holds the value of the documents edge. + items: + $ref: '#/definitions/ent.Document' + type: array items: description: Items holds the value of the items edge. items: @@ -144,6 +251,11 @@ definitions: type: object ent.ItemEdges: properties: + attachments: + description: Attachments holds the value of the attachments edge. + items: + $ref: '#/definitions/ent.Attachment' + type: array fields: description: Fields holds the value of the fields edge. items: diff --git a/backend/ent/attachment.go b/backend/ent/attachment.go new file mode 100644 index 0000000..b22b8db --- /dev/null +++ b/backend/ent/attachment.go @@ -0,0 +1,197 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/ent/dialect/sql" + "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" + "github.com/hay-kot/content/backend/ent/document" + "github.com/hay-kot/content/backend/ent/item" +) + +// Attachment is the model entity for the Attachment schema. +type Attachment struct { + config `json:"-"` + // ID of the ent. + ID uuid.UUID `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt time.Time `json:"updated_at,omitempty"` + // Type holds the value of the "type" field. + Type attachment.Type `json:"type,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the AttachmentQuery when eager-loading is set. + Edges AttachmentEdges `json:"edges"` + document_attachments *uuid.UUID + item_attachments *uuid.UUID +} + +// AttachmentEdges holds the relations/edges for other nodes in the graph. +type AttachmentEdges struct { + // Item holds the value of the item edge. + Item *Item `json:"item,omitempty"` + // Document holds the value of the document edge. + Document *Document `json:"document,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]bool +} + +// ItemOrErr returns the Item value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e AttachmentEdges) ItemOrErr() (*Item, error) { + if e.loadedTypes[0] { + if e.Item == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: item.Label} + } + return e.Item, nil + } + return nil, &NotLoadedError{edge: "item"} +} + +// DocumentOrErr returns the Document value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e AttachmentEdges) DocumentOrErr() (*Document, error) { + if e.loadedTypes[1] { + if e.Document == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: document.Label} + } + return e.Document, nil + } + return nil, &NotLoadedError{edge: "document"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Attachment) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case attachment.FieldType: + values[i] = new(sql.NullString) + case attachment.FieldCreatedAt, attachment.FieldUpdatedAt: + values[i] = new(sql.NullTime) + case attachment.FieldID: + values[i] = new(uuid.UUID) + case attachment.ForeignKeys[0]: // document_attachments + values[i] = &sql.NullScanner{S: new(uuid.UUID)} + case attachment.ForeignKeys[1]: // item_attachments + values[i] = &sql.NullScanner{S: new(uuid.UUID)} + default: + return nil, fmt.Errorf("unexpected column %q for type Attachment", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Attachment fields. +func (a *Attachment) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case attachment.FieldID: + if value, ok := values[i].(*uuid.UUID); !ok { + return fmt.Errorf("unexpected type %T for field id", values[i]) + } else if value != nil { + a.ID = *value + } + case attachment.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + a.CreatedAt = value.Time + } + case attachment.FieldUpdatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value.Valid { + a.UpdatedAt = value.Time + } + case attachment.FieldType: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field type", values[i]) + } else if value.Valid { + a.Type = attachment.Type(value.String) + } + case attachment.ForeignKeys[0]: + if value, ok := values[i].(*sql.NullScanner); !ok { + return fmt.Errorf("unexpected type %T for field document_attachments", values[i]) + } else if value.Valid { + a.document_attachments = new(uuid.UUID) + *a.document_attachments = *value.S.(*uuid.UUID) + } + case attachment.ForeignKeys[1]: + if value, ok := values[i].(*sql.NullScanner); !ok { + return fmt.Errorf("unexpected type %T for field item_attachments", values[i]) + } else if value.Valid { + a.item_attachments = new(uuid.UUID) + *a.item_attachments = *value.S.(*uuid.UUID) + } + } + } + return nil +} + +// QueryItem queries the "item" edge of the Attachment entity. +func (a *Attachment) QueryItem() *ItemQuery { + return (&AttachmentClient{config: a.config}).QueryItem(a) +} + +// QueryDocument queries the "document" edge of the Attachment entity. +func (a *Attachment) QueryDocument() *DocumentQuery { + return (&AttachmentClient{config: a.config}).QueryDocument(a) +} + +// Update returns a builder for updating this Attachment. +// Note that you need to call Attachment.Unwrap() before calling this method if this Attachment +// was returned from a transaction, and the transaction was committed or rolled back. +func (a *Attachment) Update() *AttachmentUpdateOne { + return (&AttachmentClient{config: a.config}).UpdateOne(a) +} + +// Unwrap unwraps the Attachment entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (a *Attachment) Unwrap() *Attachment { + _tx, ok := a.config.driver.(*txDriver) + if !ok { + panic("ent: Attachment is not a transactional entity") + } + a.config.driver = _tx.drv + return a +} + +// String implements the fmt.Stringer. +func (a *Attachment) String() string { + var builder strings.Builder + builder.WriteString("Attachment(") + builder.WriteString(fmt.Sprintf("id=%v, ", a.ID)) + builder.WriteString("created_at=") + builder.WriteString(a.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(a.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("type=") + builder.WriteString(fmt.Sprintf("%v", a.Type)) + builder.WriteByte(')') + return builder.String() +} + +// Attachments is a parsable slice of Attachment. +type Attachments []*Attachment + +func (a Attachments) config(cfg config) { + for _i := range a { + a[_i].config = cfg + } +} diff --git a/backend/ent/attachment/attachment.go b/backend/ent/attachment/attachment.go new file mode 100644 index 0000000..d2775e2 --- /dev/null +++ b/backend/ent/attachment/attachment.go @@ -0,0 +1,112 @@ +// Code generated by ent, DO NOT EDIT. + +package attachment + +import ( + "fmt" + "time" + + "github.com/google/uuid" +) + +const ( + // Label holds the string label denoting the attachment type in the database. + Label = "attachment" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldType holds the string denoting the type field in the database. + FieldType = "type" + // EdgeItem holds the string denoting the item edge name in mutations. + EdgeItem = "item" + // EdgeDocument holds the string denoting the document edge name in mutations. + EdgeDocument = "document" + // Table holds the table name of the attachment in the database. + Table = "attachments" + // ItemTable is the table that holds the item relation/edge. + ItemTable = "attachments" + // ItemInverseTable is the table name for the Item entity. + // It exists in this package in order to avoid circular dependency with the "item" package. + ItemInverseTable = "items" + // ItemColumn is the table column denoting the item relation/edge. + ItemColumn = "item_attachments" + // DocumentTable is the table that holds the document relation/edge. + DocumentTable = "attachments" + // DocumentInverseTable is the table name for the Document entity. + // It exists in this package in order to avoid circular dependency with the "document" package. + DocumentInverseTable = "documents" + // DocumentColumn is the table column denoting the document relation/edge. + DocumentColumn = "document_attachments" +) + +// Columns holds all SQL columns for attachment fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldType, +} + +// ForeignKeys holds the SQL foreign-keys that are owned by the "attachments" +// table and are not defined as standalone fields in the schema. +var ForeignKeys = []string{ + "document_attachments", + "item_attachments", +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + for i := range ForeignKeys { + if column == ForeignKeys[i] { + return true + } + } + return false +} + +var ( + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() time.Time + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() time.Time + // DefaultID holds the default value on creation for the "id" field. + DefaultID func() uuid.UUID +) + +// Type defines the type for the "type" enum field. +type Type string + +// TypeAttachment is the default value of the Type enum. +const DefaultType = TypeAttachment + +// Type values. +const ( + TypePhoto Type = "photo" + TypeManual Type = "manual" + TypeWarranty Type = "warranty" + TypeAttachment Type = "attachment" +) + +func (_type Type) String() string { + return string(_type) +} + +// TypeValidator is a validator for the "type" field enum values. It is called by the builders before save. +func TypeValidator(_type Type) error { + switch _type { + case TypePhoto, TypeManual, TypeWarranty, TypeAttachment: + return nil + default: + return fmt.Errorf("attachment: invalid enum value for type field: %q", _type) + } +} diff --git a/backend/ent/attachment/where.go b/backend/ent/attachment/where.go new file mode 100644 index 0000000..c601949 --- /dev/null +++ b/backend/ent/attachment/where.go @@ -0,0 +1,349 @@ +// Code generated by ent, DO NOT EDIT. + +package attachment + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id uuid.UUID) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCreatedAt), v)) + }) +} + +// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ. +func UpdatedAt(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldUpdatedAt), v)) + }) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.Attachment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.In(s.C(FieldCreatedAt), v...)) + }) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.Attachment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.NotIn(s.C(FieldCreatedAt), v...)) + }) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldCreatedAt), v)) + }) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldUpdatedAt), v)) + }) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldUpdatedAt), v)) + }) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.Attachment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.In(s.C(FieldUpdatedAt), v...)) + }) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.Attachment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.NotIn(s.C(FieldUpdatedAt), v...)) + }) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldUpdatedAt), v)) + }) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldUpdatedAt), v)) + }) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldUpdatedAt), v)) + }) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldUpdatedAt), v)) + }) +} + +// TypeEQ applies the EQ predicate on the "type" field. +func TypeEQ(v Type) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldType), v)) + }) +} + +// TypeNEQ applies the NEQ predicate on the "type" field. +func TypeNEQ(v Type) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldType), v)) + }) +} + +// TypeIn applies the In predicate on the "type" field. +func TypeIn(vs ...Type) predicate.Attachment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.In(s.C(FieldType), v...)) + }) +} + +// TypeNotIn applies the NotIn predicate on the "type" field. +func TypeNotIn(vs ...Type) predicate.Attachment { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.NotIn(s.C(FieldType), v...)) + }) +} + +// HasItem applies the HasEdge predicate on the "item" edge. +func HasItem() predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ItemTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ItemTable, ItemColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasItemWith applies the HasEdge predicate on the "item" edge with a given conditions (other predicates). +func HasItemWith(preds ...predicate.Item) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ItemInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ItemTable, ItemColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasDocument applies the HasEdge predicate on the "document" edge. +func HasDocument() predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(DocumentTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, DocumentTable, DocumentColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasDocumentWith applies the HasEdge predicate on the "document" edge with a given conditions (other predicates). +func HasDocumentWith(preds ...predicate.Document) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(DocumentInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, DocumentTable, DocumentColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Attachment) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Attachment) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Attachment) predicate.Attachment { + return predicate.Attachment(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/backend/ent/attachment_create.go b/backend/ent/attachment_create.go new file mode 100644 index 0000000..fdce24b --- /dev/null +++ b/backend/ent/attachment_create.go @@ -0,0 +1,402 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" + "github.com/hay-kot/content/backend/ent/document" + "github.com/hay-kot/content/backend/ent/item" +) + +// AttachmentCreate is the builder for creating a Attachment entity. +type AttachmentCreate struct { + config + mutation *AttachmentMutation + hooks []Hook +} + +// SetCreatedAt sets the "created_at" field. +func (ac *AttachmentCreate) SetCreatedAt(t time.Time) *AttachmentCreate { + ac.mutation.SetCreatedAt(t) + return ac +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (ac *AttachmentCreate) SetNillableCreatedAt(t *time.Time) *AttachmentCreate { + if t != nil { + ac.SetCreatedAt(*t) + } + return ac +} + +// SetUpdatedAt sets the "updated_at" field. +func (ac *AttachmentCreate) SetUpdatedAt(t time.Time) *AttachmentCreate { + ac.mutation.SetUpdatedAt(t) + return ac +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (ac *AttachmentCreate) SetNillableUpdatedAt(t *time.Time) *AttachmentCreate { + if t != nil { + ac.SetUpdatedAt(*t) + } + return ac +} + +// SetType sets the "type" field. +func (ac *AttachmentCreate) SetType(a attachment.Type) *AttachmentCreate { + ac.mutation.SetType(a) + return ac +} + +// SetNillableType sets the "type" field if the given value is not nil. +func (ac *AttachmentCreate) SetNillableType(a *attachment.Type) *AttachmentCreate { + if a != nil { + ac.SetType(*a) + } + return ac +} + +// SetID sets the "id" field. +func (ac *AttachmentCreate) SetID(u uuid.UUID) *AttachmentCreate { + ac.mutation.SetID(u) + return ac +} + +// SetNillableID sets the "id" field if the given value is not nil. +func (ac *AttachmentCreate) SetNillableID(u *uuid.UUID) *AttachmentCreate { + if u != nil { + ac.SetID(*u) + } + return ac +} + +// SetItemID sets the "item" edge to the Item entity by ID. +func (ac *AttachmentCreate) SetItemID(id uuid.UUID) *AttachmentCreate { + ac.mutation.SetItemID(id) + return ac +} + +// SetItem sets the "item" edge to the Item entity. +func (ac *AttachmentCreate) SetItem(i *Item) *AttachmentCreate { + return ac.SetItemID(i.ID) +} + +// SetDocumentID sets the "document" edge to the Document entity by ID. +func (ac *AttachmentCreate) SetDocumentID(id uuid.UUID) *AttachmentCreate { + ac.mutation.SetDocumentID(id) + return ac +} + +// SetDocument sets the "document" edge to the Document entity. +func (ac *AttachmentCreate) SetDocument(d *Document) *AttachmentCreate { + return ac.SetDocumentID(d.ID) +} + +// Mutation returns the AttachmentMutation object of the builder. +func (ac *AttachmentCreate) Mutation() *AttachmentMutation { + return ac.mutation +} + +// Save creates the Attachment in the database. +func (ac *AttachmentCreate) Save(ctx context.Context) (*Attachment, error) { + var ( + err error + node *Attachment + ) + ac.defaults() + if len(ac.hooks) == 0 { + if err = ac.check(); err != nil { + return nil, err + } + node, err = ac.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*AttachmentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = ac.check(); err != nil { + return nil, err + } + ac.mutation = mutation + if node, err = ac.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(ac.hooks) - 1; i >= 0; i-- { + if ac.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = ac.hooks[i](mut) + } + v, err := mut.Mutate(ctx, ac.mutation) + if err != nil { + return nil, err + } + nv, ok := v.(*Attachment) + if !ok { + return nil, fmt.Errorf("unexpected node type %T returned from AttachmentMutation", v) + } + node = nv + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (ac *AttachmentCreate) SaveX(ctx context.Context) *Attachment { + v, err := ac.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ac *AttachmentCreate) Exec(ctx context.Context) error { + _, err := ac.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ac *AttachmentCreate) ExecX(ctx context.Context) { + if err := ac.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ac *AttachmentCreate) defaults() { + if _, ok := ac.mutation.CreatedAt(); !ok { + v := attachment.DefaultCreatedAt() + ac.mutation.SetCreatedAt(v) + } + if _, ok := ac.mutation.UpdatedAt(); !ok { + v := attachment.DefaultUpdatedAt() + ac.mutation.SetUpdatedAt(v) + } + if _, ok := ac.mutation.GetType(); !ok { + v := attachment.DefaultType + ac.mutation.SetType(v) + } + if _, ok := ac.mutation.ID(); !ok { + v := attachment.DefaultID() + ac.mutation.SetID(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (ac *AttachmentCreate) check() error { + if _, ok := ac.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Attachment.created_at"`)} + } + if _, ok := ac.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Attachment.updated_at"`)} + } + if _, ok := ac.mutation.GetType(); !ok { + return &ValidationError{Name: "type", err: errors.New(`ent: missing required field "Attachment.type"`)} + } + if v, ok := ac.mutation.GetType(); ok { + if err := attachment.TypeValidator(v); err != nil { + return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Attachment.type": %w`, err)} + } + } + if _, ok := ac.mutation.ItemID(); !ok { + return &ValidationError{Name: "item", err: errors.New(`ent: missing required edge "Attachment.item"`)} + } + if _, ok := ac.mutation.DocumentID(); !ok { + return &ValidationError{Name: "document", err: errors.New(`ent: missing required edge "Attachment.document"`)} + } + return nil +} + +func (ac *AttachmentCreate) sqlSave(ctx context.Context) (*Attachment, error) { + _node, _spec := ac.createSpec() + if err := sqlgraph.CreateNode(ctx, ac.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != nil { + if id, ok := _spec.ID.Value.(*uuid.UUID); ok { + _node.ID = *id + } else if err := _node.ID.Scan(_spec.ID.Value); err != nil { + return nil, err + } + } + return _node, nil +} + +func (ac *AttachmentCreate) createSpec() (*Attachment, *sqlgraph.CreateSpec) { + var ( + _node = &Attachment{config: ac.config} + _spec = &sqlgraph.CreateSpec{ + Table: attachment.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + } + ) + if id, ok := ac.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = &id + } + if value, ok := ac.mutation.CreatedAt(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: attachment.FieldCreatedAt, + }) + _node.CreatedAt = value + } + if value, ok := ac.mutation.UpdatedAt(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: attachment.FieldUpdatedAt, + }) + _node.UpdatedAt = value + } + if value, ok := ac.mutation.GetType(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: attachment.FieldType, + }) + _node.Type = value + } + if nodes := ac.mutation.ItemIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.ItemTable, + Columns: []string{attachment.ItemColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.item_attachments = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := ac.mutation.DocumentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.DocumentTable, + Columns: []string{attachment.DocumentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: document.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.document_attachments = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// AttachmentCreateBulk is the builder for creating many Attachment entities in bulk. +type AttachmentCreateBulk struct { + config + builders []*AttachmentCreate +} + +// Save creates the Attachment entities in the database. +func (acb *AttachmentCreateBulk) Save(ctx context.Context) ([]*Attachment, error) { + specs := make([]*sqlgraph.CreateSpec, len(acb.builders)) + nodes := make([]*Attachment, len(acb.builders)) + mutators := make([]Mutator, len(acb.builders)) + for i := range acb.builders { + func(i int, root context.Context) { + builder := acb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*AttachmentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, acb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, acb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, acb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (acb *AttachmentCreateBulk) SaveX(ctx context.Context) []*Attachment { + v, err := acb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (acb *AttachmentCreateBulk) Exec(ctx context.Context) error { + _, err := acb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (acb *AttachmentCreateBulk) ExecX(ctx context.Context) { + if err := acb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/backend/ent/attachment_delete.go b/backend/ent/attachment_delete.go new file mode 100644 index 0000000..0b858cc --- /dev/null +++ b/backend/ent/attachment_delete.go @@ -0,0 +1,115 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/hay-kot/content/backend/ent/attachment" + "github.com/hay-kot/content/backend/ent/predicate" +) + +// AttachmentDelete is the builder for deleting a Attachment entity. +type AttachmentDelete struct { + config + hooks []Hook + mutation *AttachmentMutation +} + +// Where appends a list predicates to the AttachmentDelete builder. +func (ad *AttachmentDelete) Where(ps ...predicate.Attachment) *AttachmentDelete { + ad.mutation.Where(ps...) + return ad +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (ad *AttachmentDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(ad.hooks) == 0 { + affected, err = ad.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*AttachmentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + ad.mutation = mutation + affected, err = ad.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(ad.hooks) - 1; i >= 0; i-- { + if ad.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = ad.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, ad.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ad *AttachmentDelete) ExecX(ctx context.Context) int { + n, err := ad.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (ad *AttachmentDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: attachment.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + if ps := ad.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, ad.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return affected, err +} + +// AttachmentDeleteOne is the builder for deleting a single Attachment entity. +type AttachmentDeleteOne struct { + ad *AttachmentDelete +} + +// Exec executes the deletion query. +func (ado *AttachmentDeleteOne) Exec(ctx context.Context) error { + n, err := ado.ad.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{attachment.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (ado *AttachmentDeleteOne) ExecX(ctx context.Context) { + ado.ad.ExecX(ctx) +} diff --git a/backend/ent/attachment_query.go b/backend/ent/attachment_query.go new file mode 100644 index 0000000..f657057 --- /dev/null +++ b/backend/ent/attachment_query.go @@ -0,0 +1,683 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" + "github.com/hay-kot/content/backend/ent/document" + "github.com/hay-kot/content/backend/ent/item" + "github.com/hay-kot/content/backend/ent/predicate" +) + +// AttachmentQuery is the builder for querying Attachment entities. +type AttachmentQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.Attachment + withItem *ItemQuery + withDocument *DocumentQuery + withFKs bool + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the AttachmentQuery builder. +func (aq *AttachmentQuery) Where(ps ...predicate.Attachment) *AttachmentQuery { + aq.predicates = append(aq.predicates, ps...) + return aq +} + +// Limit adds a limit step to the query. +func (aq *AttachmentQuery) Limit(limit int) *AttachmentQuery { + aq.limit = &limit + return aq +} + +// Offset adds an offset step to the query. +func (aq *AttachmentQuery) Offset(offset int) *AttachmentQuery { + aq.offset = &offset + return aq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (aq *AttachmentQuery) Unique(unique bool) *AttachmentQuery { + aq.unique = &unique + return aq +} + +// Order adds an order step to the query. +func (aq *AttachmentQuery) Order(o ...OrderFunc) *AttachmentQuery { + aq.order = append(aq.order, o...) + return aq +} + +// QueryItem chains the current query on the "item" edge. +func (aq *AttachmentQuery) QueryItem() *ItemQuery { + query := &ItemQuery{config: aq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := aq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := aq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(attachment.Table, attachment.FieldID, selector), + sqlgraph.To(item.Table, item.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, attachment.ItemTable, attachment.ItemColumn), + ) + fromU = sqlgraph.SetNeighbors(aq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryDocument chains the current query on the "document" edge. +func (aq *AttachmentQuery) QueryDocument() *DocumentQuery { + query := &DocumentQuery{config: aq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := aq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := aq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(attachment.Table, attachment.FieldID, selector), + sqlgraph.To(document.Table, document.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, attachment.DocumentTable, attachment.DocumentColumn), + ) + fromU = sqlgraph.SetNeighbors(aq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first Attachment entity from the query. +// Returns a *NotFoundError when no Attachment was found. +func (aq *AttachmentQuery) First(ctx context.Context) (*Attachment, error) { + nodes, err := aq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{attachment.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (aq *AttachmentQuery) FirstX(ctx context.Context) *Attachment { + node, err := aq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Attachment ID from the query. +// Returns a *NotFoundError when no Attachment ID was found. +func (aq *AttachmentQuery) FirstID(ctx context.Context) (id uuid.UUID, err error) { + var ids []uuid.UUID + if ids, err = aq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{attachment.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (aq *AttachmentQuery) FirstIDX(ctx context.Context) uuid.UUID { + id, err := aq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Attachment entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Attachment entity is found. +// Returns a *NotFoundError when no Attachment entities are found. +func (aq *AttachmentQuery) Only(ctx context.Context) (*Attachment, error) { + nodes, err := aq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{attachment.Label} + default: + return nil, &NotSingularError{attachment.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (aq *AttachmentQuery) OnlyX(ctx context.Context) *Attachment { + node, err := aq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Attachment ID in the query. +// Returns a *NotSingularError when more than one Attachment ID is found. +// Returns a *NotFoundError when no entities are found. +func (aq *AttachmentQuery) OnlyID(ctx context.Context) (id uuid.UUID, err error) { + var ids []uuid.UUID + if ids, err = aq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{attachment.Label} + default: + err = &NotSingularError{attachment.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (aq *AttachmentQuery) OnlyIDX(ctx context.Context) uuid.UUID { + id, err := aq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Attachments. +func (aq *AttachmentQuery) All(ctx context.Context) ([]*Attachment, error) { + if err := aq.prepareQuery(ctx); err != nil { + return nil, err + } + return aq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (aq *AttachmentQuery) AllX(ctx context.Context) []*Attachment { + nodes, err := aq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Attachment IDs. +func (aq *AttachmentQuery) IDs(ctx context.Context) ([]uuid.UUID, error) { + var ids []uuid.UUID + if err := aq.Select(attachment.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (aq *AttachmentQuery) IDsX(ctx context.Context) []uuid.UUID { + ids, err := aq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (aq *AttachmentQuery) Count(ctx context.Context) (int, error) { + if err := aq.prepareQuery(ctx); err != nil { + return 0, err + } + return aq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (aq *AttachmentQuery) CountX(ctx context.Context) int { + count, err := aq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (aq *AttachmentQuery) Exist(ctx context.Context) (bool, error) { + if err := aq.prepareQuery(ctx); err != nil { + return false, err + } + return aq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (aq *AttachmentQuery) ExistX(ctx context.Context) bool { + exist, err := aq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the AttachmentQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (aq *AttachmentQuery) Clone() *AttachmentQuery { + if aq == nil { + return nil + } + return &AttachmentQuery{ + config: aq.config, + limit: aq.limit, + offset: aq.offset, + order: append([]OrderFunc{}, aq.order...), + predicates: append([]predicate.Attachment{}, aq.predicates...), + withItem: aq.withItem.Clone(), + withDocument: aq.withDocument.Clone(), + // clone intermediate query. + sql: aq.sql.Clone(), + path: aq.path, + unique: aq.unique, + } +} + +// WithItem tells the query-builder to eager-load the nodes that are connected to +// the "item" edge. The optional arguments are used to configure the query builder of the edge. +func (aq *AttachmentQuery) WithItem(opts ...func(*ItemQuery)) *AttachmentQuery { + query := &ItemQuery{config: aq.config} + for _, opt := range opts { + opt(query) + } + aq.withItem = query + return aq +} + +// WithDocument tells the query-builder to eager-load the nodes that are connected to +// the "document" edge. The optional arguments are used to configure the query builder of the edge. +func (aq *AttachmentQuery) WithDocument(opts ...func(*DocumentQuery)) *AttachmentQuery { + query := &DocumentQuery{config: aq.config} + for _, opt := range opts { + opt(query) + } + aq.withDocument = query + return aq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Attachment.Query(). +// GroupBy(attachment.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (aq *AttachmentQuery) GroupBy(field string, fields ...string) *AttachmentGroupBy { + grbuild := &AttachmentGroupBy{config: aq.config} + grbuild.fields = append([]string{field}, fields...) + grbuild.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := aq.prepareQuery(ctx); err != nil { + return nil, err + } + return aq.sqlQuery(ctx), nil + } + grbuild.label = attachment.Label + grbuild.flds, grbuild.scan = &grbuild.fields, grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// } +// +// client.Attachment.Query(). +// Select(attachment.FieldCreatedAt). +// Scan(ctx, &v) +func (aq *AttachmentQuery) Select(fields ...string) *AttachmentSelect { + aq.fields = append(aq.fields, fields...) + selbuild := &AttachmentSelect{AttachmentQuery: aq} + selbuild.label = attachment.Label + selbuild.flds, selbuild.scan = &aq.fields, selbuild.Scan + return selbuild +} + +func (aq *AttachmentQuery) prepareQuery(ctx context.Context) error { + for _, f := range aq.fields { + if !attachment.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if aq.path != nil { + prev, err := aq.path(ctx) + if err != nil { + return err + } + aq.sql = prev + } + return nil +} + +func (aq *AttachmentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Attachment, error) { + var ( + nodes = []*Attachment{} + withFKs = aq.withFKs + _spec = aq.querySpec() + loadedTypes = [2]bool{ + aq.withItem != nil, + aq.withDocument != nil, + } + ) + if aq.withItem != nil || aq.withDocument != nil { + withFKs = true + } + if withFKs { + _spec.Node.Columns = append(_spec.Node.Columns, attachment.ForeignKeys...) + } + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + return (*Attachment).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + node := &Attachment{config: aq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, aq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := aq.withItem; query != nil { + if err := aq.loadItem(ctx, query, nodes, nil, + func(n *Attachment, e *Item) { n.Edges.Item = e }); err != nil { + return nil, err + } + } + if query := aq.withDocument; query != nil { + if err := aq.loadDocument(ctx, query, nodes, nil, + func(n *Attachment, e *Document) { n.Edges.Document = e }); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (aq *AttachmentQuery) loadItem(ctx context.Context, query *ItemQuery, nodes []*Attachment, init func(*Attachment), assign func(*Attachment, *Item)) error { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*Attachment) + for i := range nodes { + if nodes[i].item_attachments == nil { + continue + } + fk := *nodes[i].item_attachments + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(item.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "item_attachments" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} +func (aq *AttachmentQuery) loadDocument(ctx context.Context, query *DocumentQuery, nodes []*Attachment, init func(*Attachment), assign func(*Attachment, *Document)) error { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*Attachment) + for i := range nodes { + if nodes[i].document_attachments == nil { + continue + } + fk := *nodes[i].document_attachments + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(document.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "document_attachments" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (aq *AttachmentQuery) sqlCount(ctx context.Context) (int, error) { + _spec := aq.querySpec() + _spec.Node.Columns = aq.fields + if len(aq.fields) > 0 { + _spec.Unique = aq.unique != nil && *aq.unique + } + return sqlgraph.CountNodes(ctx, aq.driver, _spec) +} + +func (aq *AttachmentQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := aq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (aq *AttachmentQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: attachment.Table, + Columns: attachment.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + From: aq.sql, + Unique: true, + } + if unique := aq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := aq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, attachment.FieldID) + for i := range fields { + if fields[i] != attachment.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := aq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := aq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := aq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := aq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (aq *AttachmentQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(aq.driver.Dialect()) + t1 := builder.Table(attachment.Table) + columns := aq.fields + if len(columns) == 0 { + columns = attachment.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if aq.sql != nil { + selector = aq.sql + selector.Select(selector.Columns(columns...)...) + } + if aq.unique != nil && *aq.unique { + selector.Distinct() + } + for _, p := range aq.predicates { + p(selector) + } + for _, p := range aq.order { + p(selector) + } + if offset := aq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := aq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// AttachmentGroupBy is the group-by builder for Attachment entities. +type AttachmentGroupBy struct { + config + selector + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (agb *AttachmentGroupBy) Aggregate(fns ...AggregateFunc) *AttachmentGroupBy { + agb.fns = append(agb.fns, fns...) + return agb +} + +// Scan applies the group-by query and scans the result into the given value. +func (agb *AttachmentGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := agb.path(ctx) + if err != nil { + return err + } + agb.sql = query + return agb.sqlScan(ctx, v) +} + +func (agb *AttachmentGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range agb.fields { + if !attachment.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := agb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := agb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (agb *AttachmentGroupBy) sqlQuery() *sql.Selector { + selector := agb.sql.Select() + aggregation := make([]string, 0, len(agb.fns)) + for _, fn := range agb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(agb.fields)+len(agb.fns)) + for _, f := range agb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(agb.fields...)...) +} + +// AttachmentSelect is the builder for selecting fields of Attachment entities. +type AttachmentSelect struct { + *AttachmentQuery + selector + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (as *AttachmentSelect) Scan(ctx context.Context, v interface{}) error { + if err := as.prepareQuery(ctx); err != nil { + return err + } + as.sql = as.AttachmentQuery.sqlQuery(ctx) + return as.sqlScan(ctx, v) +} + +func (as *AttachmentSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := as.sql.Query() + if err := as.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/backend/ent/attachment_update.go b/backend/ent/attachment_update.go new file mode 100644 index 0000000..53b5feb --- /dev/null +++ b/backend/ent/attachment_update.go @@ -0,0 +1,587 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" + "github.com/hay-kot/content/backend/ent/document" + "github.com/hay-kot/content/backend/ent/item" + "github.com/hay-kot/content/backend/ent/predicate" +) + +// AttachmentUpdate is the builder for updating Attachment entities. +type AttachmentUpdate struct { + config + hooks []Hook + mutation *AttachmentMutation +} + +// Where appends a list predicates to the AttachmentUpdate builder. +func (au *AttachmentUpdate) Where(ps ...predicate.Attachment) *AttachmentUpdate { + au.mutation.Where(ps...) + return au +} + +// SetUpdatedAt sets the "updated_at" field. +func (au *AttachmentUpdate) SetUpdatedAt(t time.Time) *AttachmentUpdate { + au.mutation.SetUpdatedAt(t) + return au +} + +// SetType sets the "type" field. +func (au *AttachmentUpdate) SetType(a attachment.Type) *AttachmentUpdate { + au.mutation.SetType(a) + return au +} + +// SetNillableType sets the "type" field if the given value is not nil. +func (au *AttachmentUpdate) SetNillableType(a *attachment.Type) *AttachmentUpdate { + if a != nil { + au.SetType(*a) + } + return au +} + +// SetItemID sets the "item" edge to the Item entity by ID. +func (au *AttachmentUpdate) SetItemID(id uuid.UUID) *AttachmentUpdate { + au.mutation.SetItemID(id) + return au +} + +// SetItem sets the "item" edge to the Item entity. +func (au *AttachmentUpdate) SetItem(i *Item) *AttachmentUpdate { + return au.SetItemID(i.ID) +} + +// SetDocumentID sets the "document" edge to the Document entity by ID. +func (au *AttachmentUpdate) SetDocumentID(id uuid.UUID) *AttachmentUpdate { + au.mutation.SetDocumentID(id) + return au +} + +// SetDocument sets the "document" edge to the Document entity. +func (au *AttachmentUpdate) SetDocument(d *Document) *AttachmentUpdate { + return au.SetDocumentID(d.ID) +} + +// Mutation returns the AttachmentMutation object of the builder. +func (au *AttachmentUpdate) Mutation() *AttachmentMutation { + return au.mutation +} + +// ClearItem clears the "item" edge to the Item entity. +func (au *AttachmentUpdate) ClearItem() *AttachmentUpdate { + au.mutation.ClearItem() + return au +} + +// ClearDocument clears the "document" edge to the Document entity. +func (au *AttachmentUpdate) ClearDocument() *AttachmentUpdate { + au.mutation.ClearDocument() + return au +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (au *AttachmentUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + au.defaults() + if len(au.hooks) == 0 { + if err = au.check(); err != nil { + return 0, err + } + affected, err = au.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*AttachmentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = au.check(); err != nil { + return 0, err + } + au.mutation = mutation + affected, err = au.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(au.hooks) - 1; i >= 0; i-- { + if au.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = au.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, au.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (au *AttachmentUpdate) SaveX(ctx context.Context) int { + affected, err := au.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (au *AttachmentUpdate) Exec(ctx context.Context) error { + _, err := au.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (au *AttachmentUpdate) ExecX(ctx context.Context) { + if err := au.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (au *AttachmentUpdate) defaults() { + if _, ok := au.mutation.UpdatedAt(); !ok { + v := attachment.UpdateDefaultUpdatedAt() + au.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (au *AttachmentUpdate) check() error { + if v, ok := au.mutation.GetType(); ok { + if err := attachment.TypeValidator(v); err != nil { + return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Attachment.type": %w`, err)} + } + } + if _, ok := au.mutation.ItemID(); au.mutation.ItemCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Attachment.item"`) + } + if _, ok := au.mutation.DocumentID(); au.mutation.DocumentCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Attachment.document"`) + } + return nil +} + +func (au *AttachmentUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: attachment.Table, + Columns: attachment.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + if ps := au.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := au.mutation.UpdatedAt(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: attachment.FieldUpdatedAt, + }) + } + if value, ok := au.mutation.GetType(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: attachment.FieldType, + }) + } + if au.mutation.ItemCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.ItemTable, + Columns: []string{attachment.ItemColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := au.mutation.ItemIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.ItemTable, + Columns: []string{attachment.ItemColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if au.mutation.DocumentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.DocumentTable, + Columns: []string{attachment.DocumentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: document.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := au.mutation.DocumentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.DocumentTable, + Columns: []string{attachment.DocumentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: document.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, au.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{attachment.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + return n, nil +} + +// AttachmentUpdateOne is the builder for updating a single Attachment entity. +type AttachmentUpdateOne struct { + config + fields []string + hooks []Hook + mutation *AttachmentMutation +} + +// SetUpdatedAt sets the "updated_at" field. +func (auo *AttachmentUpdateOne) SetUpdatedAt(t time.Time) *AttachmentUpdateOne { + auo.mutation.SetUpdatedAt(t) + return auo +} + +// SetType sets the "type" field. +func (auo *AttachmentUpdateOne) SetType(a attachment.Type) *AttachmentUpdateOne { + auo.mutation.SetType(a) + return auo +} + +// SetNillableType sets the "type" field if the given value is not nil. +func (auo *AttachmentUpdateOne) SetNillableType(a *attachment.Type) *AttachmentUpdateOne { + if a != nil { + auo.SetType(*a) + } + return auo +} + +// SetItemID sets the "item" edge to the Item entity by ID. +func (auo *AttachmentUpdateOne) SetItemID(id uuid.UUID) *AttachmentUpdateOne { + auo.mutation.SetItemID(id) + return auo +} + +// SetItem sets the "item" edge to the Item entity. +func (auo *AttachmentUpdateOne) SetItem(i *Item) *AttachmentUpdateOne { + return auo.SetItemID(i.ID) +} + +// SetDocumentID sets the "document" edge to the Document entity by ID. +func (auo *AttachmentUpdateOne) SetDocumentID(id uuid.UUID) *AttachmentUpdateOne { + auo.mutation.SetDocumentID(id) + return auo +} + +// SetDocument sets the "document" edge to the Document entity. +func (auo *AttachmentUpdateOne) SetDocument(d *Document) *AttachmentUpdateOne { + return auo.SetDocumentID(d.ID) +} + +// Mutation returns the AttachmentMutation object of the builder. +func (auo *AttachmentUpdateOne) Mutation() *AttachmentMutation { + return auo.mutation +} + +// ClearItem clears the "item" edge to the Item entity. +func (auo *AttachmentUpdateOne) ClearItem() *AttachmentUpdateOne { + auo.mutation.ClearItem() + return auo +} + +// ClearDocument clears the "document" edge to the Document entity. +func (auo *AttachmentUpdateOne) ClearDocument() *AttachmentUpdateOne { + auo.mutation.ClearDocument() + return auo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (auo *AttachmentUpdateOne) Select(field string, fields ...string) *AttachmentUpdateOne { + auo.fields = append([]string{field}, fields...) + return auo +} + +// Save executes the query and returns the updated Attachment entity. +func (auo *AttachmentUpdateOne) Save(ctx context.Context) (*Attachment, error) { + var ( + err error + node *Attachment + ) + auo.defaults() + if len(auo.hooks) == 0 { + if err = auo.check(); err != nil { + return nil, err + } + node, err = auo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*AttachmentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = auo.check(); err != nil { + return nil, err + } + auo.mutation = mutation + node, err = auo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(auo.hooks) - 1; i >= 0; i-- { + if auo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = auo.hooks[i](mut) + } + v, err := mut.Mutate(ctx, auo.mutation) + if err != nil { + return nil, err + } + nv, ok := v.(*Attachment) + if !ok { + return nil, fmt.Errorf("unexpected node type %T returned from AttachmentMutation", v) + } + node = nv + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (auo *AttachmentUpdateOne) SaveX(ctx context.Context) *Attachment { + node, err := auo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (auo *AttachmentUpdateOne) Exec(ctx context.Context) error { + _, err := auo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (auo *AttachmentUpdateOne) ExecX(ctx context.Context) { + if err := auo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (auo *AttachmentUpdateOne) defaults() { + if _, ok := auo.mutation.UpdatedAt(); !ok { + v := attachment.UpdateDefaultUpdatedAt() + auo.mutation.SetUpdatedAt(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (auo *AttachmentUpdateOne) check() error { + if v, ok := auo.mutation.GetType(); ok { + if err := attachment.TypeValidator(v); err != nil { + return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Attachment.type": %w`, err)} + } + } + if _, ok := auo.mutation.ItemID(); auo.mutation.ItemCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Attachment.item"`) + } + if _, ok := auo.mutation.DocumentID(); auo.mutation.DocumentCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Attachment.document"`) + } + return nil +} + +func (auo *AttachmentUpdateOne) sqlSave(ctx context.Context) (_node *Attachment, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: attachment.Table, + Columns: attachment.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + id, ok := auo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Attachment.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := auo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, attachment.FieldID) + for _, f := range fields { + if !attachment.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != attachment.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := auo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := auo.mutation.UpdatedAt(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: attachment.FieldUpdatedAt, + }) + } + if value, ok := auo.mutation.GetType(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: attachment.FieldType, + }) + } + if auo.mutation.ItemCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.ItemTable, + Columns: []string{attachment.ItemColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := auo.mutation.ItemIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.ItemTable, + Columns: []string{attachment.ItemColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if auo.mutation.DocumentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.DocumentTable, + Columns: []string{attachment.DocumentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: document.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := auo.mutation.DocumentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: attachment.DocumentTable, + Columns: []string{attachment.DocumentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: document.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &Attachment{config: auo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, auo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{attachment.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + return _node, nil +} diff --git a/backend/ent/client.go b/backend/ent/client.go index 0af74ba..fd39792 100644 --- a/backend/ent/client.go +++ b/backend/ent/client.go @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/hay-kot/content/backend/ent/migrate" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/authtokens" "github.com/hay-kot/content/backend/ent/document" "github.com/hay-kot/content/backend/ent/documenttoken" @@ -31,6 +32,8 @@ type Client struct { config // Schema is the client for creating, migrating and dropping schema. Schema *migrate.Schema + // Attachment is the client for interacting with the Attachment builders. + Attachment *AttachmentClient // AuthTokens is the client for interacting with the AuthTokens builders. AuthTokens *AuthTokensClient // Document is the client for interacting with the Document builders. @@ -62,6 +65,7 @@ func NewClient(opts ...Option) *Client { func (c *Client) init() { c.Schema = migrate.NewSchema(c.driver) + c.Attachment = NewAttachmentClient(c.config) c.AuthTokens = NewAuthTokensClient(c.config) c.Document = NewDocumentClient(c.config) c.DocumentToken = NewDocumentTokenClient(c.config) @@ -104,6 +108,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { return &Tx{ ctx: ctx, config: cfg, + Attachment: NewAttachmentClient(cfg), AuthTokens: NewAuthTokensClient(cfg), Document: NewDocumentClient(cfg), DocumentToken: NewDocumentTokenClient(cfg), @@ -132,6 +137,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) return &Tx{ ctx: ctx, config: cfg, + Attachment: NewAttachmentClient(cfg), AuthTokens: NewAuthTokensClient(cfg), Document: NewDocumentClient(cfg), DocumentToken: NewDocumentTokenClient(cfg), @@ -147,7 +153,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) // Debug returns a new debug-client. It's used to get verbose logging on specific operations. // // client.Debug(). -// AuthTokens. +// Attachment. // Query(). // Count(ctx) func (c *Client) Debug() *Client { @@ -169,6 +175,7 @@ func (c *Client) Close() error { // Use adds the mutation hooks to all the entity clients. // In order to add hooks to a specific client, call: `client.Node.Use(...)`. func (c *Client) Use(hooks ...Hook) { + c.Attachment.Use(hooks...) c.AuthTokens.Use(hooks...) c.Document.Use(hooks...) c.DocumentToken.Use(hooks...) @@ -180,6 +187,128 @@ func (c *Client) Use(hooks ...Hook) { c.User.Use(hooks...) } +// AttachmentClient is a client for the Attachment schema. +type AttachmentClient struct { + config +} + +// NewAttachmentClient returns a client for the Attachment from the given config. +func NewAttachmentClient(c config) *AttachmentClient { + return &AttachmentClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `attachment.Hooks(f(g(h())))`. +func (c *AttachmentClient) Use(hooks ...Hook) { + c.hooks.Attachment = append(c.hooks.Attachment, hooks...) +} + +// Create returns a builder for creating a Attachment entity. +func (c *AttachmentClient) Create() *AttachmentCreate { + mutation := newAttachmentMutation(c.config, OpCreate) + return &AttachmentCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Attachment entities. +func (c *AttachmentClient) CreateBulk(builders ...*AttachmentCreate) *AttachmentCreateBulk { + return &AttachmentCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Attachment. +func (c *AttachmentClient) Update() *AttachmentUpdate { + mutation := newAttachmentMutation(c.config, OpUpdate) + return &AttachmentUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *AttachmentClient) UpdateOne(a *Attachment) *AttachmentUpdateOne { + mutation := newAttachmentMutation(c.config, OpUpdateOne, withAttachment(a)) + return &AttachmentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *AttachmentClient) UpdateOneID(id uuid.UUID) *AttachmentUpdateOne { + mutation := newAttachmentMutation(c.config, OpUpdateOne, withAttachmentID(id)) + return &AttachmentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Attachment. +func (c *AttachmentClient) Delete() *AttachmentDelete { + mutation := newAttachmentMutation(c.config, OpDelete) + return &AttachmentDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *AttachmentClient) DeleteOne(a *Attachment) *AttachmentDeleteOne { + return c.DeleteOneID(a.ID) +} + +// DeleteOne returns a builder for deleting the given entity by its id. +func (c *AttachmentClient) DeleteOneID(id uuid.UUID) *AttachmentDeleteOne { + builder := c.Delete().Where(attachment.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &AttachmentDeleteOne{builder} +} + +// Query returns a query builder for Attachment. +func (c *AttachmentClient) Query() *AttachmentQuery { + return &AttachmentQuery{ + config: c.config, + } +} + +// Get returns a Attachment entity by its id. +func (c *AttachmentClient) Get(ctx context.Context, id uuid.UUID) (*Attachment, error) { + return c.Query().Where(attachment.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *AttachmentClient) GetX(ctx context.Context, id uuid.UUID) *Attachment { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryItem queries the item edge of a Attachment. +func (c *AttachmentClient) QueryItem(a *Attachment) *ItemQuery { + query := &ItemQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := a.ID + step := sqlgraph.NewStep( + sqlgraph.From(attachment.Table, attachment.FieldID, id), + sqlgraph.To(item.Table, item.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, attachment.ItemTable, attachment.ItemColumn), + ) + fromV = sqlgraph.Neighbors(a.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryDocument queries the document edge of a Attachment. +func (c *AttachmentClient) QueryDocument(a *Attachment) *DocumentQuery { + query := &DocumentQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := a.ID + step := sqlgraph.NewStep( + sqlgraph.From(attachment.Table, attachment.FieldID, id), + sqlgraph.To(document.Table, document.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, attachment.DocumentTable, attachment.DocumentColumn), + ) + fromV = sqlgraph.Neighbors(a.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *AttachmentClient) Hooks() []Hook { + return c.hooks.Attachment +} + // AuthTokensClient is a client for the AuthTokens schema. type AuthTokensClient struct { config @@ -403,6 +532,22 @@ func (c *DocumentClient) QueryDocumentTokens(d *Document) *DocumentTokenQuery { return query } +// QueryAttachments queries the attachments edge of a Document. +func (c *DocumentClient) QueryAttachments(d *Document) *AttachmentQuery { + query := &AttachmentQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := d.ID + step := sqlgraph.NewStep( + sqlgraph.From(document.Table, document.FieldID, id), + sqlgraph.To(attachment.Table, attachment.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, document.AttachmentsTable, document.AttachmentsColumn), + ) + fromV = sqlgraph.Neighbors(d.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *DocumentClient) Hooks() []Hook { return c.hooks.Document @@ -833,6 +978,22 @@ func (c *ItemClient) QueryLabel(i *Item) *LabelQuery { return query } +// QueryAttachments queries the attachments edge of a Item. +func (c *ItemClient) QueryAttachments(i *Item) *AttachmentQuery { + query := &AttachmentQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := i.ID + step := sqlgraph.NewStep( + sqlgraph.From(item.Table, item.FieldID, id), + sqlgraph.To(attachment.Table, attachment.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, item.AttachmentsTable, item.AttachmentsColumn), + ) + fromV = sqlgraph.Neighbors(i.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *ItemClient) Hooks() []Hook { return c.hooks.Item diff --git a/backend/ent/config.go b/backend/ent/config.go index 58bafc9..8ae9829 100644 --- a/backend/ent/config.go +++ b/backend/ent/config.go @@ -24,6 +24,7 @@ type config struct { // hooks per client, for fast access. type hooks struct { + Attachment []ent.Hook AuthTokens []ent.Hook Document []ent.Hook DocumentToken []ent.Hook diff --git a/backend/ent/document.go b/backend/ent/document.go index c29a515..14a33ca 100644 --- a/backend/ent/document.go +++ b/backend/ent/document.go @@ -38,9 +38,11 @@ type DocumentEdges struct { Group *Group `json:"group,omitempty"` // DocumentTokens holds the value of the document_tokens edge. DocumentTokens []*DocumentToken `json:"document_tokens,omitempty"` + // Attachments holds the value of the attachments edge. + Attachments []*Attachment `json:"attachments,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [2]bool + loadedTypes [3]bool } // GroupOrErr returns the Group value or an error if the edge @@ -65,6 +67,15 @@ func (e DocumentEdges) DocumentTokensOrErr() ([]*DocumentToken, error) { return nil, &NotLoadedError{edge: "document_tokens"} } +// AttachmentsOrErr returns the Attachments value or an error if the edge +// was not loaded in eager-loading. +func (e DocumentEdges) AttachmentsOrErr() ([]*Attachment, error) { + if e.loadedTypes[2] { + return e.Attachments, nil + } + return nil, &NotLoadedError{edge: "attachments"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Document) scanValues(columns []string) ([]interface{}, error) { values := make([]interface{}, len(columns)) @@ -145,6 +156,11 @@ func (d *Document) QueryDocumentTokens() *DocumentTokenQuery { return (&DocumentClient{config: d.config}).QueryDocumentTokens(d) } +// QueryAttachments queries the "attachments" edge of the Document entity. +func (d *Document) QueryAttachments() *AttachmentQuery { + return (&DocumentClient{config: d.config}).QueryAttachments(d) +} + // Update returns a builder for updating this Document. // Note that you need to call Document.Unwrap() before calling this method if this Document // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/backend/ent/document/document.go b/backend/ent/document/document.go index b019a6f..bfc3881 100644 --- a/backend/ent/document/document.go +++ b/backend/ent/document/document.go @@ -25,6 +25,8 @@ const ( EdgeGroup = "group" // EdgeDocumentTokens holds the string denoting the document_tokens edge name in mutations. EdgeDocumentTokens = "document_tokens" + // EdgeAttachments holds the string denoting the attachments edge name in mutations. + EdgeAttachments = "attachments" // Table holds the table name of the document in the database. Table = "documents" // GroupTable is the table that holds the group relation/edge. @@ -41,6 +43,13 @@ const ( DocumentTokensInverseTable = "document_tokens" // DocumentTokensColumn is the table column denoting the document_tokens relation/edge. DocumentTokensColumn = "document_document_tokens" + // AttachmentsTable is the table that holds the attachments relation/edge. + AttachmentsTable = "attachments" + // AttachmentsInverseTable is the table name for the Attachment entity. + // It exists in this package in order to avoid circular dependency with the "attachment" package. + AttachmentsInverseTable = "attachments" + // AttachmentsColumn is the table column denoting the attachments relation/edge. + AttachmentsColumn = "document_attachments" ) // Columns holds all SQL columns for document fields. diff --git a/backend/ent/document/where.go b/backend/ent/document/where.go index e01f4bb..f859293 100644 --- a/backend/ent/document/where.go +++ b/backend/ent/document/where.go @@ -492,6 +492,34 @@ func HasDocumentTokensWith(preds ...predicate.DocumentToken) predicate.Document }) } +// HasAttachments applies the HasEdge predicate on the "attachments" edge. +func HasAttachments() predicate.Document { + return predicate.Document(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(AttachmentsTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, AttachmentsTable, AttachmentsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasAttachmentsWith applies the HasEdge predicate on the "attachments" edge with a given conditions (other predicates). +func HasAttachmentsWith(preds ...predicate.Attachment) predicate.Document { + return predicate.Document(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(AttachmentsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, AttachmentsTable, AttachmentsColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Document) predicate.Document { return predicate.Document(func(s *sql.Selector) { diff --git a/backend/ent/document_create.go b/backend/ent/document_create.go index 6ffce74..ea98c1e 100644 --- a/backend/ent/document_create.go +++ b/backend/ent/document_create.go @@ -11,6 +11,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/document" "github.com/hay-kot/content/backend/ent/documenttoken" "github.com/hay-kot/content/backend/ent/group" @@ -103,6 +104,21 @@ func (dc *DocumentCreate) AddDocumentTokens(d ...*DocumentToken) *DocumentCreate return dc.AddDocumentTokenIDs(ids...) } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs. +func (dc *DocumentCreate) AddAttachmentIDs(ids ...uuid.UUID) *DocumentCreate { + dc.mutation.AddAttachmentIDs(ids...) + return dc +} + +// AddAttachments adds the "attachments" edges to the Attachment entity. +func (dc *DocumentCreate) AddAttachments(a ...*Attachment) *DocumentCreate { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return dc.AddAttachmentIDs(ids...) +} + // Mutation returns the DocumentMutation object of the builder. func (dc *DocumentCreate) Mutation() *DocumentMutation { return dc.mutation @@ -328,6 +344,25 @@ func (dc *DocumentCreate) createSpec() (*Document, *sqlgraph.CreateSpec) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := dc.mutation.AttachmentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: document.AttachmentsTable, + Columns: []string{document.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/backend/ent/document_query.go b/backend/ent/document_query.go index e8d9418..0739e02 100644 --- a/backend/ent/document_query.go +++ b/backend/ent/document_query.go @@ -12,6 +12,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/document" "github.com/hay-kot/content/backend/ent/documenttoken" "github.com/hay-kot/content/backend/ent/group" @@ -29,6 +30,7 @@ type DocumentQuery struct { predicates []predicate.Document withGroup *GroupQuery withDocumentTokens *DocumentTokenQuery + withAttachments *AttachmentQuery withFKs bool // intermediate query (i.e. traversal path). sql *sql.Selector @@ -110,6 +112,28 @@ func (dq *DocumentQuery) QueryDocumentTokens() *DocumentTokenQuery { return query } +// QueryAttachments chains the current query on the "attachments" edge. +func (dq *DocumentQuery) QueryAttachments() *AttachmentQuery { + query := &AttachmentQuery{config: dq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := dq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := dq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(document.Table, document.FieldID, selector), + sqlgraph.To(attachment.Table, attachment.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, document.AttachmentsTable, document.AttachmentsColumn), + ) + fromU = sqlgraph.SetNeighbors(dq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Document entity from the query. // Returns a *NotFoundError when no Document was found. func (dq *DocumentQuery) First(ctx context.Context) (*Document, error) { @@ -293,6 +317,7 @@ func (dq *DocumentQuery) Clone() *DocumentQuery { predicates: append([]predicate.Document{}, dq.predicates...), withGroup: dq.withGroup.Clone(), withDocumentTokens: dq.withDocumentTokens.Clone(), + withAttachments: dq.withAttachments.Clone(), // clone intermediate query. sql: dq.sql.Clone(), path: dq.path, @@ -322,6 +347,17 @@ func (dq *DocumentQuery) WithDocumentTokens(opts ...func(*DocumentTokenQuery)) * return dq } +// WithAttachments tells the query-builder to eager-load the nodes that are connected to +// the "attachments" edge. The optional arguments are used to configure the query builder of the edge. +func (dq *DocumentQuery) WithAttachments(opts ...func(*AttachmentQuery)) *DocumentQuery { + query := &AttachmentQuery{config: dq.config} + for _, opt := range opts { + opt(query) + } + dq.withAttachments = query + return dq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -391,9 +427,10 @@ func (dq *DocumentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Doc nodes = []*Document{} withFKs = dq.withFKs _spec = dq.querySpec() - loadedTypes = [2]bool{ + loadedTypes = [3]bool{ dq.withGroup != nil, dq.withDocumentTokens != nil, + dq.withAttachments != nil, } ) if dq.withGroup != nil { @@ -433,6 +470,13 @@ func (dq *DocumentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Doc return nil, err } } + if query := dq.withAttachments; query != nil { + if err := dq.loadAttachments(ctx, query, nodes, + func(n *Document) { n.Edges.Attachments = []*Attachment{} }, + func(n *Document, e *Attachment) { n.Edges.Attachments = append(n.Edges.Attachments, e) }); err != nil { + return nil, err + } + } return nodes, nil } @@ -496,6 +540,37 @@ func (dq *DocumentQuery) loadDocumentTokens(ctx context.Context, query *Document } return nil } +func (dq *DocumentQuery) loadAttachments(ctx context.Context, query *AttachmentQuery, nodes []*Document, init func(*Document), assign func(*Document, *Attachment)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[uuid.UUID]*Document) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + query.withFKs = true + query.Where(predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.InValues(document.AttachmentsColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.document_attachments + if fk == nil { + return fmt.Errorf(`foreign-key "document_attachments" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return fmt.Errorf(`unexpected foreign-key "document_attachments" returned %v for node %v`, *fk, n.ID) + } + assign(node, n) + } + return nil +} func (dq *DocumentQuery) sqlCount(ctx context.Context) (int, error) { _spec := dq.querySpec() diff --git a/backend/ent/document_update.go b/backend/ent/document_update.go index dfd276d..6aab168 100644 --- a/backend/ent/document_update.go +++ b/backend/ent/document_update.go @@ -12,6 +12,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/document" "github.com/hay-kot/content/backend/ent/documenttoken" "github.com/hay-kot/content/backend/ent/group" @@ -75,6 +76,21 @@ func (du *DocumentUpdate) AddDocumentTokens(d ...*DocumentToken) *DocumentUpdate return du.AddDocumentTokenIDs(ids...) } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs. +func (du *DocumentUpdate) AddAttachmentIDs(ids ...uuid.UUID) *DocumentUpdate { + du.mutation.AddAttachmentIDs(ids...) + return du +} + +// AddAttachments adds the "attachments" edges to the Attachment entity. +func (du *DocumentUpdate) AddAttachments(a ...*Attachment) *DocumentUpdate { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return du.AddAttachmentIDs(ids...) +} + // Mutation returns the DocumentMutation object of the builder. func (du *DocumentUpdate) Mutation() *DocumentMutation { return du.mutation @@ -107,6 +123,27 @@ func (du *DocumentUpdate) RemoveDocumentTokens(d ...*DocumentToken) *DocumentUpd return du.RemoveDocumentTokenIDs(ids...) } +// ClearAttachments clears all "attachments" edges to the Attachment entity. +func (du *DocumentUpdate) ClearAttachments() *DocumentUpdate { + du.mutation.ClearAttachments() + return du +} + +// RemoveAttachmentIDs removes the "attachments" edge to Attachment entities by IDs. +func (du *DocumentUpdate) RemoveAttachmentIDs(ids ...uuid.UUID) *DocumentUpdate { + du.mutation.RemoveAttachmentIDs(ids...) + return du +} + +// RemoveAttachments removes "attachments" edges to Attachment entities. +func (du *DocumentUpdate) RemoveAttachments(a ...*Attachment) *DocumentUpdate { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return du.RemoveAttachmentIDs(ids...) +} + // Save executes the query and returns the number of nodes affected by the update operation. func (du *DocumentUpdate) Save(ctx context.Context) (int, error) { var ( @@ -322,6 +359,60 @@ func (du *DocumentUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if du.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: document.AttachmentsTable, + Columns: []string{document.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := du.mutation.RemovedAttachmentsIDs(); len(nodes) > 0 && !du.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: document.AttachmentsTable, + Columns: []string{document.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := du.mutation.AttachmentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: document.AttachmentsTable, + Columns: []string{document.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, du.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{document.Label} @@ -385,6 +476,21 @@ func (duo *DocumentUpdateOne) AddDocumentTokens(d ...*DocumentToken) *DocumentUp return duo.AddDocumentTokenIDs(ids...) } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs. +func (duo *DocumentUpdateOne) AddAttachmentIDs(ids ...uuid.UUID) *DocumentUpdateOne { + duo.mutation.AddAttachmentIDs(ids...) + return duo +} + +// AddAttachments adds the "attachments" edges to the Attachment entity. +func (duo *DocumentUpdateOne) AddAttachments(a ...*Attachment) *DocumentUpdateOne { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return duo.AddAttachmentIDs(ids...) +} + // Mutation returns the DocumentMutation object of the builder. func (duo *DocumentUpdateOne) Mutation() *DocumentMutation { return duo.mutation @@ -417,6 +523,27 @@ func (duo *DocumentUpdateOne) RemoveDocumentTokens(d ...*DocumentToken) *Documen return duo.RemoveDocumentTokenIDs(ids...) } +// ClearAttachments clears all "attachments" edges to the Attachment entity. +func (duo *DocumentUpdateOne) ClearAttachments() *DocumentUpdateOne { + duo.mutation.ClearAttachments() + return duo +} + +// RemoveAttachmentIDs removes the "attachments" edge to Attachment entities by IDs. +func (duo *DocumentUpdateOne) RemoveAttachmentIDs(ids ...uuid.UUID) *DocumentUpdateOne { + duo.mutation.RemoveAttachmentIDs(ids...) + return duo +} + +// RemoveAttachments removes "attachments" edges to Attachment entities. +func (duo *DocumentUpdateOne) RemoveAttachments(a ...*Attachment) *DocumentUpdateOne { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return duo.RemoveAttachmentIDs(ids...) +} + // Select allows selecting one or more fields (columns) of the returned entity. // The default is selecting all fields defined in the entity schema. func (duo *DocumentUpdateOne) Select(field string, fields ...string) *DocumentUpdateOne { @@ -662,6 +789,60 @@ func (duo *DocumentUpdateOne) sqlSave(ctx context.Context) (_node *Document, err } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if duo.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: document.AttachmentsTable, + Columns: []string{document.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := duo.mutation.RemovedAttachmentsIDs(); len(nodes) > 0 && !duo.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: document.AttachmentsTable, + Columns: []string{document.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := duo.mutation.AttachmentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: document.AttachmentsTable, + Columns: []string{document.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _node = &Document{config: duo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/backend/ent/ent.go b/backend/ent/ent.go index 74b405e..997c25e 100644 --- a/backend/ent/ent.go +++ b/backend/ent/ent.go @@ -10,6 +10,7 @@ import ( "entgo.io/ent" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/authtokens" "github.com/hay-kot/content/backend/ent/document" "github.com/hay-kot/content/backend/ent/documenttoken" @@ -39,6 +40,7 @@ type OrderFunc func(*sql.Selector) // columnChecker returns a function indicates if the column exists in the given column. func columnChecker(table string) func(string) error { checks := map[string]func(string) bool{ + attachment.Table: attachment.ValidColumn, authtokens.Table: authtokens.ValidColumn, document.Table: document.ValidColumn, documenttoken.Table: documenttoken.ValidColumn, diff --git a/backend/ent/hook/hook.go b/backend/ent/hook/hook.go index 645a568..095e929 100644 --- a/backend/ent/hook/hook.go +++ b/backend/ent/hook/hook.go @@ -9,6 +9,19 @@ import ( "github.com/hay-kot/content/backend/ent" ) +// The AttachmentFunc type is an adapter to allow the use of ordinary +// function as Attachment mutator. +type AttachmentFunc func(context.Context, *ent.AttachmentMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f AttachmentFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.AttachmentMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AttachmentMutation", m) + } + return f(ctx, mv) +} + // The AuthTokensFunc type is an adapter to allow the use of ordinary // function as AuthTokens mutator. type AuthTokensFunc func(context.Context, *ent.AuthTokensMutation) (ent.Value, error) diff --git a/backend/ent/item.go b/backend/ent/item.go index 7e427d5..2bb9118 100644 --- a/backend/ent/item.go +++ b/backend/ent/item.go @@ -72,9 +72,11 @@ type ItemEdges struct { Fields []*ItemField `json:"fields,omitempty"` // Label holds the value of the label edge. Label []*Label `json:"label,omitempty"` + // Attachments holds the value of the attachments edge. + Attachments []*Attachment `json:"attachments,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [4]bool + loadedTypes [5]bool } // GroupOrErr returns the Group value or an error if the edge @@ -121,6 +123,15 @@ func (e ItemEdges) LabelOrErr() ([]*Label, error) { return nil, &NotLoadedError{edge: "label"} } +// AttachmentsOrErr returns the Attachments value or an error if the edge +// was not loaded in eager-loading. +func (e ItemEdges) AttachmentsOrErr() ([]*Attachment, error) { + if e.loadedTypes[4] { + return e.Attachments, nil + } + return nil, &NotLoadedError{edge: "attachments"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Item) scanValues(columns []string) ([]interface{}, error) { values := make([]interface{}, len(columns)) @@ -308,6 +319,11 @@ func (i *Item) QueryLabel() *LabelQuery { return (&ItemClient{config: i.config}).QueryLabel(i) } +// QueryAttachments queries the "attachments" edge of the Item entity. +func (i *Item) QueryAttachments() *AttachmentQuery { + return (&ItemClient{config: i.config}).QueryAttachments(i) +} + // Update returns a builder for updating this Item. // Note that you need to call Item.Unwrap() before calling this method if this Item // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/backend/ent/item/item.go b/backend/ent/item/item.go index 481d8e7..eff087e 100644 --- a/backend/ent/item/item.go +++ b/backend/ent/item/item.go @@ -57,6 +57,8 @@ const ( EdgeFields = "fields" // EdgeLabel holds the string denoting the label edge name in mutations. EdgeLabel = "label" + // EdgeAttachments holds the string denoting the attachments edge name in mutations. + EdgeAttachments = "attachments" // Table holds the table name of the item in the database. Table = "items" // GroupTable is the table that holds the group relation/edge. @@ -85,6 +87,13 @@ const ( // LabelInverseTable is the table name for the Label entity. // It exists in this package in order to avoid circular dependency with the "label" package. LabelInverseTable = "labels" + // AttachmentsTable is the table that holds the attachments relation/edge. + AttachmentsTable = "attachments" + // AttachmentsInverseTable is the table name for the Attachment entity. + // It exists in this package in order to avoid circular dependency with the "attachment" package. + AttachmentsInverseTable = "attachments" + // AttachmentsColumn is the table column denoting the attachments relation/edge. + AttachmentsColumn = "item_attachments" ) // Columns holds all SQL columns for item fields. diff --git a/backend/ent/item/where.go b/backend/ent/item/where.go index 58d9f68..85cf146 100644 --- a/backend/ent/item/where.go +++ b/backend/ent/item/where.go @@ -1940,6 +1940,34 @@ func HasLabelWith(preds ...predicate.Label) predicate.Item { }) } +// HasAttachments applies the HasEdge predicate on the "attachments" edge. +func HasAttachments() predicate.Item { + return predicate.Item(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(AttachmentsTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, AttachmentsTable, AttachmentsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasAttachmentsWith applies the HasEdge predicate on the "attachments" edge with a given conditions (other predicates). +func HasAttachmentsWith(preds ...predicate.Attachment) predicate.Item { + return predicate.Item(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(AttachmentsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, AttachmentsTable, AttachmentsColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Item) predicate.Item { return predicate.Item(func(s *sql.Selector) { diff --git a/backend/ent/item_create.go b/backend/ent/item_create.go index 2715420..f428fd9 100644 --- a/backend/ent/item_create.go +++ b/backend/ent/item_create.go @@ -11,6 +11,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/group" "github.com/hay-kot/content/backend/ent/item" "github.com/hay-kot/content/backend/ent/itemfield" @@ -343,6 +344,21 @@ func (ic *ItemCreate) AddLabel(l ...*Label) *ItemCreate { return ic.AddLabelIDs(ids...) } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs. +func (ic *ItemCreate) AddAttachmentIDs(ids ...uuid.UUID) *ItemCreate { + ic.mutation.AddAttachmentIDs(ids...) + return ic +} + +// AddAttachments adds the "attachments" edges to the Attachment entity. +func (ic *ItemCreate) AddAttachments(a ...*Attachment) *ItemCreate { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return ic.AddAttachmentIDs(ids...) +} + // Mutation returns the ItemMutation object of the builder. func (ic *ItemCreate) Mutation() *ItemMutation { return ic.mutation @@ -767,6 +783,25 @@ func (ic *ItemCreate) createSpec() (*Item, *sqlgraph.CreateSpec) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := ic.mutation.AttachmentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.AttachmentsTable, + Columns: []string{item.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/backend/ent/item_query.go b/backend/ent/item_query.go index b164239..a922b5b 100644 --- a/backend/ent/item_query.go +++ b/backend/ent/item_query.go @@ -12,6 +12,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/group" "github.com/hay-kot/content/backend/ent/item" "github.com/hay-kot/content/backend/ent/itemfield" @@ -23,17 +24,18 @@ import ( // ItemQuery is the builder for querying Item entities. type ItemQuery struct { config - limit *int - offset *int - unique *bool - order []OrderFunc - fields []string - predicates []predicate.Item - withGroup *GroupQuery - withLocation *LocationQuery - withFields *ItemFieldQuery - withLabel *LabelQuery - withFKs bool + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.Item + withGroup *GroupQuery + withLocation *LocationQuery + withFields *ItemFieldQuery + withLabel *LabelQuery + withAttachments *AttachmentQuery + withFKs bool // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -158,6 +160,28 @@ func (iq *ItemQuery) QueryLabel() *LabelQuery { return query } +// QueryAttachments chains the current query on the "attachments" edge. +func (iq *ItemQuery) QueryAttachments() *AttachmentQuery { + query := &AttachmentQuery{config: iq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := iq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := iq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(item.Table, item.FieldID, selector), + sqlgraph.To(attachment.Table, attachment.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, item.AttachmentsTable, item.AttachmentsColumn), + ) + fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Item entity from the query. // Returns a *NotFoundError when no Item was found. func (iq *ItemQuery) First(ctx context.Context) (*Item, error) { @@ -334,15 +358,16 @@ func (iq *ItemQuery) Clone() *ItemQuery { return nil } return &ItemQuery{ - config: iq.config, - limit: iq.limit, - offset: iq.offset, - order: append([]OrderFunc{}, iq.order...), - predicates: append([]predicate.Item{}, iq.predicates...), - withGroup: iq.withGroup.Clone(), - withLocation: iq.withLocation.Clone(), - withFields: iq.withFields.Clone(), - withLabel: iq.withLabel.Clone(), + config: iq.config, + limit: iq.limit, + offset: iq.offset, + order: append([]OrderFunc{}, iq.order...), + predicates: append([]predicate.Item{}, iq.predicates...), + withGroup: iq.withGroup.Clone(), + withLocation: iq.withLocation.Clone(), + withFields: iq.withFields.Clone(), + withLabel: iq.withLabel.Clone(), + withAttachments: iq.withAttachments.Clone(), // clone intermediate query. sql: iq.sql.Clone(), path: iq.path, @@ -394,6 +419,17 @@ func (iq *ItemQuery) WithLabel(opts ...func(*LabelQuery)) *ItemQuery { return iq } +// WithAttachments tells the query-builder to eager-load the nodes that are connected to +// the "attachments" edge. The optional arguments are used to configure the query builder of the edge. +func (iq *ItemQuery) WithAttachments(opts ...func(*AttachmentQuery)) *ItemQuery { + query := &AttachmentQuery{config: iq.config} + for _, opt := range opts { + opt(query) + } + iq.withAttachments = query + return iq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -463,11 +499,12 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e nodes = []*Item{} withFKs = iq.withFKs _spec = iq.querySpec() - loadedTypes = [4]bool{ + loadedTypes = [5]bool{ iq.withGroup != nil, iq.withLocation != nil, iq.withFields != nil, iq.withLabel != nil, + iq.withAttachments != nil, } ) if iq.withGroup != nil || iq.withLocation != nil { @@ -520,6 +557,13 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e return nil, err } } + if query := iq.withAttachments; query != nil { + if err := iq.loadAttachments(ctx, query, nodes, + func(n *Item) { n.Edges.Attachments = []*Attachment{} }, + func(n *Item, e *Attachment) { n.Edges.Attachments = append(n.Edges.Attachments, e) }); err != nil { + return nil, err + } + } return nodes, nil } @@ -670,6 +714,37 @@ func (iq *ItemQuery) loadLabel(ctx context.Context, query *LabelQuery, nodes []* } return nil } +func (iq *ItemQuery) loadAttachments(ctx context.Context, query *AttachmentQuery, nodes []*Item, init func(*Item), assign func(*Item, *Attachment)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[uuid.UUID]*Item) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + query.withFKs = true + query.Where(predicate.Attachment(func(s *sql.Selector) { + s.Where(sql.InValues(item.AttachmentsColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.item_attachments + if fk == nil { + return fmt.Errorf(`foreign-key "item_attachments" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return fmt.Errorf(`unexpected foreign-key "item_attachments" returned %v for node %v`, *fk, n.ID) + } + assign(node, n) + } + return nil +} func (iq *ItemQuery) sqlCount(ctx context.Context) (int, error) { _spec := iq.querySpec() diff --git a/backend/ent/item_update.go b/backend/ent/item_update.go index f2aa155..ec63be4 100644 --- a/backend/ent/item_update.go +++ b/backend/ent/item_update.go @@ -12,6 +12,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/group" "github.com/hay-kot/content/backend/ent/item" "github.com/hay-kot/content/backend/ent/itemfield" @@ -401,6 +402,21 @@ func (iu *ItemUpdate) AddLabel(l ...*Label) *ItemUpdate { return iu.AddLabelIDs(ids...) } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs. +func (iu *ItemUpdate) AddAttachmentIDs(ids ...uuid.UUID) *ItemUpdate { + iu.mutation.AddAttachmentIDs(ids...) + return iu +} + +// AddAttachments adds the "attachments" edges to the Attachment entity. +func (iu *ItemUpdate) AddAttachments(a ...*Attachment) *ItemUpdate { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return iu.AddAttachmentIDs(ids...) +} + // Mutation returns the ItemMutation object of the builder. func (iu *ItemUpdate) Mutation() *ItemMutation { return iu.mutation @@ -460,6 +476,27 @@ func (iu *ItemUpdate) RemoveLabel(l ...*Label) *ItemUpdate { return iu.RemoveLabelIDs(ids...) } +// ClearAttachments clears all "attachments" edges to the Attachment entity. +func (iu *ItemUpdate) ClearAttachments() *ItemUpdate { + iu.mutation.ClearAttachments() + return iu +} + +// RemoveAttachmentIDs removes the "attachments" edge to Attachment entities by IDs. +func (iu *ItemUpdate) RemoveAttachmentIDs(ids ...uuid.UUID) *ItemUpdate { + iu.mutation.RemoveAttachmentIDs(ids...) + return iu +} + +// RemoveAttachments removes "attachments" edges to Attachment entities. +func (iu *ItemUpdate) RemoveAttachments(a ...*Attachment) *ItemUpdate { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return iu.RemoveAttachmentIDs(ids...) +} + // Save executes the query and returns the number of nodes affected by the update operation. func (iu *ItemUpdate) Save(ctx context.Context) (int, error) { var ( @@ -978,6 +1015,60 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if iu.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.AttachmentsTable, + Columns: []string{item.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iu.mutation.RemovedAttachmentsIDs(); len(nodes) > 0 && !iu.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.AttachmentsTable, + Columns: []string{item.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iu.mutation.AttachmentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.AttachmentsTable, + Columns: []string{item.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, iu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{item.Label} @@ -1365,6 +1456,21 @@ func (iuo *ItemUpdateOne) AddLabel(l ...*Label) *ItemUpdateOne { return iuo.AddLabelIDs(ids...) } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs. +func (iuo *ItemUpdateOne) AddAttachmentIDs(ids ...uuid.UUID) *ItemUpdateOne { + iuo.mutation.AddAttachmentIDs(ids...) + return iuo +} + +// AddAttachments adds the "attachments" edges to the Attachment entity. +func (iuo *ItemUpdateOne) AddAttachments(a ...*Attachment) *ItemUpdateOne { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return iuo.AddAttachmentIDs(ids...) +} + // Mutation returns the ItemMutation object of the builder. func (iuo *ItemUpdateOne) Mutation() *ItemMutation { return iuo.mutation @@ -1424,6 +1530,27 @@ func (iuo *ItemUpdateOne) RemoveLabel(l ...*Label) *ItemUpdateOne { return iuo.RemoveLabelIDs(ids...) } +// ClearAttachments clears all "attachments" edges to the Attachment entity. +func (iuo *ItemUpdateOne) ClearAttachments() *ItemUpdateOne { + iuo.mutation.ClearAttachments() + return iuo +} + +// RemoveAttachmentIDs removes the "attachments" edge to Attachment entities by IDs. +func (iuo *ItemUpdateOne) RemoveAttachmentIDs(ids ...uuid.UUID) *ItemUpdateOne { + iuo.mutation.RemoveAttachmentIDs(ids...) + return iuo +} + +// RemoveAttachments removes "attachments" edges to Attachment entities. +func (iuo *ItemUpdateOne) RemoveAttachments(a ...*Attachment) *ItemUpdateOne { + ids := make([]uuid.UUID, len(a)) + for i := range a { + ids[i] = a[i].ID + } + return iuo.RemoveAttachmentIDs(ids...) +} + // Select allows selecting one or more fields (columns) of the returned entity. // The default is selecting all fields defined in the entity schema. func (iuo *ItemUpdateOne) Select(field string, fields ...string) *ItemUpdateOne { @@ -1972,6 +2099,60 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error) } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if iuo.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.AttachmentsTable, + Columns: []string{item.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iuo.mutation.RemovedAttachmentsIDs(); len(nodes) > 0 && !iuo.mutation.AttachmentsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.AttachmentsTable, + Columns: []string{item.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iuo.mutation.AttachmentsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.AttachmentsTable, + Columns: []string{item.AttachmentsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: attachment.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _node = &Item{config: iuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/backend/ent/migrate/schema.go b/backend/ent/migrate/schema.go index c2cfc00..8bdfb1e 100644 --- a/backend/ent/migrate/schema.go +++ b/backend/ent/migrate/schema.go @@ -8,6 +8,35 @@ import ( ) var ( + // AttachmentsColumns holds the columns for the "attachments" table. + AttachmentsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeUUID}, + {Name: "created_at", Type: field.TypeTime}, + {Name: "updated_at", Type: field.TypeTime}, + {Name: "type", Type: field.TypeEnum, Enums: []string{"photo", "manual", "warranty", "attachment"}, Default: "attachment"}, + {Name: "document_attachments", Type: field.TypeUUID}, + {Name: "item_attachments", Type: field.TypeUUID}, + } + // AttachmentsTable holds the schema information for the "attachments" table. + AttachmentsTable = &schema.Table{ + Name: "attachments", + Columns: AttachmentsColumns, + PrimaryKey: []*schema.Column{AttachmentsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "attachments_documents_attachments", + Columns: []*schema.Column{AttachmentsColumns[4]}, + RefColumns: []*schema.Column{DocumentsColumns[0]}, + OnDelete: schema.Cascade, + }, + { + Symbol: "attachments_items_attachments", + Columns: []*schema.Column{AttachmentsColumns[5]}, + RefColumns: []*schema.Column{ItemsColumns[0]}, + OnDelete: schema.Cascade, + }, + }, + } // AuthTokensColumns holds the columns for the "auth_tokens" table. AuthTokensColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID}, @@ -299,6 +328,7 @@ var ( } // Tables holds all the tables in the schema. Tables = []*schema.Table{ + AttachmentsTable, AuthTokensTable, DocumentsTable, DocumentTokensTable, @@ -313,6 +343,8 @@ var ( ) func init() { + AttachmentsTable.ForeignKeys[0].RefTable = DocumentsTable + AttachmentsTable.ForeignKeys[1].RefTable = ItemsTable AuthTokensTable.ForeignKeys[0].RefTable = UsersTable DocumentsTable.ForeignKeys[0].RefTable = GroupsTable DocumentTokensTable.ForeignKeys[0].RefTable = DocumentsTable diff --git a/backend/ent/mutation.go b/backend/ent/mutation.go index fc3d35b..a36fc46 100644 --- a/backend/ent/mutation.go +++ b/backend/ent/mutation.go @@ -10,6 +10,7 @@ import ( "time" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/authtokens" "github.com/hay-kot/content/backend/ent/document" "github.com/hay-kot/content/backend/ent/documenttoken" @@ -33,6 +34,7 @@ const ( OpUpdateOne = ent.OpUpdateOne // Node types. + TypeAttachment = "Attachment" TypeAuthTokens = "AuthTokens" TypeDocument = "Document" TypeDocumentToken = "DocumentToken" @@ -44,6 +46,559 @@ const ( TypeUser = "User" ) +// AttachmentMutation represents an operation that mutates the Attachment nodes in the graph. +type AttachmentMutation struct { + config + op Op + typ string + id *uuid.UUID + created_at *time.Time + updated_at *time.Time + _type *attachment.Type + clearedFields map[string]struct{} + item *uuid.UUID + cleareditem bool + document *uuid.UUID + cleareddocument bool + done bool + oldValue func(context.Context) (*Attachment, error) + predicates []predicate.Attachment +} + +var _ ent.Mutation = (*AttachmentMutation)(nil) + +// attachmentOption allows management of the mutation configuration using functional options. +type attachmentOption func(*AttachmentMutation) + +// newAttachmentMutation creates new mutation for the Attachment entity. +func newAttachmentMutation(c config, op Op, opts ...attachmentOption) *AttachmentMutation { + m := &AttachmentMutation{ + config: c, + op: op, + typ: TypeAttachment, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withAttachmentID sets the ID field of the mutation. +func withAttachmentID(id uuid.UUID) attachmentOption { + return func(m *AttachmentMutation) { + var ( + err error + once sync.Once + value *Attachment + ) + m.oldValue = func(ctx context.Context) (*Attachment, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Attachment.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withAttachment sets the old Attachment of the mutation. +func withAttachment(node *Attachment) attachmentOption { + return func(m *AttachmentMutation) { + m.oldValue = func(context.Context) (*Attachment, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m AttachmentMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m AttachmentMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of Attachment entities. +func (m *AttachmentMutation) SetID(id uuid.UUID) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *AttachmentMutation) ID() (id uuid.UUID, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *AttachmentMutation) IDs(ctx context.Context) ([]uuid.UUID, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []uuid.UUID{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Attachment.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *AttachmentMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *AttachmentMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Attachment entity. +// If the Attachment object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AttachmentMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *AttachmentMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *AttachmentMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *AttachmentMutation) UpdatedAt() (r time.Time, exists bool) { + v := m.updated_at + if v == nil { + return + } + return *v, true +} + +// OldUpdatedAt returns the old "updated_at" field's value of the Attachment entity. +// If the Attachment object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AttachmentMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUpdatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err) + } + return oldValue.UpdatedAt, nil +} + +// ResetUpdatedAt resets all changes to the "updated_at" field. +func (m *AttachmentMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetType sets the "type" field. +func (m *AttachmentMutation) SetType(a attachment.Type) { + m._type = &a +} + +// GetType returns the value of the "type" field in the mutation. +func (m *AttachmentMutation) GetType() (r attachment.Type, exists bool) { + v := m._type + if v == nil { + return + } + return *v, true +} + +// OldType returns the old "type" field's value of the Attachment entity. +// If the Attachment object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *AttachmentMutation) OldType(ctx context.Context) (v attachment.Type, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldType is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldType requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldType: %w", err) + } + return oldValue.Type, nil +} + +// ResetType resets all changes to the "type" field. +func (m *AttachmentMutation) ResetType() { + m._type = nil +} + +// SetItemID sets the "item" edge to the Item entity by id. +func (m *AttachmentMutation) SetItemID(id uuid.UUID) { + m.item = &id +} + +// ClearItem clears the "item" edge to the Item entity. +func (m *AttachmentMutation) ClearItem() { + m.cleareditem = true +} + +// ItemCleared reports if the "item" edge to the Item entity was cleared. +func (m *AttachmentMutation) ItemCleared() bool { + return m.cleareditem +} + +// ItemID returns the "item" edge ID in the mutation. +func (m *AttachmentMutation) ItemID() (id uuid.UUID, exists bool) { + if m.item != nil { + return *m.item, true + } + return +} + +// ItemIDs returns the "item" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ItemID instead. It exists only for internal usage by the builders. +func (m *AttachmentMutation) ItemIDs() (ids []uuid.UUID) { + if id := m.item; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetItem resets all changes to the "item" edge. +func (m *AttachmentMutation) ResetItem() { + m.item = nil + m.cleareditem = false +} + +// SetDocumentID sets the "document" edge to the Document entity by id. +func (m *AttachmentMutation) SetDocumentID(id uuid.UUID) { + m.document = &id +} + +// ClearDocument clears the "document" edge to the Document entity. +func (m *AttachmentMutation) ClearDocument() { + m.cleareddocument = true +} + +// DocumentCleared reports if the "document" edge to the Document entity was cleared. +func (m *AttachmentMutation) DocumentCleared() bool { + return m.cleareddocument +} + +// DocumentID returns the "document" edge ID in the mutation. +func (m *AttachmentMutation) DocumentID() (id uuid.UUID, exists bool) { + if m.document != nil { + return *m.document, true + } + return +} + +// DocumentIDs returns the "document" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// DocumentID instead. It exists only for internal usage by the builders. +func (m *AttachmentMutation) DocumentIDs() (ids []uuid.UUID) { + if id := m.document; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetDocument resets all changes to the "document" edge. +func (m *AttachmentMutation) ResetDocument() { + m.document = nil + m.cleareddocument = false +} + +// Where appends a list predicates to the AttachmentMutation builder. +func (m *AttachmentMutation) Where(ps ...predicate.Attachment) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *AttachmentMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (Attachment). +func (m *AttachmentMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *AttachmentMutation) Fields() []string { + fields := make([]string, 0, 3) + if m.created_at != nil { + fields = append(fields, attachment.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, attachment.FieldUpdatedAt) + } + if m._type != nil { + fields = append(fields, attachment.FieldType) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *AttachmentMutation) Field(name string) (ent.Value, bool) { + switch name { + case attachment.FieldCreatedAt: + return m.CreatedAt() + case attachment.FieldUpdatedAt: + return m.UpdatedAt() + case attachment.FieldType: + return m.GetType() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *AttachmentMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case attachment.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case attachment.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case attachment.FieldType: + return m.OldType(ctx) + } + return nil, fmt.Errorf("unknown Attachment field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *AttachmentMutation) SetField(name string, value ent.Value) error { + switch name { + case attachment.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case attachment.FieldUpdatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUpdatedAt(v) + return nil + case attachment.FieldType: + v, ok := value.(attachment.Type) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetType(v) + return nil + } + return fmt.Errorf("unknown Attachment field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *AttachmentMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *AttachmentMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *AttachmentMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown Attachment numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *AttachmentMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *AttachmentMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *AttachmentMutation) ClearField(name string) error { + return fmt.Errorf("unknown Attachment nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *AttachmentMutation) ResetField(name string) error { + switch name { + case attachment.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case attachment.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case attachment.FieldType: + m.ResetType() + return nil + } + return fmt.Errorf("unknown Attachment field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *AttachmentMutation) AddedEdges() []string { + edges := make([]string, 0, 2) + if m.item != nil { + edges = append(edges, attachment.EdgeItem) + } + if m.document != nil { + edges = append(edges, attachment.EdgeDocument) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *AttachmentMutation) AddedIDs(name string) []ent.Value { + switch name { + case attachment.EdgeItem: + if id := m.item; id != nil { + return []ent.Value{*id} + } + case attachment.EdgeDocument: + if id := m.document; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *AttachmentMutation) RemovedEdges() []string { + edges := make([]string, 0, 2) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *AttachmentMutation) RemovedIDs(name string) []ent.Value { + switch name { + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *AttachmentMutation) ClearedEdges() []string { + edges := make([]string, 0, 2) + if m.cleareditem { + edges = append(edges, attachment.EdgeItem) + } + if m.cleareddocument { + edges = append(edges, attachment.EdgeDocument) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *AttachmentMutation) EdgeCleared(name string) bool { + switch name { + case attachment.EdgeItem: + return m.cleareditem + case attachment.EdgeDocument: + return m.cleareddocument + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *AttachmentMutation) ClearEdge(name string) error { + switch name { + case attachment.EdgeItem: + m.ClearItem() + return nil + case attachment.EdgeDocument: + m.ClearDocument() + return nil + } + return fmt.Errorf("unknown Attachment unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *AttachmentMutation) ResetEdge(name string) error { + switch name { + case attachment.EdgeItem: + m.ResetItem() + return nil + case attachment.EdgeDocument: + m.ResetDocument() + return nil + } + return fmt.Errorf("unknown Attachment edge %s", name) +} + // AuthTokensMutation represents an operation that mutates the AuthTokens nodes in the graph. type AuthTokensMutation struct { config @@ -608,6 +1163,9 @@ type DocumentMutation struct { document_tokens map[uuid.UUID]struct{} removeddocument_tokens map[uuid.UUID]struct{} cleareddocument_tokens bool + attachments map[uuid.UUID]struct{} + removedattachments map[uuid.UUID]struct{} + clearedattachments bool done bool oldValue func(context.Context) (*Document, error) predicates []predicate.Document @@ -954,6 +1512,60 @@ func (m *DocumentMutation) ResetDocumentTokens() { m.removeddocument_tokens = nil } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by ids. +func (m *DocumentMutation) AddAttachmentIDs(ids ...uuid.UUID) { + if m.attachments == nil { + m.attachments = make(map[uuid.UUID]struct{}) + } + for i := range ids { + m.attachments[ids[i]] = struct{}{} + } +} + +// ClearAttachments clears the "attachments" edge to the Attachment entity. +func (m *DocumentMutation) ClearAttachments() { + m.clearedattachments = true +} + +// AttachmentsCleared reports if the "attachments" edge to the Attachment entity was cleared. +func (m *DocumentMutation) AttachmentsCleared() bool { + return m.clearedattachments +} + +// RemoveAttachmentIDs removes the "attachments" edge to the Attachment entity by IDs. +func (m *DocumentMutation) RemoveAttachmentIDs(ids ...uuid.UUID) { + if m.removedattachments == nil { + m.removedattachments = make(map[uuid.UUID]struct{}) + } + for i := range ids { + delete(m.attachments, ids[i]) + m.removedattachments[ids[i]] = struct{}{} + } +} + +// RemovedAttachments returns the removed IDs of the "attachments" edge to the Attachment entity. +func (m *DocumentMutation) RemovedAttachmentsIDs() (ids []uuid.UUID) { + for id := range m.removedattachments { + ids = append(ids, id) + } + return +} + +// AttachmentsIDs returns the "attachments" edge IDs in the mutation. +func (m *DocumentMutation) AttachmentsIDs() (ids []uuid.UUID) { + for id := range m.attachments { + ids = append(ids, id) + } + return +} + +// ResetAttachments resets all changes to the "attachments" edge. +func (m *DocumentMutation) ResetAttachments() { + m.attachments = nil + m.clearedattachments = false + m.removedattachments = nil +} + // Where appends a list predicates to the DocumentMutation builder. func (m *DocumentMutation) Where(ps ...predicate.Document) { m.predicates = append(m.predicates, ps...) @@ -1123,13 +1735,16 @@ func (m *DocumentMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *DocumentMutation) AddedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.group != nil { edges = append(edges, document.EdgeGroup) } if m.document_tokens != nil { edges = append(edges, document.EdgeDocumentTokens) } + if m.attachments != nil { + edges = append(edges, document.EdgeAttachments) + } return edges } @@ -1147,16 +1762,25 @@ func (m *DocumentMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case document.EdgeAttachments: + ids := make([]ent.Value, 0, len(m.attachments)) + for id := range m.attachments { + ids = append(ids, id) + } + return ids } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *DocumentMutation) RemovedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.removeddocument_tokens != nil { edges = append(edges, document.EdgeDocumentTokens) } + if m.removedattachments != nil { + edges = append(edges, document.EdgeAttachments) + } return edges } @@ -1170,19 +1794,28 @@ func (m *DocumentMutation) RemovedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case document.EdgeAttachments: + ids := make([]ent.Value, 0, len(m.removedattachments)) + for id := range m.removedattachments { + ids = append(ids, id) + } + return ids } return nil } // ClearedEdges returns all edge names that were cleared in this mutation. func (m *DocumentMutation) ClearedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.clearedgroup { edges = append(edges, document.EdgeGroup) } if m.cleareddocument_tokens { edges = append(edges, document.EdgeDocumentTokens) } + if m.clearedattachments { + edges = append(edges, document.EdgeAttachments) + } return edges } @@ -1194,6 +1827,8 @@ func (m *DocumentMutation) EdgeCleared(name string) bool { return m.clearedgroup case document.EdgeDocumentTokens: return m.cleareddocument_tokens + case document.EdgeAttachments: + return m.clearedattachments } return false } @@ -1219,6 +1854,9 @@ func (m *DocumentMutation) ResetEdge(name string) error { case document.EdgeDocumentTokens: m.ResetDocumentTokens() return nil + case document.EdgeAttachments: + m.ResetAttachments() + return nil } return fmt.Errorf("unknown Document edge %s", name) } @@ -2768,43 +3406,46 @@ func (m *GroupMutation) ResetEdge(name string) error { // ItemMutation represents an operation that mutates the Item nodes in the graph. type ItemMutation struct { config - op Op - typ string - id *uuid.UUID - created_at *time.Time - updated_at *time.Time - name *string - description *string - notes *string - serial_number *string - model_number *string - manufacturer *string - lifetime_warranty *bool - warranty_expires *time.Time - warranty_details *string - purchase_time *time.Time - purchase_from *string - purchase_price *float64 - addpurchase_price *float64 - sold_time *time.Time - sold_to *string - sold_price *float64 - addsold_price *float64 - sold_notes *string - clearedFields map[string]struct{} - group *uuid.UUID - clearedgroup bool - location *uuid.UUID - clearedlocation bool - fields map[uuid.UUID]struct{} - removedfields map[uuid.UUID]struct{} - clearedfields bool - label map[uuid.UUID]struct{} - removedlabel map[uuid.UUID]struct{} - clearedlabel bool - done bool - oldValue func(context.Context) (*Item, error) - predicates []predicate.Item + op Op + typ string + id *uuid.UUID + created_at *time.Time + updated_at *time.Time + name *string + description *string + notes *string + serial_number *string + model_number *string + manufacturer *string + lifetime_warranty *bool + warranty_expires *time.Time + warranty_details *string + purchase_time *time.Time + purchase_from *string + purchase_price *float64 + addpurchase_price *float64 + sold_time *time.Time + sold_to *string + sold_price *float64 + addsold_price *float64 + sold_notes *string + clearedFields map[string]struct{} + group *uuid.UUID + clearedgroup bool + location *uuid.UUID + clearedlocation bool + fields map[uuid.UUID]struct{} + removedfields map[uuid.UUID]struct{} + clearedfields bool + label map[uuid.UUID]struct{} + removedlabel map[uuid.UUID]struct{} + clearedlabel bool + attachments map[uuid.UUID]struct{} + removedattachments map[uuid.UUID]struct{} + clearedattachments bool + done bool + oldValue func(context.Context) (*Item, error) + predicates []predicate.Item } var _ ent.Mutation = (*ItemMutation)(nil) @@ -3941,6 +4582,60 @@ func (m *ItemMutation) ResetLabel() { m.removedlabel = nil } +// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by ids. +func (m *ItemMutation) AddAttachmentIDs(ids ...uuid.UUID) { + if m.attachments == nil { + m.attachments = make(map[uuid.UUID]struct{}) + } + for i := range ids { + m.attachments[ids[i]] = struct{}{} + } +} + +// ClearAttachments clears the "attachments" edge to the Attachment entity. +func (m *ItemMutation) ClearAttachments() { + m.clearedattachments = true +} + +// AttachmentsCleared reports if the "attachments" edge to the Attachment entity was cleared. +func (m *ItemMutation) AttachmentsCleared() bool { + return m.clearedattachments +} + +// RemoveAttachmentIDs removes the "attachments" edge to the Attachment entity by IDs. +func (m *ItemMutation) RemoveAttachmentIDs(ids ...uuid.UUID) { + if m.removedattachments == nil { + m.removedattachments = make(map[uuid.UUID]struct{}) + } + for i := range ids { + delete(m.attachments, ids[i]) + m.removedattachments[ids[i]] = struct{}{} + } +} + +// RemovedAttachments returns the removed IDs of the "attachments" edge to the Attachment entity. +func (m *ItemMutation) RemovedAttachmentsIDs() (ids []uuid.UUID) { + for id := range m.removedattachments { + ids = append(ids, id) + } + return +} + +// AttachmentsIDs returns the "attachments" edge IDs in the mutation. +func (m *ItemMutation) AttachmentsIDs() (ids []uuid.UUID) { + for id := range m.attachments { + ids = append(ids, id) + } + return +} + +// ResetAttachments resets all changes to the "attachments" edge. +func (m *ItemMutation) ResetAttachments() { + m.attachments = nil + m.clearedattachments = false + m.removedattachments = nil +} + // Where appends a list predicates to the ItemMutation builder. func (m *ItemMutation) Where(ps ...predicate.Item) { m.predicates = append(m.predicates, ps...) @@ -4450,7 +5145,7 @@ func (m *ItemMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *ItemMutation) AddedEdges() []string { - edges := make([]string, 0, 4) + edges := make([]string, 0, 5) if m.group != nil { edges = append(edges, item.EdgeGroup) } @@ -4463,6 +5158,9 @@ func (m *ItemMutation) AddedEdges() []string { if m.label != nil { edges = append(edges, item.EdgeLabel) } + if m.attachments != nil { + edges = append(edges, item.EdgeAttachments) + } return edges } @@ -4490,19 +5188,28 @@ func (m *ItemMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case item.EdgeAttachments: + ids := make([]ent.Value, 0, len(m.attachments)) + for id := range m.attachments { + ids = append(ids, id) + } + return ids } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *ItemMutation) RemovedEdges() []string { - edges := make([]string, 0, 4) + edges := make([]string, 0, 5) if m.removedfields != nil { edges = append(edges, item.EdgeFields) } if m.removedlabel != nil { edges = append(edges, item.EdgeLabel) } + if m.removedattachments != nil { + edges = append(edges, item.EdgeAttachments) + } return edges } @@ -4522,13 +5229,19 @@ func (m *ItemMutation) RemovedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case item.EdgeAttachments: + ids := make([]ent.Value, 0, len(m.removedattachments)) + for id := range m.removedattachments { + ids = append(ids, id) + } + return ids } return nil } // ClearedEdges returns all edge names that were cleared in this mutation. func (m *ItemMutation) ClearedEdges() []string { - edges := make([]string, 0, 4) + edges := make([]string, 0, 5) if m.clearedgroup { edges = append(edges, item.EdgeGroup) } @@ -4541,6 +5254,9 @@ func (m *ItemMutation) ClearedEdges() []string { if m.clearedlabel { edges = append(edges, item.EdgeLabel) } + if m.clearedattachments { + edges = append(edges, item.EdgeAttachments) + } return edges } @@ -4556,6 +5272,8 @@ func (m *ItemMutation) EdgeCleared(name string) bool { return m.clearedfields case item.EdgeLabel: return m.clearedlabel + case item.EdgeAttachments: + return m.clearedattachments } return false } @@ -4590,6 +5308,9 @@ func (m *ItemMutation) ResetEdge(name string) error { case item.EdgeLabel: m.ResetLabel() return nil + case item.EdgeAttachments: + m.ResetAttachments() + return nil } return fmt.Errorf("unknown Item edge %s", name) } diff --git a/backend/ent/predicate/predicate.go b/backend/ent/predicate/predicate.go index 7d96d7f..4287b9d 100644 --- a/backend/ent/predicate/predicate.go +++ b/backend/ent/predicate/predicate.go @@ -6,6 +6,9 @@ import ( "entgo.io/ent/dialect/sql" ) +// Attachment is the predicate function for attachment builders. +type Attachment func(*sql.Selector) + // AuthTokens is the predicate function for authtokens builders. type AuthTokens func(*sql.Selector) diff --git a/backend/ent/runtime.go b/backend/ent/runtime.go index d5d5eb8..6623741 100644 --- a/backend/ent/runtime.go +++ b/backend/ent/runtime.go @@ -6,6 +6,7 @@ import ( "time" "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent/attachment" "github.com/hay-kot/content/backend/ent/authtokens" "github.com/hay-kot/content/backend/ent/document" "github.com/hay-kot/content/backend/ent/documenttoken" @@ -22,6 +23,25 @@ import ( // (default values, validators, hooks and policies) and stitches it // to their package variables. func init() { + attachmentMixin := schema.Attachment{}.Mixin() + attachmentMixinFields0 := attachmentMixin[0].Fields() + _ = attachmentMixinFields0 + attachmentFields := schema.Attachment{}.Fields() + _ = attachmentFields + // attachmentDescCreatedAt is the schema descriptor for created_at field. + attachmentDescCreatedAt := attachmentMixinFields0[1].Descriptor() + // attachment.DefaultCreatedAt holds the default value on creation for the created_at field. + attachment.DefaultCreatedAt = attachmentDescCreatedAt.Default.(func() time.Time) + // attachmentDescUpdatedAt is the schema descriptor for updated_at field. + attachmentDescUpdatedAt := attachmentMixinFields0[2].Descriptor() + // attachment.DefaultUpdatedAt holds the default value on creation for the updated_at field. + attachment.DefaultUpdatedAt = attachmentDescUpdatedAt.Default.(func() time.Time) + // attachment.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + attachment.UpdateDefaultUpdatedAt = attachmentDescUpdatedAt.UpdateDefault.(func() time.Time) + // attachmentDescID is the schema descriptor for id field. + attachmentDescID := attachmentMixinFields0[0].Descriptor() + // attachment.DefaultID holds the default value on creation for the id field. + attachment.DefaultID = attachmentDescID.Default.(func() uuid.UUID) authtokensMixin := schema.AuthTokens{}.Mixin() authtokensMixinFields0 := authtokensMixin[0].Fields() _ = authtokensMixinFields0 diff --git a/backend/ent/schema/attachment.go b/backend/ent/schema/attachment.go new file mode 100644 index 0000000..b0adb8c --- /dev/null +++ b/backend/ent/schema/attachment.go @@ -0,0 +1,42 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "github.com/hay-kot/content/backend/ent/schema/mixins" +) + +// Attachment holds the schema definition for the Attachment entity. +type Attachment struct { + ent.Schema +} + +func (Attachment) Mixin() []ent.Mixin { + return []ent.Mixin{ + mixins.BaseMixin{}, + } +} + +// Fields of the Attachment. +func (Attachment) Fields() []ent.Field { + return []ent.Field{ + field.Enum("type"). + Values("photo", "manual", "warranty", "attachment"). + Default("attachment"), + } +} + +// Edges of the Attachment. +func (Attachment) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("item", Item.Type). + Ref("attachments"). + Required(). + Unique(), + edge.From("document", Document.Type). + Ref("attachments"). + Required(). + Unique(), + } +} diff --git a/backend/ent/schema/document.go b/backend/ent/schema/document.go index 4a34b92..9797b0f 100644 --- a/backend/ent/schema/document.go +++ b/backend/ent/schema/document.go @@ -42,5 +42,9 @@ func (Document) Edges() []ent.Edge { Annotations(entsql.Annotation{ OnDelete: entsql.Cascade, }), + edge.To("attachments", Attachment.Type). + Annotations(entsql.Annotation{ + OnDelete: entsql.Cascade, + }), } } diff --git a/backend/ent/schema/item.go b/backend/ent/schema/item.go index 8c2f4cc..30473e0 100644 --- a/backend/ent/schema/item.go +++ b/backend/ent/schema/item.go @@ -93,10 +93,15 @@ func (Item) Edges() []ent.Edge { edge.From("location", Location.Type). Ref("items"). Unique(), - edge.To("fields", ItemField.Type).Annotations(entsql.Annotation{ - OnDelete: entsql.Cascade, - }), + edge.To("fields", ItemField.Type). + Annotations(entsql.Annotation{ + OnDelete: entsql.Cascade, + }), edge.From("label", Label.Type). Ref("items"), + edge.To("attachments", Attachment.Type). + Annotations(entsql.Annotation{ + OnDelete: entsql.Cascade, + }), } } diff --git a/backend/ent/tx.go b/backend/ent/tx.go index 6dc9a55..b062e19 100644 --- a/backend/ent/tx.go +++ b/backend/ent/tx.go @@ -12,6 +12,8 @@ import ( // Tx is a transactional client that is created by calling Client.Tx(). type Tx struct { config + // Attachment is the client for interacting with the Attachment builders. + Attachment *AttachmentClient // AuthTokens is the client for interacting with the AuthTokens builders. AuthTokens *AuthTokensClient // Document is the client for interacting with the Document builders. @@ -165,6 +167,7 @@ func (tx *Tx) Client() *Client { } func (tx *Tx) init() { + tx.Attachment = NewAttachmentClient(tx.config) tx.AuthTokens = NewAuthTokensClient(tx.config) tx.Document = NewDocumentClient(tx.config) tx.DocumentToken = NewDocumentTokenClient(tx.config) @@ -183,7 +186,7 @@ func (tx *Tx) init() { // of them in order to commit or rollback the transaction. // // If a closed transaction is embedded in one of the generated entities, and the entity -// applies a query, for example: AuthTokens.QueryXXX(), the query will be executed +// applies a query, for example: Attachment.QueryXXX(), the query will be executed // through the driver which created this transaction. // // Note that txDriver is not goroutine safe. diff --git a/backend/internal/repo/repo_item_attachments.go b/backend/internal/repo/repo_item_attachments.go new file mode 100644 index 0000000..f21bb7e --- /dev/null +++ b/backend/internal/repo/repo_item_attachments.go @@ -0,0 +1,44 @@ +package repo + +import ( + "context" + + "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent" + "github.com/hay-kot/content/backend/ent/attachment" +) + +// AttachmentRepo is a repository for Attachments table that links Items to Documents +// While also specifying the type of the attachment. This _ONLY_ provides basic Create Update +// And Delete operations. For accessing the actual documents, use the Items repository since it +// provides the attachments with the documents. +type AttachmentRepo struct { + db *ent.Client +} + +func (r *AttachmentRepo) Create(ctx context.Context, itemId, docId uuid.UUID, typ attachment.Type) (*ent.Attachment, error) { + return r.db.Attachment.Create(). + SetType(typ). + SetDocumentID(docId). + SetItemID(itemId). + Save(ctx) +} + +func (r *AttachmentRepo) Get(ctx context.Context, id uuid.UUID) (*ent.Attachment, error) { + return r.db.Attachment. + Query(). + Where(attachment.ID(id)). + WithItem(). + WithDocument(). + Only(ctx) +} + +func (r *AttachmentRepo) Update(ctx context.Context, itemId uuid.UUID, typ attachment.Type) (*ent.Attachment, error) { + return r.db.Attachment.UpdateOneID(itemId). + SetType(typ). + Save(ctx) +} + +func (r *AttachmentRepo) Delete(ctx context.Context, id uuid.UUID) error { + return r.db.Attachment.DeleteOneID(id).Exec(ctx) +} diff --git a/backend/internal/repo/repo_item_attachments_test.go b/backend/internal/repo/repo_item_attachments_test.go new file mode 100644 index 0000000..0165b8e --- /dev/null +++ b/backend/internal/repo/repo_item_attachments_test.go @@ -0,0 +1,133 @@ +package repo + +import ( + "context" + "testing" + + "github.com/google/uuid" + "github.com/hay-kot/content/backend/ent" + "github.com/hay-kot/content/backend/ent/attachment" + "github.com/stretchr/testify/assert" +) + +func TestAttachmentRepo_Create(t *testing.T) { + doc := useDocs(t, 1)[0] + item := useItems(t, 1)[0] + + ids := []uuid.UUID{doc.ID, item.ID} + t.Cleanup(func() { + for _, id := range ids { + _ = tRepos.Attachments.Delete(context.Background(), id) + } + }) + + type args struct { + ctx context.Context + itemId uuid.UUID + docId uuid.UUID + typ attachment.Type + } + tests := []struct { + name string + args args + want *ent.Attachment + wantErr bool + }{ + { + name: "create attachment", + args: args{ + ctx: context.Background(), + itemId: item.ID, + docId: doc.ID, + typ: attachment.TypePhoto, + }, + want: &ent.Attachment{ + Type: attachment.TypePhoto, + }, + }, + { + name: "create attachment with invalid item id", + args: args{ + ctx: context.Background(), + itemId: uuid.New(), + docId: doc.ID, + typ: "blarg", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + got, err := tRepos.Attachments.Create(tt.args.ctx, tt.args.itemId, tt.args.docId, tt.args.typ) + if (err != nil) != tt.wantErr { + t.Errorf("AttachmentRepo.Create() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if tt.wantErr { + return + } + + assert.Equal(t, tt.want.Type, got.Type) + + withItems, err := tRepos.Attachments.Get(tt.args.ctx, got.ID) + assert.NoError(t, err) + assert.Equal(t, tt.args.itemId, withItems.Edges.Item.ID) + assert.Equal(t, tt.args.docId, withItems.Edges.Document.ID) + + ids = append(ids, got.ID) + }) + } +} + +func useAttachments(t *testing.T, n int) []*ent.Attachment { + t.Helper() + + doc := useDocs(t, 1)[0] + item := useItems(t, 1)[0] + + ids := make([]uuid.UUID, 0, n) + t.Cleanup(func() { + for _, id := range ids { + _ = tRepos.Attachments.Delete(context.Background(), id) + } + }) + + attachments := make([]*ent.Attachment, n) + for i := 0; i < n; i++ { + attachment, err := tRepos.Attachments.Create(context.Background(), item.ID, doc.ID, attachment.TypePhoto) + assert.NoError(t, err) + attachments[i] = attachment + + ids = append(ids, attachment.ID) + } + + return attachments +} + +func TestAttachmentRepo_Update(t *testing.T) { + entity := useAttachments(t, 1)[0] + + for _, typ := range []attachment.Type{"photo", "manual", "warranty", "attachment"} { + t.Run(string(typ), func(t *testing.T) { + _, err := tRepos.Attachments.Update(context.Background(), entity.ID, typ) + assert.NoError(t, err) + + updated, err := tRepos.Attachments.Get(context.Background(), entity.ID) + assert.NoError(t, err) + assert.Equal(t, typ, updated.Type) + }) + } + +} + +func TestAttachmentRepo_Delete(t *testing.T) { + entity := useAttachments(t, 1)[0] + + err := tRepos.Attachments.Delete(context.Background(), entity.ID) + assert.NoError(t, err) + + _, err = tRepos.Attachments.Get(context.Background(), entity.ID) + assert.Error(t, err) +} diff --git a/backend/internal/repo/repo_items.go b/backend/internal/repo/repo_items.go index 90fc911..a1c90df 100644 --- a/backend/internal/repo/repo_items.go +++ b/backend/internal/repo/repo_items.go @@ -21,6 +21,9 @@ func (e *ItemsRepository) GetOne(ctx context.Context, id uuid.UUID) (*ent.Item, WithLabel(). WithLocation(). WithGroup(). + WithAttachments(func(aq *ent.AttachmentQuery) { + aq.WithDocument() + }). Only(ctx) } diff --git a/backend/internal/repo/repo_items_test.go b/backend/internal/repo/repo_items_test.go index e3fc078..625ef6c 100644 --- a/backend/internal/repo/repo_items_test.go +++ b/backend/internal/repo/repo_items_test.go @@ -17,7 +17,7 @@ func itemFactory() types.ItemCreate { } } -func useItems(t *testing.T, len int) ([]*ent.Item, func()) { +func useItems(t *testing.T, len int) []*ent.Item { t.Helper() location, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory()) @@ -33,17 +33,17 @@ func useItems(t *testing.T, len int) ([]*ent.Item, func()) { items[i] = item } - return items, func() { + t.Cleanup(func() { for _, item := range items { - err := tRepos.Items.Delete(context.Background(), item.ID) - assert.NoError(t, err) + _ = tRepos.Items.Delete(context.Background(), item.ID) } - } + }) + + return items } func TestItemsRepository_GetOne(t *testing.T) { - entity, cleanup := useItems(t, 3) - defer cleanup() + entity := useItems(t, 3) for _, item := range entity { result, err := tRepos.Items.GetOne(context.Background(), item.ID) @@ -54,8 +54,7 @@ func TestItemsRepository_GetOne(t *testing.T) { func TestItemsRepository_GetAll(t *testing.T) { length := 10 - expected, cleanup := useItems(t, length) - defer cleanup() + expected := useItems(t, length) results, err := tRepos.Items.GetAll(context.Background(), tGroup.ID) assert.NoError(t, err) @@ -119,7 +118,7 @@ func TestItemsRepository_Create_Location(t *testing.T) { } func TestItemsRepository_Delete(t *testing.T) { - entities, _ := useItems(t, 3) + entities := useItems(t, 3) for _, item := range entities { err := tRepos.Items.Delete(context.Background(), item.ID) @@ -132,8 +131,7 @@ func TestItemsRepository_Delete(t *testing.T) { } func TestItemsRepository_Update(t *testing.T) { - entities, cleanup := useItems(t, 3) - defer cleanup() + entities := useItems(t, 3) entity := entities[0] diff --git a/backend/internal/repo/repos_all.go b/backend/internal/repo/repos_all.go index d4aa65e..e89fe33 100644 --- a/backend/internal/repo/repos_all.go +++ b/backend/internal/repo/repos_all.go @@ -4,25 +4,27 @@ import "github.com/hay-kot/content/backend/ent" // AllRepos is a container for all the repository interfaces type AllRepos struct { - Users *UserRepository - AuthTokens *TokenRepository - Groups *GroupRepository - Locations *LocationRepository - Labels *LabelRepository - Items *ItemsRepository - Docs *DocumentRepository - DocTokens *DocumentTokensRepository + Users *UserRepository + AuthTokens *TokenRepository + Groups *GroupRepository + Locations *LocationRepository + Labels *LabelRepository + Items *ItemsRepository + Docs *DocumentRepository + DocTokens *DocumentTokensRepository + Attachments *AttachmentRepo } func EntAllRepos(db *ent.Client) *AllRepos { return &AllRepos{ - Users: &UserRepository{db}, - AuthTokens: &TokenRepository{db}, - Groups: &GroupRepository{db}, - Locations: &LocationRepository{db}, - Labels: &LabelRepository{db}, - Items: &ItemsRepository{db}, - Docs: &DocumentRepository{db}, - DocTokens: &DocumentTokensRepository{db}, + Users: &UserRepository{db}, + AuthTokens: &TokenRepository{db}, + Groups: &GroupRepository{db}, + Locations: &LocationRepository{db}, + Labels: &LabelRepository{db}, + Items: &ItemsRepository{db}, + Docs: &DocumentRepository{db}, + DocTokens: &DocumentTokensRepository{db}, + Attachments: &AttachmentRepo{db}, } } diff --git a/backend/internal/types/document_types.go b/backend/internal/types/document_types.go index cc903aa..f867504 100644 --- a/backend/internal/types/document_types.go +++ b/backend/internal/types/document_types.go @@ -6,16 +6,17 @@ import ( "github.com/google/uuid" ) +type DocumentOut struct { + ID uuid.UUID `json:"id"` + Title string `json:"title"` +} + type DocumentCreate struct { Title string `json:"name"` Path string `json:"path"` } -type DocumentUpdate struct { - ID uuid.UUID `json:"id"` - Title string `json:"name"` - Path string `json:"path"` -} +type DocumentUpdate = DocumentCreate type DocumentToken struct { Raw string `json:"raw"` diff --git a/backend/internal/types/item_types.go b/backend/internal/types/item_types.go index 38ca8d7..cf2f2be 100644 --- a/backend/internal/types/item_types.go +++ b/backend/internal/types/item_types.go @@ -88,6 +88,14 @@ type ItemSummary struct { type ItemOut struct { ItemSummary + Attachments []*ItemAttachment `json:"attachments"` // Future // Fields []*FieldSummary `json:"fields"` } + +type ItemAttachment struct { + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + Document DocumentOut `json:"document"` +}