feat: Notifiers CRUD (#337)

* introduce scaffold for new models

* wip: shoutrrr wrapper (may remove)

* update schema files

* gen: ent code

* gen: migrations

* go mod tidy

* add group_id to notifier

* db migration

* new mapper helpers

* notifier repo

* introduce experimental adapter pattern for hdlrs

* refactor adapters to fit more common use cases

* new routes for notifiers

* update errors to fix validation panic

* go tidy

* reverse checkbox label display

* wip: notifiers UI

* use badges instead of text

* improve documentation

* add scaffold schema reference

* remove notifier service

* refactor schema folder

* support group edges via scaffold

* delete test file

* include link to API docs

* audit and update documentation + improve format

* refactor schema edges

* refactor

* add custom validator

* set validate + order fields by name

* fix failing tests
This commit is contained in:
Hayden 2023-03-06 21:18:58 -09:00 committed by GitHub
parent 2665b666f1
commit 23b5892aef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
100 changed files with 11437 additions and 2075 deletions

View file

@ -0,0 +1,33 @@
---
# yaml-language-server: $schema=https://hay-kot.github.io/scaffold/schema.json
messages:
pre: |
# Ent Model Generation
With Boilerplate!
post: |
Complete!
questions:
- name: "model"
prompt:
message: "What is the name of the model? (PascalCase)"
required: true
- name: "by_group"
prompt:
confirm: "Include a Group Edge? (group_id -> id)"
required: true
rewrites:
- from: 'templates/model.go'
to: 'backend/internal/data/ent/schema/{{ lower .Scaffold.model }}.go'
inject:
- name: "Insert Groups Edge"
path: 'backend/internal/data/ent/schema/group.go'
at: // $scaffold_edge
template: |
{{- if .Scaffold.by_group -}}
owned("{{ lower .Scaffold.model }}s", {{ .Scaffold.model }}.Type),
{{- end -}}

View file

@ -0,0 +1,40 @@
package schema
import (
"entgo.io/ent"
"github.com/hay-kot/homebox/backend/internal/data/ent/schema/mixins"
)
type {{ .Scaffold.model }} struct {
ent.Schema
}
func ({{ .Scaffold.model }}) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.BaseMixin{},
{{- if .Scaffold.by_group }}
GroupMixin{ref: "{{ snakecase .Scaffold.model }}s"},
{{- end }}
}
}
// Fields of the {{ .Scaffold.model }}.
func ({{ .Scaffold.model }}) Fields() []ent.Field {
return []ent.Field{
// field.String("name").
}
}
// Edges of the {{ .Scaffold.model }}.
func ({{ .Scaffold.model }}) Edges() []ent.Edge {
return []ent.Edge{
// edge.From("group", Group.Type).
}
}
func ({{ .Scaffold.model }}) Indexes() []ent.Index {
return []ent.Index{
// index.Fields("token"),
}
}

View file

@ -28,6 +28,7 @@ tasks:
--path ./backend/app/api/static/docs/swagger.json \
--output ./frontend/lib/api/types
- go run ./scripts/process-types/*.go ./frontend/lib/api/types/data-contracts.ts
- cp ./backend/app/api/static/docs/swagger.json docs/docs/api/openapi-2.0.json
sources:
- "./backend/app/api/**/*"
- "./backend/internal/data/**"

View file

@ -75,17 +75,18 @@ func NewControllerV1(svc *services.AllServices, repos *repo.AllRepos, options ..
}
// HandleBase godoc
// @Summary Retrieves the basic information about the API
// @Tags Base
// @Produce json
// @Success 200 {object} ApiSummary
// @Router /v1/status [GET]
//
// @Summary Application Info
// @Tags Base
// @Produce json
// @Success 200 {object} ApiSummary
// @Router /v1/status [GET]
func (ctrl *V1Controller) HandleBase(ready ReadyFunc, build Build) server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
return server.Respond(w, http.StatusOK, ApiSummary{
Healthy: ready(),
Title: "Go API Template",
Message: "Welcome to the Go API Template Application!",
Title: "Homebox",
Message: "Track, Manage, and Organize your shit",
Build: build,
Demo: ctrl.isDemo,
AllowRegistration: ctrl.allowRegistration,

View file

@ -21,7 +21,7 @@ func (ctrl *V1Controller) routeID(r *http.Request) (uuid.UUID, error) {
func (ctrl *V1Controller) routeUUID(r *http.Request, key string) (uuid.UUID, error) {
ID, err := uuid.Parse(chi.URLParam(r, key))
if err != nil {
return uuid.Nil, validate.NewInvalidRouteKeyError(key)
return uuid.Nil, validate.NewRouteKeyError(key)
}
return ID, nil
}

View file

@ -29,35 +29,41 @@ func actionHandlerFactory(ref string, fn func(context.Context, uuid.UUID) (int,
}
}
// HandleGroupInvitationsCreate godoc
// @Summary Ensures all items in the database have an asset id
// @Tags Group
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-asset-ids [Post]
// @Security Bearer
// HandleEnsureAssetID godoc
//
// @Summary Ensure Asset IDs
// @Description Ensures all items in the database have an asset ID
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-asset-ids [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleEnsureAssetID() server.HandlerFunc {
return actionHandlerFactory("ensure asset IDs", ctrl.svc.Items.EnsureAssetID)
}
// HandleEnsureImportRefs godoc
// @Summary Ensures all items in the database have an import ref
// @Tags Group
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-import-refs [Post]
// @Security Bearer
//
// @Summary Ensures Import Refs
// @Description Ensures all items in the database have an import ref
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-import-refs [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleEnsureImportRefs() server.HandlerFunc {
return actionHandlerFactory("ensure import refs", ctrl.svc.Items.EnsureImportRef)
}
// HandleItemDateZeroOut godoc
// @Summary Resets all item date fields to the beginning of the day
// @Tags Group
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/zero-item-time-fields [Post]
// @Security Bearer
//
// @Summary Zero Out Time Fields
// @Description Resets all item date fields to the beginning of the day
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/zero-item-time-fields [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleItemDateZeroOut() server.HandlerFunc {
return actionHandlerFactory("zero out date time", ctrl.repo.Items.ZeroOutTimeFields)
}

View file

@ -14,14 +14,15 @@ import (
"github.com/rs/zerolog/log"
)
// HandleItemGet godocs
// @Summary Gets an item by Asset ID
// @Tags Assets
// @Produce json
// @Param id path string true "Asset ID"
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/assets/{id} [GET]
// @Security Bearer
// HandleAssetGet godocs
//
// @Summary Get Item by Asset ID
// @Tags Items
// @Produce json
// @Param id path string true "Asset ID"
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/assets/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleAssetGet() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())

View file

@ -26,15 +26,16 @@ type (
)
// HandleAuthLogin godoc
// @Summary User Login
// @Tags Authentication
// @Accept x-www-form-urlencoded
// @Accept application/json
// @Param username formData string false "string" example(admin@admin.com)
// @Param password formData string false "string" example(admin)
// @Produce json
// @Success 200 {object} TokenResponse
// @Router /v1/users/login [POST]
//
// @Summary User Login
// @Tags Authentication
// @Accept x-www-form-urlencoded
// @Accept application/json
// @Param username formData string false "string" example(admin@admin.com)
// @Param password formData string false "string" example(admin)
// @Produce json
// @Success 200 {object} TokenResponse
// @Router /v1/users/login [POST]
func (ctrl *V1Controller) HandleAuthLogin() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
loginForm := &LoginForm{}
@ -84,11 +85,12 @@ func (ctrl *V1Controller) HandleAuthLogin() server.HandlerFunc {
}
// HandleAuthLogout godoc
// @Summary User Logout
// @Tags Authentication
// @Success 204
// @Router /v1/users/logout [POST]
// @Security Bearer
//
// @Summary User Logout
// @Tags Authentication
// @Success 204
// @Router /v1/users/logout [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleAuthLogout() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
token := services.UseTokenCtx(r.Context())
@ -106,13 +108,14 @@ func (ctrl *V1Controller) HandleAuthLogout() server.HandlerFunc {
}
// HandleAuthLogout godoc
// @Summary User Token Refresh
// @Description handleAuthRefresh returns a handler that will issue a new token from an existing token.
// @Description This does not validate that the user still exists within the database.
// @Tags Authentication
// @Success 200
// @Router /v1/users/refresh [GET]
// @Security Bearer
//
// @Summary User Token Refresh
// @Description handleAuthRefresh returns a handler that will issue a new token from an existing token.
// @Description This does not validate that the user still exists within the database.
// @Tags Authentication
// @Success 200
// @Router /v1/users/refresh [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleAuthRefresh() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
requestToken := services.UseTokenCtx(r.Context())

View file

@ -25,24 +25,26 @@ type (
)
// HandleGroupGet godoc
// @Summary Get the current user's group
// @Tags Group
// @Produce json
// @Success 200 {object} repo.Group
// @Router /v1/groups [Get]
// @Security Bearer
//
// @Summary Get Group
// @Tags Group
// @Produce json
// @Success 200 {object} repo.Group
// @Router /v1/groups [Get]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupGet() server.HandlerFunc {
return ctrl.handleGroupGeneral()
}
// HandleGroupUpdate godoc
// @Summary Updates some fields of the current users group
// @Tags Group
// @Produce json
// @Param payload body repo.GroupUpdate true "User Data"
// @Success 200 {object} repo.Group
// @Router /v1/groups [Put]
// @Security Bearer
//
// @Summary Update Group
// @Tags Group
// @Produce json
// @Param payload body repo.GroupUpdate true "User Data"
// @Success 200 {object} repo.Group
// @Router /v1/groups [Put]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupUpdate() server.HandlerFunc {
return ctrl.handleGroupGeneral()
}
@ -81,13 +83,14 @@ func (ctrl *V1Controller) handleGroupGeneral() server.HandlerFunc {
}
// HandleGroupInvitationsCreate godoc
// @Summary Get the current user
// @Tags Group
// @Produce json
// @Param payload body GroupInvitationCreate true "User Data"
// @Success 200 {object} GroupInvitation
// @Router /v1/groups/invitations [Post]
// @Security Bearer
//
// @Summary Create Group Invitation
// @Tags Group
// @Produce json
// @Param payload body GroupInvitationCreate true "User Data"
// @Success 200 {object} GroupInvitation
// @Router /v1/groups/invitations [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupInvitationsCreate() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
data := GroupInvitationCreate{}

View file

@ -15,17 +15,18 @@ import (
)
// HandleItemsGetAll godoc
// @Summary Get All Items
// @Tags Items
// @Produce json
// @Param q query string false "search string"
// @Param page query int false "page number"
// @Param pageSize query int false "items per page"
// @Param labels query []string false "label Ids" collectionFormat(multi)
// @Param locations query []string false "location Ids" collectionFormat(multi)
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/items [GET]
// @Security Bearer
//
// @Summary Query All Items
// @Tags Items
// @Produce json
// @Param q query string false "search string"
// @Param page query int false "page number"
// @Param pageSize query int false "items per page"
// @Param labels query []string false "label Ids" collectionFormat(multi)
// @Param locations query []string false "location Ids" collectionFormat(multi)
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/items [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsGetAll() server.HandlerFunc {
extractQuery := func(r *http.Request) repo.ItemQuery {
params := r.URL.Query()
@ -87,13 +88,14 @@ func (ctrl *V1Controller) HandleItemsGetAll() server.HandlerFunc {
}
// HandleItemsCreate godoc
// @Summary Create a new item
// @Tags Items
// @Produce json
// @Param payload body repo.ItemCreate true "Item Data"
// @Success 200 {object} repo.ItemSummary
// @Router /v1/items [POST]
// @Security Bearer
//
// @Summary Create Item
// @Tags Items
// @Produce json
// @Param payload body repo.ItemCreate true "Item Data"
// @Success 200 {object} repo.ItemSummary
// @Router /v1/items [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsCreate() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
createData := repo.ItemCreate{}
@ -114,38 +116,41 @@ func (ctrl *V1Controller) HandleItemsCreate() server.HandlerFunc {
}
// HandleItemGet godocs
// @Summary Gets a item and fields
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [GET]
// @Security Bearer
//
// @Summary Get Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemGet() server.HandlerFunc {
return ctrl.handleItemsGeneral()
}
// HandleItemDelete godocs
// @Summary deletes a item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 204
// @Router /v1/items/{id} [DELETE]
// @Security Bearer
//
// @Summary Delete Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 204
// @Router /v1/items/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleItemDelete() server.HandlerFunc {
return ctrl.handleItemsGeneral()
}
// HandleItemUpdate godocs
// @Summary updates a item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Param payload body repo.ItemUpdate true "Item Data"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [PUT]
// @Security Bearer
//
// @Summary Update Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Param payload body repo.ItemUpdate true "Item Data"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleItemUpdate() server.HandlerFunc {
return ctrl.handleItemsGeneral()
}
@ -193,13 +198,14 @@ func (ctrl *V1Controller) handleItemsGeneral() server.HandlerFunc {
}
// HandleGetAllCustomFieldNames godocs
// @Summary imports items into the database
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields [GET]
// @Success 200 {object} []string
// @Security Bearer
//
// @Summary Get All Custom Field Names
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields [GET]
// @Success 200 {object} []string
// @Security Bearer
func (ctrl *V1Controller) HandleGetAllCustomFieldNames() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())
@ -214,13 +220,14 @@ func (ctrl *V1Controller) HandleGetAllCustomFieldNames() server.HandlerFunc {
}
// HandleGetAllCustomFieldValues godocs
// @Summary imports items into the database
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields/values [GET]
// @Success 200 {object} []string
// @Security Bearer
//
// @Summary Get All Custom Field Values
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields/values [GET]
// @Success 200 {object} []string
// @Security Bearer
func (ctrl *V1Controller) HandleGetAllCustomFieldValues() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())
@ -235,13 +242,14 @@ func (ctrl *V1Controller) HandleGetAllCustomFieldValues() server.HandlerFunc {
}
// HandleItemsImport godocs
// @Summary imports items into the database
// @Tags Items
// @Produce json
// @Success 204
// @Param csv formData file true "Image to upload"
// @Router /v1/items/import [Post]
// @Security Bearer
//
// @Summary Import Items
// @Tags Items
// @Produce json
// @Success 204
// @Param csv formData file true "Image to upload"
// @Router /v1/items/import [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsImport() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
err := r.ParseMultipartForm(ctrl.maxUploadSize << 20)
@ -268,12 +276,13 @@ func (ctrl *V1Controller) HandleItemsImport() server.HandlerFunc {
}
}
// HandleItemsImport godocs
// @Summary exports items into the database
// @Tags Items
// @Success 200 {string} string "text/csv"
// @Router /v1/items/export [GET]
// @Security Bearer
// HandleItemsExport godocs
//
// @Summary Export Items
// @Tags Items
// @Success 200 {string} string "text/csv"
// @Router /v1/items/export [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsExport() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())

View file

@ -18,18 +18,19 @@ type (
}
)
// HandleItemsImport godocs
// @Summary imports items into the database
// @Tags Items Attachments
// @Produce json
// @Param id path string true "Item ID"
// @Param file formData file true "File attachment"
// @Param type formData string true "Type of file"
// @Param name formData string true "name of the file including extension"
// @Success 200 {object} repo.ItemOut
// @Failure 422 {object} server.ErrorResponse
// @Router /v1/items/{id}/attachments [POST]
// @Security Bearer
// HandleItemAttachmentCreate godocs
//
// @Summary Create Item Attachment
// @Tags Items Attachments
// @Produce json
// @Param id path string true "Item ID"
// @Param file formData file true "File attachment"
// @Param type formData string true "Type of file"
// @Param name formData string true "name of the file including extension"
// @Success 200 {object} repo.ItemOut
// @Failure 422 {object} server.ErrorResponse
// @Router /v1/items/{id}/attachments [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentCreate() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
err := r.ParseMultipartForm(ctrl.maxUploadSize << 20)
@ -92,39 +93,42 @@ func (ctrl *V1Controller) HandleItemAttachmentCreate() server.HandlerFunc {
}
// HandleItemAttachmentGet godocs
// @Summary retrieves an attachment for an item
// @Tags Items Attachments
// @Produce application/octet-stream
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 200 {object} ItemAttachmentToken
// @Router /v1/items/{id}/attachments/{attachment_id} [GET]
// @Security Bearer
//
// @Summary Get Item Attachment
// @Tags Items Attachments
// @Produce application/octet-stream
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 200 {object} ItemAttachmentToken
// @Router /v1/items/{id}/attachments/{attachment_id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentGet() server.HandlerFunc {
return ctrl.handleItemAttachmentsHandler
}
// HandleItemAttachmentDelete godocs
// @Summary retrieves an attachment for an item
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 204
// @Router /v1/items/{id}/attachments/{attachment_id} [DELETE]
// @Security Bearer
//
// @Summary Delete Item Attachment
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 204
// @Router /v1/items/{id}/attachments/{attachment_id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentDelete() server.HandlerFunc {
return ctrl.handleItemAttachmentsHandler
}
// HandleItemAttachmentUpdate godocs
// @Summary retrieves an attachment for an item
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Param payload body repo.ItemAttachmentUpdate true "Attachment Update"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id}/attachments/{attachment_id} [PUT]
// @Security Bearer
//
// @Summary Update Item Attachment
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Param payload body repo.ItemAttachmentUpdate true "Attachment Update"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id}/attachments/{attachment_id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentUpdate() server.HandlerFunc {
return ctrl.handleItemAttachmentsHandler
}

View file

@ -12,12 +12,13 @@ import (
)
// HandleLabelsGetAll godoc
// @Summary Get All Labels
// @Tags Labels
// @Produce json
// @Success 200 {object} server.Results{items=[]repo.LabelOut}
// @Router /v1/labels [GET]
// @Security Bearer
//
// @Summary Get All Labels
// @Tags Labels
// @Produce json
// @Success 200 {object} server.Results{items=[]repo.LabelOut}
// @Router /v1/labels [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelsGetAll() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
user := services.UseUserCtx(r.Context())
@ -31,13 +32,14 @@ func (ctrl *V1Controller) HandleLabelsGetAll() server.HandlerFunc {
}
// HandleLabelsCreate godoc
// @Summary Create a new label
// @Tags Labels
// @Produce json
// @Param payload body repo.LabelCreate true "Label Data"
// @Success 200 {object} repo.LabelSummary
// @Router /v1/labels [POST]
// @Security Bearer
//
// @Summary Create Label
// @Tags Labels
// @Produce json
// @Param payload body repo.LabelCreate true "Label Data"
// @Success 200 {object} repo.LabelSummary
// @Router /v1/labels [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelsCreate() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
createData := repo.LabelCreate{}
@ -58,37 +60,40 @@ func (ctrl *V1Controller) HandleLabelsCreate() server.HandlerFunc {
}
// HandleLabelDelete godocs
// @Summary deletes a label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 204
// @Router /v1/labels/{id} [DELETE]
// @Security Bearer
//
// @Summary Delete Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 204
// @Router /v1/labels/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelDelete() server.HandlerFunc {
return ctrl.handleLabelsGeneral()
}
// HandleLabelGet godocs
// @Summary Gets a label and fields
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [GET]
// @Security Bearer
//
// @Summary Get Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelGet() server.HandlerFunc {
return ctrl.handleLabelsGeneral()
}
// HandleLabelUpdate godocs
// @Summary updates a label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [PUT]
// @Security Bearer
//
// @Summary Update Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelUpdate() server.HandlerFunc {
return ctrl.handleLabelsGeneral()
}

View file

@ -12,13 +12,14 @@ import (
)
// HandleLocationTreeQuery godoc
// @Summary Get All Locations
// @Tags Locations
// @Produce json
// @Param withItems query bool false "include items in response tree"
// @Success 200 {object} server.Results{items=[]repo.TreeItem}
// @Router /v1/locations/tree [GET]
// @Security Bearer
//
// @Summary Get Locations Tree
// @Tags Locations
// @Produce json
// @Param withItems query bool false "include items in response tree"
// @Success 200 {object} server.Results{items=[]repo.TreeItem}
// @Router /v1/locations/tree [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationTreeQuery() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
user := services.UseUserCtx(r.Context())
@ -44,13 +45,14 @@ func (ctrl *V1Controller) HandleLocationTreeQuery() server.HandlerFunc {
}
// HandleLocationGetAll godoc
// @Summary Get All Locations
// @Tags Locations
// @Produce json
// @Param filterChildren query bool false "Filter locations with parents"
// @Success 200 {object} server.Results{items=[]repo.LocationOutCount}
// @Router /v1/locations [GET]
// @Security Bearer
//
// @Summary Get All Locations
// @Tags Locations
// @Produce json
// @Param filterChildren query bool false "Filter locations with parents"
// @Success 200 {object} server.Results{items=[]repo.LocationOutCount}
// @Router /v1/locations [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationGetAll() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
user := services.UseUserCtx(r.Context())
@ -72,13 +74,14 @@ func (ctrl *V1Controller) HandleLocationGetAll() server.HandlerFunc {
}
// HandleLocationCreate godoc
// @Summary Create a new location
// @Tags Locations
// @Produce json
// @Param payload body repo.LocationCreate true "Location Data"
// @Success 200 {object} repo.LocationSummary
// @Router /v1/locations [POST]
// @Security Bearer
//
// @Summary Create Location
// @Tags Locations
// @Produce json
// @Param payload body repo.LocationCreate true "Location Data"
// @Success 200 {object} repo.LocationSummary
// @Router /v1/locations [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationCreate() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
createData := repo.LocationCreate{}
@ -99,38 +102,41 @@ func (ctrl *V1Controller) HandleLocationCreate() server.HandlerFunc {
}
// HandleLocationDelete godocs
// @Summary deletes a location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 204
// @Router /v1/locations/{id} [DELETE]
// @Security Bearer
//
// @Summary Delete Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 204
// @Router /v1/locations/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationDelete() server.HandlerFunc {
return ctrl.handleLocationGeneral()
}
// HandleLocationGet godocs
// @Summary Gets a location and fields
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [GET]
// @Security Bearer
//
// @Summary Get Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationGet() server.HandlerFunc {
return ctrl.handleLocationGeneral()
}
// HandleLocationUpdate godocs
// @Summary updates a location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Param payload body repo.LocationUpdate true "Location Data"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [PUT]
// @Security Bearer
//
// @Summary Update Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Param payload body repo.LocationUpdate true "Location Data"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationUpdate() server.HandlerFunc {
return ctrl.handleLocationGeneral()
}

View file

@ -12,47 +12,51 @@ import (
)
// HandleMaintenanceGetLog godoc
// @Summary Get Maintenance Log
// @Tags Maintenance
// @Produce json
// @Success 200 {object} repo.MaintenanceLog
// @Router /v1/items/{id}/maintenance [GET]
// @Security Bearer
//
// @Summary Get Maintenance Log
// @Tags Maintenance
// @Produce json
// @Success 200 {object} repo.MaintenanceLog
// @Router /v1/items/{id}/maintenance [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceLogGet() server.HandlerFunc {
return ctrl.handleMaintenanceLog()
}
// HandleMaintenanceEntryCreate godoc
// @Summary Create Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Param payload body repo.MaintenanceEntryCreate true "Entry Data"
// @Success 200 {object} repo.MaintenanceEntry
// @Router /v1/items/{id}/maintenance [POST]
// @Security Bearer
//
// @Summary Create Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Param payload body repo.MaintenanceEntryCreate true "Entry Data"
// @Success 200 {object} repo.MaintenanceEntry
// @Router /v1/items/{id}/maintenance [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceEntryCreate() server.HandlerFunc {
return ctrl.handleMaintenanceLog()
}
// HandleMaintenanceEntryDelete godoc
// @Summary Delete Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Success 204
// @Router /v1/items/{id}/maintenance/{entry_id} [DELETE]
// @Security Bearer
//
// @Summary Delete Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Success 204
// @Router /v1/items/{id}/maintenance/{entry_id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceEntryDelete() server.HandlerFunc {
return ctrl.handleMaintenanceLog()
}
// HandleMaintenanceEntryUpdate godoc
// @Summary Update Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Param payload body repo.MaintenanceEntryUpdate true "Entry Data"
// @Success 200 {object} repo.MaintenanceEntry
// @Router /v1/items/{id}/maintenance/{entry_id} [PUT]
// @Security Bearer
//
// @Summary Update Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Param payload body repo.MaintenanceEntryUpdate true "Entry Data"
// @Success 200 {object} repo.MaintenanceEntry
// @Router /v1/items/{id}/maintenance/{entry_id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceEntryUpdate() server.HandlerFunc {
return ctrl.handleMaintenanceLog()
}

View file

@ -0,0 +1,106 @@
package v1
import (
"context"
"net/http"
"github.com/containrrr/shoutrrr"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/core/services"
"github.com/hay-kot/homebox/backend/internal/data/repo"
"github.com/hay-kot/homebox/backend/internal/web/adapters"
"github.com/hay-kot/homebox/backend/pkgs/server"
)
// HandleGetUserNotifiers godoc
//
// @Summary Get Notifiers
// @Tags Notifiers
// @Produce json
// @Success 200 {object} server.Results{items=[]repo.NotifierOut}
// @Router /v1/notifiers [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGetUserNotifiers() server.HandlerFunc {
fn := func(ctx context.Context, _ struct{}) ([]repo.NotifierOut, error) {
user := services.UseUserCtx(ctx)
return ctrl.repo.Notifiers.GetByUser(ctx, user.ID)
}
return adapters.Query(fn, http.StatusOK)
}
// HandleCreateNotifier godoc
//
// @Summary Create Notifier
// @Tags Notifiers
// @Produce json
// @Param payload body repo.NotifierCreate true "Notifier Data"
// @Success 200 {object} repo.NotifierOut
// @Router /v1/notifiers [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleCreateNotifier() server.HandlerFunc {
fn := func(ctx context.Context, in repo.NotifierCreate) (repo.NotifierOut, error) {
auth := services.NewContext(ctx)
return ctrl.repo.Notifiers.Create(ctx, auth.GID, auth.UID, in)
}
return adapters.Action(fn, http.StatusCreated)
}
// HandleDeleteNotifier godocs
//
// @Summary Delete a Notifier
// @Tags Notifiers
// @Param id path string true "Notifier ID"
// @Success 204
// @Router /v1/notifiers/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleDeleteNotifier() server.HandlerFunc {
fn := func(ctx context.Context, ID uuid.UUID) (any, error) {
auth := services.NewContext(ctx)
return nil, ctrl.repo.Notifiers.Delete(ctx, auth.UID, ID)
}
return adapters.CommandID("id", fn, http.StatusNoContent)
}
// HandleUpdateNotifier godocs
//
// @Summary Update Notifier
// @Tags Notifiers
// @Param id path string true "Notifier ID"
// @Param payload body repo.NotifierUpdate true "Notifier Data"
// @Success 200 {object} repo.NotifierOut
// @Router /v1/notifiers/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleUpdateNotifier() server.HandlerFunc {
fn := func(ctx context.Context, ID uuid.UUID, in repo.NotifierUpdate) (repo.NotifierOut, error) {
auth := services.NewContext(ctx)
return ctrl.repo.Notifiers.Update(ctx, auth.UID, ID, in)
}
return adapters.ActionID("id", fn, http.StatusOK)
}
// HandlerNotifierTest godoc
//
// @Summary Test Notifier
// @Tags Notifiers
// @Produce json
// @Param id path string true "Notifier ID"
// @Param url query string true "URL"
// @Success 204
// @Router /v1/notifiers/test [POST]
// @Security Bearer
func (ctrl *V1Controller) HandlerNotifierTest() server.HandlerFunc {
type body struct {
URL string `json:"url" validate:"required"`
}
fn := func(ctx context.Context, q body) (any, error) {
err := shoutrrr.Send(q.URL, "Test message from Homebox")
return nil, err
}
return adapters.Action(fn, http.StatusOK)
}

View file

@ -19,7 +19,7 @@ var qrcodeLogo []byte
// HandleGenerateQRCode godoc
//
// @Summary Encode data into QRCode
// @Summary Create QR Code
// @Tags Items
// @Produce json
// @Param data query string false "data to be encoded into qrcode"

View file

@ -9,7 +9,7 @@ import (
// HandleBillOfMaterialsExport godoc
//
// @Summary Generates a Bill of Materials CSV
// @Summary Export Bill of Materials
// @Tags Reporting
// @Produce json
// @Success 200 {string} string "text/csv"

View file

@ -10,12 +10,13 @@ import (
)
// HandleGroupGet godoc
// @Summary Get the current user's group statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/locations [GET]
// @Security Bearer
//
// @Summary Get Location Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/locations [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatisticsLocations() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())
@ -29,13 +30,14 @@ func (ctrl *V1Controller) HandleGroupStatisticsLocations() server.HandlerFunc {
}
}
// HandleGroupGet godoc
// @Summary Get the current user's group statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/labels [GET]
// @Security Bearer
// HandleGroupStatisticsLabels godoc
//
// @Summary Get Label Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/labels [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatisticsLabels() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())
@ -49,13 +51,14 @@ func (ctrl *V1Controller) HandleGroupStatisticsLabels() server.HandlerFunc {
}
}
// HandleGroupGet godoc
// @Summary Get the current user's group statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.GroupStatistics
// @Router /v1/groups/statistics [GET]
// @Security Bearer
// HandleGroupStatistics godoc
//
// @Summary Get Group Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.GroupStatistics
// @Router /v1/groups/statistics [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatistics() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())
@ -69,15 +72,16 @@ func (ctrl *V1Controller) HandleGroupStatistics() server.HandlerFunc {
}
}
// HandleGroupGet godoc
// @Summary Queries the changes overtime of the purchase price over time
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.ValueOverTime
// @Param start query string false "start date"
// @Param end query string false "end date"
// @Router /v1/groups/statistics/purchase-price [GET]
// @Security Bearer
// HandleGroupStatisticsPriceOverTime godoc
//
// @Summary Get Purchase Price Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.ValueOverTime
// @Param start query string false "start date"
// @Param end query string false "end date"
// @Router /v1/groups/statistics/purchase-price [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatisticsPriceOverTime() server.HandlerFunc {
parseDate := func(datestr string, defaultDate time.Time) (time.Time, error) {
if datestr == "" {

View file

@ -12,13 +12,14 @@ import (
"github.com/rs/zerolog/log"
)
// HandleUserSelf godoc
// @Summary Get the current user
// @Tags User
// @Produce json
// @Param payload body services.UserRegistration true "User Data"
// @Success 204
// @Router /v1/users/register [Post]
// HandleUserRegistration godoc
//
// @Summary Register New User
// @Tags User
// @Produce json
// @Param payload body services.UserRegistration true "User Data"
// @Success 204
// @Router /v1/users/register [Post]
func (ctrl *V1Controller) HandleUserRegistration() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
regData := services.UserRegistration{}
@ -43,12 +44,13 @@ func (ctrl *V1Controller) HandleUserRegistration() server.HandlerFunc {
}
// HandleUserSelf godoc
// @Summary Get the current user
// @Tags User
// @Produce json
// @Success 200 {object} server.Result{item=repo.UserOut}
// @Router /v1/users/self [GET]
// @Security Bearer
//
// @Summary Get User Self
// @Tags User
// @Produce json
// @Success 200 {object} server.Result{item=repo.UserOut}
// @Router /v1/users/self [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelf() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
token := services.UseTokenCtx(r.Context())
@ -63,13 +65,14 @@ func (ctrl *V1Controller) HandleUserSelf() server.HandlerFunc {
}
// HandleUserSelfUpdate godoc
// @Summary Update the current user
// @Tags User
// @Produce json
// @Param payload body repo.UserUpdate true "User Data"
// @Success 200 {object} server.Result{item=repo.UserUpdate}
// @Router /v1/users/self [PUT]
// @Security Bearer
//
// @Summary Update Account
// @Tags User
// @Produce json
// @Param payload body repo.UserUpdate true "User Data"
// @Success 200 {object} server.Result{item=repo.UserUpdate}
// @Router /v1/users/self [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfUpdate() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
updateData := repo.UserUpdate{}
@ -89,12 +92,13 @@ func (ctrl *V1Controller) HandleUserSelfUpdate() server.HandlerFunc {
}
// HandleUserSelfDelete godoc
// @Summary Deletes the user account
// @Tags User
// @Produce json
// @Success 204
// @Router /v1/users/self [DELETE]
// @Security Bearer
//
// @Summary Delete Account
// @Tags User
// @Produce json
// @Success 204
// @Router /v1/users/self [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfDelete() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
if ctrl.isDemo {
@ -118,12 +122,13 @@ type (
)
// HandleUserSelfChangePassword godoc
// @Summary Updates the users password
// @Tags User
// @Success 204
// @Param payload body ChangePassword true "Password Payload"
// @Router /v1/users/change-password [PUT]
// @Security Bearer
//
// @Summary Change Password
// @Tags User
// @Success 204
// @Param payload body ChangePassword true "Password Payload"
// @Router /v1/users/change-password [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfChangePassword() server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
if ctrl.isDemo {

View file

@ -27,9 +27,9 @@ var (
buildTime = "now"
)
// @title Go API Templates
// @title Homebox API
// @version 1.0
// @description This is a simple Rest API Server Template that implements some basic User and Authentication patterns to help you get started and bootstrap your next project!.
// @description Track, Manage, and Organize your Shit.
// @contact.name Don't
// @license.name MIT
// @BasePath /api

View file

@ -126,6 +126,13 @@ func (a *app) mountRoutes(repos *repo.AllRepos) {
a.server.Get(v1Base("/asset/{id}"), v1Ctrl.HandleAssetGet(), userMW...)
// Notifiers
a.server.Get(v1Base("/notifiers"), v1Ctrl.HandleGetUserNotifiers(), userMW...)
a.server.Post(v1Base("/notifiers"), v1Ctrl.HandleCreateNotifier(), userMW...)
a.server.Put(v1Base("/notifiers/{id}"), v1Ctrl.HandleUpdateNotifier(), userMW...)
a.server.Delete(v1Base("/notifiers/{id}"), v1Ctrl.HandleDeleteNotifier(), userMW...)
a.server.Post(v1Base("/notifiers/test"), v1Ctrl.HandlerNotifierTest(), userMW...)
// Asset-Like endpoints
a.server.Get(
v1Base("/qrcode"),

View file

@ -28,13 +28,14 @@ const docTemplate = `{
"Bearer": []
}
],
"description": "Ensures all items in the database have an asset ID",
"produces": [
"application/json"
],
"tags": [
"Group"
"Actions"
],
"summary": "Ensures all items in the database have an asset id",
"summary": "Ensure Asset IDs",
"responses": {
"200": {
"description": "OK",
@ -52,13 +53,14 @@ const docTemplate = `{
"Bearer": []
}
],
"description": "Ensures all items in the database have an import ref",
"produces": [
"application/json"
],
"tags": [
"Group"
"Actions"
],
"summary": "Ensures all items in the database have an import ref",
"summary": "Ensures Import Refs",
"responses": {
"200": {
"description": "OK",
@ -76,13 +78,14 @@ const docTemplate = `{
"Bearer": []
}
],
"description": "Resets all item date fields to the beginning of the day",
"produces": [
"application/json"
],
"tags": [
"Group"
"Actions"
],
"summary": "Resets all item date fields to the beginning of the day",
"summary": "Zero Out Time Fields",
"responses": {
"200": {
"description": "OK",
@ -104,9 +107,9 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Assets"
"Items"
],
"summary": "Gets an item by Asset ID",
"summary": "Get Item by Asset ID",
"parameters": [
{
"type": "string",
@ -139,7 +142,7 @@ const docTemplate = `{
"tags": [
"Group"
],
"summary": "Get the current user's group",
"summary": "Get Group",
"responses": {
"200": {
"description": "OK",
@ -161,7 +164,7 @@ const docTemplate = `{
"tags": [
"Group"
],
"summary": "Updates some fields of the current users group",
"summary": "Update Group",
"parameters": [
{
"description": "User Data",
@ -196,7 +199,7 @@ const docTemplate = `{
"tags": [
"Group"
],
"summary": "Get the current user",
"summary": "Create Group Invitation",
"parameters": [
{
"description": "User Data",
@ -231,7 +234,7 @@ const docTemplate = `{
"tags": [
"Statistics"
],
"summary": "Get the current user's group statistics",
"summary": "Get Group Statistics",
"responses": {
"200": {
"description": "OK",
@ -255,7 +258,7 @@ const docTemplate = `{
"tags": [
"Statistics"
],
"summary": "Get the current user's group statistics",
"summary": "Get Label Statistics",
"responses": {
"200": {
"description": "OK",
@ -282,7 +285,7 @@ const docTemplate = `{
"tags": [
"Statistics"
],
"summary": "Get the current user's group statistics",
"summary": "Get Location Statistics",
"responses": {
"200": {
"description": "OK",
@ -309,7 +312,7 @@ const docTemplate = `{
"tags": [
"Statistics"
],
"summary": "Queries the changes overtime of the purchase price over time",
"summary": "Get Purchase Price Statistics",
"parameters": [
{
"type": "string",
@ -347,7 +350,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "Get All Items",
"summary": "Query All Items",
"parameters": [
{
"type": "string",
@ -409,7 +412,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "Create a new item",
"summary": "Create Item",
"parameters": [
{
"description": "Item Data",
@ -441,7 +444,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "exports items into the database",
"summary": "Export Items",
"responses": {
"200": {
"description": "text/csv",
@ -465,7 +468,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "imports items into the database",
"summary": "Get All Custom Field Names",
"responses": {
"200": {
"description": "OK",
@ -492,7 +495,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "imports items into the database",
"summary": "Get All Custom Field Values",
"responses": {
"200": {
"description": "OK",
@ -519,7 +522,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "imports items into the database",
"summary": "Import Items",
"parameters": [
{
"type": "file",
@ -549,7 +552,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "Gets a item and fields",
"summary": "Get Item",
"parameters": [
{
"type": "string",
@ -580,7 +583,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "updates a item",
"summary": "Update Item",
"parameters": [
{
"type": "string",
@ -620,7 +623,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "deletes a item",
"summary": "Delete Item",
"parameters": [
{
"type": "string",
@ -650,7 +653,7 @@ const docTemplate = `{
"tags": [
"Items Attachments"
],
"summary": "imports items into the database",
"summary": "Create Item Attachment",
"parameters": [
{
"type": "string",
@ -710,7 +713,7 @@ const docTemplate = `{
"tags": [
"Items Attachments"
],
"summary": "retrieves an attachment for an item",
"summary": "Get Item Attachment",
"parameters": [
{
"type": "string",
@ -745,7 +748,7 @@ const docTemplate = `{
"tags": [
"Items Attachments"
],
"summary": "retrieves an attachment for an item",
"summary": "Update Item Attachment",
"parameters": [
{
"type": "string",
@ -789,7 +792,7 @@ const docTemplate = `{
"tags": [
"Items Attachments"
],
"summary": "retrieves an attachment for an item",
"summary": "Delete Item Attachment",
"parameters": [
{
"type": "string",
@ -974,7 +977,7 @@ const docTemplate = `{
"tags": [
"Labels"
],
"summary": "Create a new label",
"summary": "Create Label",
"parameters": [
{
"description": "Label Data",
@ -1009,7 +1012,7 @@ const docTemplate = `{
"tags": [
"Labels"
],
"summary": "Gets a label and fields",
"summary": "Get Label",
"parameters": [
{
"type": "string",
@ -1040,7 +1043,7 @@ const docTemplate = `{
"tags": [
"Labels"
],
"summary": "updates a label",
"summary": "Update Label",
"parameters": [
{
"type": "string",
@ -1071,7 +1074,7 @@ const docTemplate = `{
"tags": [
"Labels"
],
"summary": "deletes a label",
"summary": "Delete Label",
"parameters": [
{
"type": "string",
@ -1146,7 +1149,7 @@ const docTemplate = `{
"tags": [
"Locations"
],
"summary": "Create a new location",
"summary": "Create Location",
"parameters": [
{
"description": "Location Data",
@ -1181,7 +1184,7 @@ const docTemplate = `{
"tags": [
"Locations"
],
"summary": "Get All Locations",
"summary": "Get Locations Tree",
"parameters": [
{
"type": "boolean",
@ -1228,7 +1231,7 @@ const docTemplate = `{
"tags": [
"Locations"
],
"summary": "Gets a location and fields",
"summary": "Get Location",
"parameters": [
{
"type": "string",
@ -1259,7 +1262,7 @@ const docTemplate = `{
"tags": [
"Locations"
],
"summary": "updates a location",
"summary": "Update Location",
"parameters": [
{
"type": "string",
@ -1299,7 +1302,7 @@ const docTemplate = `{
"tags": [
"Locations"
],
"summary": "deletes a location",
"summary": "Delete Location",
"parameters": [
{
"type": "string",
@ -1316,6 +1319,179 @@ const docTemplate = `{
}
}
},
"/v1/notifiers": {
"get": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Notifiers"
],
"summary": "Get Notifiers",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/server.Results"
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/repo.NotifierOut"
}
}
}
}
]
}
}
}
},
"post": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Notifiers"
],
"summary": "Create Notifier",
"parameters": [
{
"description": "Notifier Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/repo.NotifierCreate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/repo.NotifierOut"
}
}
}
}
},
"/v1/notifiers/test": {
"post": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Notifiers"
],
"summary": "Test Notifier",
"parameters": [
{
"type": "string",
"description": "Notifier ID",
"name": "id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "URL",
"name": "url",
"in": "query",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
}
}
}
},
"/v1/notifiers/{id}": {
"put": {
"security": [
{
"Bearer": []
}
],
"tags": [
"Notifiers"
],
"summary": "Update Notifier",
"parameters": [
{
"type": "string",
"description": "Notifier ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Notifier Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/repo.NotifierUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/repo.NotifierOut"
}
}
}
},
"delete": {
"security": [
{
"Bearer": []
}
],
"tags": [
"Notifiers"
],
"summary": "Delete a Notifier",
"parameters": [
{
"type": "string",
"description": "Notifier ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
}
}
}
},
"/v1/qrcode": {
"get": {
"security": [
@ -1329,7 +1505,7 @@ const docTemplate = `{
"tags": [
"Items"
],
"summary": "Encode data into QRCode",
"summary": "Create QR Code",
"parameters": [
{
"type": "string",
@ -1361,7 +1537,7 @@ const docTemplate = `{
"tags": [
"Reporting"
],
"summary": "Generates a Bill of Materials CSV",
"summary": "Export Bill of Materials",
"responses": {
"200": {
"description": "text/csv",
@ -1380,7 +1556,7 @@ const docTemplate = `{
"tags": [
"Base"
],
"summary": "Retrieves the basic information about the API",
"summary": "Application Info",
"responses": {
"200": {
"description": "OK",
@ -1401,7 +1577,7 @@ const docTemplate = `{
"tags": [
"User"
],
"summary": "Updates the users password",
"summary": "Change Password",
"parameters": [
{
"description": "Password Payload",
@ -1504,7 +1680,7 @@ const docTemplate = `{
"tags": [
"User"
],
"summary": "Get the current user",
"summary": "Register New User",
"parameters": [
{
"description": "User Data",
@ -1536,7 +1712,7 @@ const docTemplate = `{
"tags": [
"User"
],
"summary": "Get the current user",
"summary": "Get User Self",
"responses": {
"200": {
"description": "OK",
@ -1570,7 +1746,7 @@ const docTemplate = `{
"tags": [
"User"
],
"summary": "Update the current user",
"summary": "Update Account",
"parameters": [
{
"description": "User Data",
@ -1615,7 +1791,7 @@ const docTemplate = `{
"tags": [
"User"
],
"summary": "Deletes the user account",
"summary": "Delete Account",
"responses": {
"204": {
"description": "No Content"
@ -2293,6 +2469,72 @@ const docTemplate = `{
}
}
},
"repo.NotifierCreate": {
"type": "object",
"required": [
"name",
"url"
],
"properties": {
"isActive": {
"type": "boolean"
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"url": {
"type": "string"
}
}
},
"repo.NotifierOut": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"groupId": {
"type": "string"
},
"id": {
"type": "string"
},
"isActive": {
"type": "boolean"
},
"name": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
"userId": {
"type": "string"
}
}
},
"repo.NotifierUpdate": {
"type": "object",
"required": [
"name"
],
"properties": {
"isActive": {
"type": "boolean"
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"url": {
"type": "string",
"x-nullable": true
}
}
},
"repo.PaginationResult-repo_ItemSummary": {
"type": "object",
"properties": {
@ -2597,8 +2839,8 @@ var SwaggerInfo = &swag.Spec{
Host: "",
BasePath: "/api",
Schemes: []string{},
Title: "Go API Templates",
Description: "This is a simple Rest API Server Template that implements some basic User and Authentication patterns to help you get started and bootstrap your next project!.",
Title: "Homebox API",
Description: "Track, Manage, and Organize your Shit.",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
}

View file

@ -1,8 +1,8 @@
{
"swagger": "2.0",
"info": {
"description": "This is a simple Rest API Server Template that implements some basic User and Authentication patterns to help you get started and bootstrap your next project!.",
"title": "Go API Templates",
"description": "Track, Manage, and Organize your Shit.",
"title": "Homebox API",
"contact": {
"name": "Don't"
},
@ -20,13 +20,14 @@
"Bearer": []
}
],
"description": "Ensures all items in the database have an asset ID",
"produces": [
"application/json"
],
"tags": [
"Group"
"Actions"
],
"summary": "Ensures all items in the database have an asset id",
"summary": "Ensure Asset IDs",
"responses": {
"200": {
"description": "OK",
@ -44,13 +45,14 @@
"Bearer": []
}
],
"description": "Ensures all items in the database have an import ref",
"produces": [
"application/json"
],
"tags": [
"Group"
"Actions"
],
"summary": "Ensures all items in the database have an import ref",
"summary": "Ensures Import Refs",
"responses": {
"200": {
"description": "OK",
@ -68,13 +70,14 @@
"Bearer": []
}
],
"description": "Resets all item date fields to the beginning of the day",
"produces": [
"application/json"
],
"tags": [
"Group"
"Actions"
],
"summary": "Resets all item date fields to the beginning of the day",
"summary": "Zero Out Time Fields",
"responses": {
"200": {
"description": "OK",
@ -96,9 +99,9 @@
"application/json"
],
"tags": [
"Assets"
"Items"
],
"summary": "Gets an item by Asset ID",
"summary": "Get Item by Asset ID",
"parameters": [
{
"type": "string",
@ -131,7 +134,7 @@
"tags": [
"Group"
],
"summary": "Get the current user's group",
"summary": "Get Group",
"responses": {
"200": {
"description": "OK",
@ -153,7 +156,7 @@
"tags": [
"Group"
],
"summary": "Updates some fields of the current users group",
"summary": "Update Group",
"parameters": [
{
"description": "User Data",
@ -188,7 +191,7 @@
"tags": [
"Group"
],
"summary": "Get the current user",
"summary": "Create Group Invitation",
"parameters": [
{
"description": "User Data",
@ -223,7 +226,7 @@
"tags": [
"Statistics"
],
"summary": "Get the current user's group statistics",
"summary": "Get Group Statistics",
"responses": {
"200": {
"description": "OK",
@ -247,7 +250,7 @@
"tags": [
"Statistics"
],
"summary": "Get the current user's group statistics",
"summary": "Get Label Statistics",
"responses": {
"200": {
"description": "OK",
@ -274,7 +277,7 @@
"tags": [
"Statistics"
],
"summary": "Get the current user's group statistics",
"summary": "Get Location Statistics",
"responses": {
"200": {
"description": "OK",
@ -301,7 +304,7 @@
"tags": [
"Statistics"
],
"summary": "Queries the changes overtime of the purchase price over time",
"summary": "Get Purchase Price Statistics",
"parameters": [
{
"type": "string",
@ -339,7 +342,7 @@
"tags": [
"Items"
],
"summary": "Get All Items",
"summary": "Query All Items",
"parameters": [
{
"type": "string",
@ -401,7 +404,7 @@
"tags": [
"Items"
],
"summary": "Create a new item",
"summary": "Create Item",
"parameters": [
{
"description": "Item Data",
@ -433,7 +436,7 @@
"tags": [
"Items"
],
"summary": "exports items into the database",
"summary": "Export Items",
"responses": {
"200": {
"description": "text/csv",
@ -457,7 +460,7 @@
"tags": [
"Items"
],
"summary": "imports items into the database",
"summary": "Get All Custom Field Names",
"responses": {
"200": {
"description": "OK",
@ -484,7 +487,7 @@
"tags": [
"Items"
],
"summary": "imports items into the database",
"summary": "Get All Custom Field Values",
"responses": {
"200": {
"description": "OK",
@ -511,7 +514,7 @@
"tags": [
"Items"
],
"summary": "imports items into the database",
"summary": "Import Items",
"parameters": [
{
"type": "file",
@ -541,7 +544,7 @@
"tags": [
"Items"
],
"summary": "Gets a item and fields",
"summary": "Get Item",
"parameters": [
{
"type": "string",
@ -572,7 +575,7 @@
"tags": [
"Items"
],
"summary": "updates a item",
"summary": "Update Item",
"parameters": [
{
"type": "string",
@ -612,7 +615,7 @@
"tags": [
"Items"
],
"summary": "deletes a item",
"summary": "Delete Item",
"parameters": [
{
"type": "string",
@ -642,7 +645,7 @@
"tags": [
"Items Attachments"
],
"summary": "imports items into the database",
"summary": "Create Item Attachment",
"parameters": [
{
"type": "string",
@ -702,7 +705,7 @@
"tags": [
"Items Attachments"
],
"summary": "retrieves an attachment for an item",
"summary": "Get Item Attachment",
"parameters": [
{
"type": "string",
@ -737,7 +740,7 @@
"tags": [
"Items Attachments"
],
"summary": "retrieves an attachment for an item",
"summary": "Update Item Attachment",
"parameters": [
{
"type": "string",
@ -781,7 +784,7 @@
"tags": [
"Items Attachments"
],
"summary": "retrieves an attachment for an item",
"summary": "Delete Item Attachment",
"parameters": [
{
"type": "string",
@ -966,7 +969,7 @@
"tags": [
"Labels"
],
"summary": "Create a new label",
"summary": "Create Label",
"parameters": [
{
"description": "Label Data",
@ -1001,7 +1004,7 @@
"tags": [
"Labels"
],
"summary": "Gets a label and fields",
"summary": "Get Label",
"parameters": [
{
"type": "string",
@ -1032,7 +1035,7 @@
"tags": [
"Labels"
],
"summary": "updates a label",
"summary": "Update Label",
"parameters": [
{
"type": "string",
@ -1063,7 +1066,7 @@
"tags": [
"Labels"
],
"summary": "deletes a label",
"summary": "Delete Label",
"parameters": [
{
"type": "string",
@ -1138,7 +1141,7 @@
"tags": [
"Locations"
],
"summary": "Create a new location",
"summary": "Create Location",
"parameters": [
{
"description": "Location Data",
@ -1173,7 +1176,7 @@
"tags": [
"Locations"
],
"summary": "Get All Locations",
"summary": "Get Locations Tree",
"parameters": [
{
"type": "boolean",
@ -1220,7 +1223,7 @@
"tags": [
"Locations"
],
"summary": "Gets a location and fields",
"summary": "Get Location",
"parameters": [
{
"type": "string",
@ -1251,7 +1254,7 @@
"tags": [
"Locations"
],
"summary": "updates a location",
"summary": "Update Location",
"parameters": [
{
"type": "string",
@ -1291,7 +1294,7 @@
"tags": [
"Locations"
],
"summary": "deletes a location",
"summary": "Delete Location",
"parameters": [
{
"type": "string",
@ -1308,6 +1311,179 @@
}
}
},
"/v1/notifiers": {
"get": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Notifiers"
],
"summary": "Get Notifiers",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/server.Results"
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/repo.NotifierOut"
}
}
}
}
]
}
}
}
},
"post": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Notifiers"
],
"summary": "Create Notifier",
"parameters": [
{
"description": "Notifier Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/repo.NotifierCreate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/repo.NotifierOut"
}
}
}
}
},
"/v1/notifiers/test": {
"post": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Notifiers"
],
"summary": "Test Notifier",
"parameters": [
{
"type": "string",
"description": "Notifier ID",
"name": "id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "URL",
"name": "url",
"in": "query",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
}
}
}
},
"/v1/notifiers/{id}": {
"put": {
"security": [
{
"Bearer": []
}
],
"tags": [
"Notifiers"
],
"summary": "Update Notifier",
"parameters": [
{
"type": "string",
"description": "Notifier ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Notifier Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/repo.NotifierUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/repo.NotifierOut"
}
}
}
},
"delete": {
"security": [
{
"Bearer": []
}
],
"tags": [
"Notifiers"
],
"summary": "Delete a Notifier",
"parameters": [
{
"type": "string",
"description": "Notifier ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
}
}
}
},
"/v1/qrcode": {
"get": {
"security": [
@ -1321,7 +1497,7 @@
"tags": [
"Items"
],
"summary": "Encode data into QRCode",
"summary": "Create QR Code",
"parameters": [
{
"type": "string",
@ -1353,7 +1529,7 @@
"tags": [
"Reporting"
],
"summary": "Generates a Bill of Materials CSV",
"summary": "Export Bill of Materials",
"responses": {
"200": {
"description": "text/csv",
@ -1372,7 +1548,7 @@
"tags": [
"Base"
],
"summary": "Retrieves the basic information about the API",
"summary": "Application Info",
"responses": {
"200": {
"description": "OK",
@ -1393,7 +1569,7 @@
"tags": [
"User"
],
"summary": "Updates the users password",
"summary": "Change Password",
"parameters": [
{
"description": "Password Payload",
@ -1496,7 +1672,7 @@
"tags": [
"User"
],
"summary": "Get the current user",
"summary": "Register New User",
"parameters": [
{
"description": "User Data",
@ -1528,7 +1704,7 @@
"tags": [
"User"
],
"summary": "Get the current user",
"summary": "Get User Self",
"responses": {
"200": {
"description": "OK",
@ -1562,7 +1738,7 @@
"tags": [
"User"
],
"summary": "Update the current user",
"summary": "Update Account",
"parameters": [
{
"description": "User Data",
@ -1607,7 +1783,7 @@
"tags": [
"User"
],
"summary": "Deletes the user account",
"summary": "Delete Account",
"responses": {
"204": {
"description": "No Content"
@ -2285,6 +2461,72 @@
}
}
},
"repo.NotifierCreate": {
"type": "object",
"required": [
"name",
"url"
],
"properties": {
"isActive": {
"type": "boolean"
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"url": {
"type": "string"
}
}
},
"repo.NotifierOut": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"groupId": {
"type": "string"
},
"id": {
"type": "string"
},
"isActive": {
"type": "boolean"
},
"name": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
"userId": {
"type": "string"
}
}
},
"repo.NotifierUpdate": {
"type": "object",
"required": [
"name"
],
"properties": {
"isActive": {
"type": "boolean"
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"url": {
"type": "string",
"x-nullable": true
}
}
},
"repo.PaginationResult-repo_ItemSummary": {
"type": "object",
"properties": {

View file

@ -451,6 +451,51 @@ definitions:
itemId:
type: string
type: object
repo.NotifierCreate:
properties:
isActive:
type: boolean
name:
maxLength: 255
minLength: 1
type: string
url:
type: string
required:
- name
- url
type: object
repo.NotifierOut:
properties:
createdAt:
type: string
groupId:
type: string
id:
type: string
isActive:
type: boolean
name:
type: string
updatedAt:
type: string
userId:
type: string
type: object
repo.NotifierUpdate:
properties:
isActive:
type: boolean
name:
maxLength: 255
minLength: 1
type: string
url:
type: string
x-nullable: true
required:
- name
type: object
repo.PaginationResult-repo_ItemSummary:
properties:
items:
@ -640,16 +685,15 @@ definitions:
info:
contact:
name: Don't
description: This is a simple Rest API Server Template that implements some basic
User and Authentication patterns to help you get started and bootstrap your next
project!.
description: Track, Manage, and Organize your Shit.
license:
name: MIT
title: Go API Templates
title: Homebox API
version: "1.0"
paths:
/v1/actions/ensure-asset-ids:
post:
description: Ensures all items in the database have an asset ID
produces:
- application/json
responses:
@ -659,11 +703,12 @@ paths:
$ref: '#/definitions/v1.ActionAmountResult'
security:
- Bearer: []
summary: Ensures all items in the database have an asset id
summary: Ensure Asset IDs
tags:
- Group
- Actions
/v1/actions/ensure-import-refs:
post:
description: Ensures all items in the database have an import ref
produces:
- application/json
responses:
@ -673,11 +718,12 @@ paths:
$ref: '#/definitions/v1.ActionAmountResult'
security:
- Bearer: []
summary: Ensures all items in the database have an import ref
summary: Ensures Import Refs
tags:
- Group
- Actions
/v1/actions/zero-item-time-fields:
post:
description: Resets all item date fields to the beginning of the day
produces:
- application/json
responses:
@ -687,9 +733,9 @@ paths:
$ref: '#/definitions/v1.ActionAmountResult'
security:
- Bearer: []
summary: Resets all item date fields to the beginning of the day
summary: Zero Out Time Fields
tags:
- Group
- Actions
/v1/assets/{id}:
get:
parameters:
@ -707,9 +753,9 @@ paths:
$ref: '#/definitions/repo.PaginationResult-repo_ItemSummary'
security:
- Bearer: []
summary: Gets an item by Asset ID
summary: Get Item by Asset ID
tags:
- Assets
- Items
/v1/groups:
get:
produces:
@ -721,7 +767,7 @@ paths:
$ref: '#/definitions/repo.Group'
security:
- Bearer: []
summary: Get the current user's group
summary: Get Group
tags:
- Group
put:
@ -741,7 +787,7 @@ paths:
$ref: '#/definitions/repo.Group'
security:
- Bearer: []
summary: Updates some fields of the current users group
summary: Update Group
tags:
- Group
/v1/groups/invitations:
@ -762,7 +808,7 @@ paths:
$ref: '#/definitions/v1.GroupInvitation'
security:
- Bearer: []
summary: Get the current user
summary: Create Group Invitation
tags:
- Group
/v1/groups/statistics:
@ -776,7 +822,7 @@ paths:
$ref: '#/definitions/repo.GroupStatistics'
security:
- Bearer: []
summary: Get the current user's group statistics
summary: Get Group Statistics
tags:
- Statistics
/v1/groups/statistics/labels:
@ -792,7 +838,7 @@ paths:
type: array
security:
- Bearer: []
summary: Get the current user's group statistics
summary: Get Label Statistics
tags:
- Statistics
/v1/groups/statistics/locations:
@ -808,7 +854,7 @@ paths:
type: array
security:
- Bearer: []
summary: Get the current user's group statistics
summary: Get Location Statistics
tags:
- Statistics
/v1/groups/statistics/purchase-price:
@ -831,7 +877,7 @@ paths:
$ref: '#/definitions/repo.ValueOverTime'
security:
- Bearer: []
summary: Queries the changes overtime of the purchase price over time
summary: Get Purchase Price Statistics
tags:
- Statistics
/v1/items:
@ -872,7 +918,7 @@ paths:
$ref: '#/definitions/repo.PaginationResult-repo_ItemSummary'
security:
- Bearer: []
summary: Get All Items
summary: Query All Items
tags:
- Items
post:
@ -892,7 +938,7 @@ paths:
$ref: '#/definitions/repo.ItemSummary'
security:
- Bearer: []
summary: Create a new item
summary: Create Item
tags:
- Items
/v1/items/{id}:
@ -910,7 +956,7 @@ paths:
description: No Content
security:
- Bearer: []
summary: deletes a item
summary: Delete Item
tags:
- Items
get:
@ -929,7 +975,7 @@ paths:
$ref: '#/definitions/repo.ItemOut'
security:
- Bearer: []
summary: Gets a item and fields
summary: Get Item
tags:
- Items
put:
@ -954,7 +1000,7 @@ paths:
$ref: '#/definitions/repo.ItemOut'
security:
- Bearer: []
summary: updates a item
summary: Update Item
tags:
- Items
/v1/items/{id}/attachments:
@ -993,7 +1039,7 @@ paths:
$ref: '#/definitions/server.ErrorResponse'
security:
- Bearer: []
summary: imports items into the database
summary: Create Item Attachment
tags:
- Items Attachments
/v1/items/{id}/attachments/{attachment_id}:
@ -1014,7 +1060,7 @@ paths:
description: No Content
security:
- Bearer: []
summary: retrieves an attachment for an item
summary: Delete Item Attachment
tags:
- Items Attachments
get:
@ -1038,7 +1084,7 @@ paths:
$ref: '#/definitions/v1.ItemAttachmentToken'
security:
- Bearer: []
summary: retrieves an attachment for an item
summary: Get Item Attachment
tags:
- Items Attachments
put:
@ -1066,7 +1112,7 @@ paths:
$ref: '#/definitions/repo.ItemOut'
security:
- Bearer: []
summary: retrieves an attachment for an item
summary: Update Item Attachment
tags:
- Items Attachments
/v1/items/{id}/maintenance:
@ -1144,7 +1190,7 @@ paths:
type: string
security:
- Bearer: []
summary: exports items into the database
summary: Export Items
tags:
- Items
/v1/items/fields:
@ -1160,7 +1206,7 @@ paths:
type: array
security:
- Bearer: []
summary: imports items into the database
summary: Get All Custom Field Names
tags:
- Items
/v1/items/fields/values:
@ -1176,7 +1222,7 @@ paths:
type: array
security:
- Bearer: []
summary: imports items into the database
summary: Get All Custom Field Values
tags:
- Items
/v1/items/import:
@ -1194,7 +1240,7 @@ paths:
description: No Content
security:
- Bearer: []
summary: imports items into the database
summary: Import Items
tags:
- Items
/v1/labels:
@ -1235,7 +1281,7 @@ paths:
$ref: '#/definitions/repo.LabelSummary'
security:
- Bearer: []
summary: Create a new label
summary: Create Label
tags:
- Labels
/v1/labels/{id}:
@ -1253,7 +1299,7 @@ paths:
description: No Content
security:
- Bearer: []
summary: deletes a label
summary: Delete Label
tags:
- Labels
get:
@ -1272,7 +1318,7 @@ paths:
$ref: '#/definitions/repo.LabelOut'
security:
- Bearer: []
summary: Gets a label and fields
summary: Get Label
tags:
- Labels
put:
@ -1291,7 +1337,7 @@ paths:
$ref: '#/definitions/repo.LabelOut'
security:
- Bearer: []
summary: updates a label
summary: Update Label
tags:
- Labels
/v1/locations:
@ -1337,7 +1383,7 @@ paths:
$ref: '#/definitions/repo.LocationSummary'
security:
- Bearer: []
summary: Create a new location
summary: Create Location
tags:
- Locations
/v1/locations/{id}:
@ -1355,7 +1401,7 @@ paths:
description: No Content
security:
- Bearer: []
summary: deletes a location
summary: Delete Location
tags:
- Locations
get:
@ -1374,7 +1420,7 @@ paths:
$ref: '#/definitions/repo.LocationOut'
security:
- Bearer: []
summary: Gets a location and fields
summary: Get Location
tags:
- Locations
put:
@ -1399,7 +1445,7 @@ paths:
$ref: '#/definitions/repo.LocationOut'
security:
- Bearer: []
summary: updates a location
summary: Update Location
tags:
- Locations
/v1/locations/tree:
@ -1425,9 +1471,112 @@ paths:
type: object
security:
- Bearer: []
summary: Get All Locations
summary: Get Locations Tree
tags:
- Locations
/v1/notifiers:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/server.Results'
- properties:
items:
items:
$ref: '#/definitions/repo.NotifierOut'
type: array
type: object
security:
- Bearer: []
summary: Get Notifiers
tags:
- Notifiers
post:
parameters:
- description: Notifier Data
in: body
name: payload
required: true
schema:
$ref: '#/definitions/repo.NotifierCreate'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/repo.NotifierOut'
security:
- Bearer: []
summary: Create Notifier
tags:
- Notifiers
/v1/notifiers/{id}:
delete:
parameters:
- description: Notifier ID
in: path
name: id
required: true
type: string
responses:
"204":
description: No Content
security:
- Bearer: []
summary: Delete a Notifier
tags:
- Notifiers
put:
parameters:
- description: Notifier ID
in: path
name: id
required: true
type: string
- description: Notifier Data
in: body
name: payload
required: true
schema:
$ref: '#/definitions/repo.NotifierUpdate'
responses:
"200":
description: OK
schema:
$ref: '#/definitions/repo.NotifierOut'
security:
- Bearer: []
summary: Update Notifier
tags:
- Notifiers
/v1/notifiers/test:
post:
parameters:
- description: Notifier ID
in: path
name: id
required: true
type: string
- description: URL
in: query
name: url
required: true
type: string
produces:
- application/json
responses:
"204":
description: No Content
security:
- Bearer: []
summary: Test Notifier
tags:
- Notifiers
/v1/qrcode:
get:
parameters:
@ -1444,7 +1593,7 @@ paths:
type: string
security:
- Bearer: []
summary: Encode data into QRCode
summary: Create QR Code
tags:
- Items
/v1/reporting/bill-of-materials:
@ -1458,7 +1607,7 @@ paths:
type: string
security:
- Bearer: []
summary: Generates a Bill of Materials CSV
summary: Export Bill of Materials
tags:
- Reporting
/v1/status:
@ -1470,7 +1619,7 @@ paths:
description: OK
schema:
$ref: '#/definitions/v1.ApiSummary'
summary: Retrieves the basic information about the API
summary: Application Info
tags:
- Base
/v1/users/change-password:
@ -1487,7 +1636,7 @@ paths:
description: No Content
security:
- Bearer: []
summary: Updates the users password
summary: Change Password
tags:
- User
/v1/users/login:
@ -1553,7 +1702,7 @@ paths:
responses:
"204":
description: No Content
summary: Get the current user
summary: Register New User
tags:
- User
/v1/users/self:
@ -1565,7 +1714,7 @@ paths:
description: No Content
security:
- Bearer: []
summary: Deletes the user account
summary: Delete Account
tags:
- User
get:
@ -1583,7 +1732,7 @@ paths:
type: object
security:
- Bearer: []
summary: Get the current user
summary: Get User Self
tags:
- User
put:
@ -1608,7 +1757,7 @@ paths:
type: object
security:
- Bearer: []
summary: Update the current user
summary: Update Account
tags:
- User
securityDefinitions:

View file

@ -6,10 +6,12 @@ require (
ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb
entgo.io/ent v0.11.8
github.com/ardanlabs/conf/v3 v3.1.4
github.com/containrrr/shoutrrr v0.7.1
github.com/go-chi/chi/v5 v5.0.8
github.com/go-playground/validator/v10 v10.11.2
github.com/gocarina/gocsv v0.0.0-20230226133904-70c27cb2918a
github.com/google/uuid v1.3.0
github.com/gorilla/schema v1.2.0
github.com/mattn/go-sqlite3 v1.14.16
github.com/rs/zerolog v1.29.0
github.com/stretchr/testify v1.8.2
@ -25,6 +27,7 @@ require (
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fogleman/gg v1.3.0 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/ent/label"
"github.com/hay-kot/homebox/backend/internal/data/ent/location"
"github.com/hay-kot/homebox/backend/internal/data/ent/maintenanceentry"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
"entgo.io/ent/dialect"
@ -56,6 +57,8 @@ type Client struct {
Location *LocationClient
// MaintenanceEntry is the client for interacting with the MaintenanceEntry builders.
MaintenanceEntry *MaintenanceEntryClient
// Notifier is the client for interacting with the Notifier builders.
Notifier *NotifierClient
// User is the client for interacting with the User builders.
User *UserClient
}
@ -82,6 +85,7 @@ func (c *Client) init() {
c.Label = NewLabelClient(c.config)
c.Location = NewLocationClient(c.config)
c.MaintenanceEntry = NewMaintenanceEntryClient(c.config)
c.Notifier = NewNotifierClient(c.config)
c.User = NewUserClient(c.config)
}
@ -127,6 +131,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
Label: NewLabelClient(cfg),
Location: NewLocationClient(cfg),
MaintenanceEntry: NewMaintenanceEntryClient(cfg),
Notifier: NewNotifierClient(cfg),
User: NewUserClient(cfg),
}, nil
}
@ -158,6 +163,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
Label: NewLabelClient(cfg),
Location: NewLocationClient(cfg),
MaintenanceEntry: NewMaintenanceEntryClient(cfg),
Notifier: NewNotifierClient(cfg),
User: NewUserClient(cfg),
}, nil
}
@ -198,6 +204,7 @@ func (c *Client) Use(hooks ...Hook) {
c.Label.Use(hooks...)
c.Location.Use(hooks...)
c.MaintenanceEntry.Use(hooks...)
c.Notifier.Use(hooks...)
c.User.Use(hooks...)
}
@ -215,6 +222,7 @@ func (c *Client) Intercept(interceptors ...Interceptor) {
c.Label.Intercept(interceptors...)
c.Location.Intercept(interceptors...)
c.MaintenanceEntry.Intercept(interceptors...)
c.Notifier.Intercept(interceptors...)
c.User.Intercept(interceptors...)
}
@ -243,6 +251,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
return c.Location.mutate(ctx, m)
case *MaintenanceEntryMutation:
return c.MaintenanceEntry.mutate(ctx, m)
case *NotifierMutation:
return c.Notifier.mutate(ctx, m)
case *UserMutation:
return c.User.mutate(ctx, m)
default:
@ -1023,6 +1033,22 @@ func (c *GroupClient) QueryInvitationTokens(gr *Group) *GroupInvitationTokenQuer
return query
}
// QueryNotifiers queries the notifiers edge of a Group.
func (c *GroupClient) QueryNotifiers(gr *Group) *NotifierQuery {
query := (&NotifierClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := gr.ID
step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, id),
sqlgraph.To(notifier.Table, notifier.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, group.NotifiersTable, group.NotifiersColumn),
)
fromV = sqlgraph.Neighbors(gr.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *GroupClient) Hooks() []Hook {
return c.hooks.Group
@ -1275,6 +1301,22 @@ func (c *ItemClient) GetX(ctx context.Context, id uuid.UUID) *Item {
return obj
}
// QueryGroup queries the group edge of a Item.
func (c *ItemClient) QueryGroup(i *Item) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := i.ID
step := sqlgraph.NewStep(
sqlgraph.From(item.Table, item.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, item.GroupTable, item.GroupColumn),
)
fromV = sqlgraph.Neighbors(i.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryParent queries the parent edge of a Item.
func (c *ItemClient) QueryParent(i *Item) *ItemQuery {
query := (&ItemClient{config: c.config}).Query()
@ -1307,22 +1349,6 @@ func (c *ItemClient) QueryChildren(i *Item) *ItemQuery {
return query
}
// QueryGroup queries the group edge of a Item.
func (c *ItemClient) QueryGroup(i *Item) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := i.ID
step := sqlgraph.NewStep(
sqlgraph.From(item.Table, item.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, item.GroupTable, item.GroupColumn),
)
fromV = sqlgraph.Neighbors(i.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryLabel queries the label edge of a Item.
func (c *ItemClient) QueryLabel(i *Item) *LabelQuery {
query := (&LabelClient{config: c.config}).Query()
@ -1805,6 +1831,22 @@ func (c *LocationClient) GetX(ctx context.Context, id uuid.UUID) *Location {
return obj
}
// QueryGroup queries the group edge of a Location.
func (c *LocationClient) QueryGroup(l *Location) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := l.ID
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, location.GroupTable, location.GroupColumn),
)
fromV = sqlgraph.Neighbors(l.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryParent queries the parent edge of a Location.
func (c *LocationClient) QueryParent(l *Location) *LocationQuery {
query := (&LocationClient{config: c.config}).Query()
@ -1837,22 +1879,6 @@ func (c *LocationClient) QueryChildren(l *Location) *LocationQuery {
return query
}
// QueryGroup queries the group edge of a Location.
func (c *LocationClient) QueryGroup(l *Location) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := l.ID
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, location.GroupTable, location.GroupColumn),
)
fromV = sqlgraph.Neighbors(l.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryItems queries the items edge of a Location.
func (c *LocationClient) QueryItems(l *Location) *ItemQuery {
query := (&ItemClient{config: c.config}).Query()
@ -2028,6 +2054,156 @@ func (c *MaintenanceEntryClient) mutate(ctx context.Context, m *MaintenanceEntry
}
}
// NotifierClient is a client for the Notifier schema.
type NotifierClient struct {
config
}
// NewNotifierClient returns a client for the Notifier from the given config.
func NewNotifierClient(c config) *NotifierClient {
return &NotifierClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `notifier.Hooks(f(g(h())))`.
func (c *NotifierClient) Use(hooks ...Hook) {
c.hooks.Notifier = append(c.hooks.Notifier, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `notifier.Intercept(f(g(h())))`.
func (c *NotifierClient) Intercept(interceptors ...Interceptor) {
c.inters.Notifier = append(c.inters.Notifier, interceptors...)
}
// Create returns a builder for creating a Notifier entity.
func (c *NotifierClient) Create() *NotifierCreate {
mutation := newNotifierMutation(c.config, OpCreate)
return &NotifierCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of Notifier entities.
func (c *NotifierClient) CreateBulk(builders ...*NotifierCreate) *NotifierCreateBulk {
return &NotifierCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for Notifier.
func (c *NotifierClient) Update() *NotifierUpdate {
mutation := newNotifierMutation(c.config, OpUpdate)
return &NotifierUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *NotifierClient) UpdateOne(n *Notifier) *NotifierUpdateOne {
mutation := newNotifierMutation(c.config, OpUpdateOne, withNotifier(n))
return &NotifierUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *NotifierClient) UpdateOneID(id uuid.UUID) *NotifierUpdateOne {
mutation := newNotifierMutation(c.config, OpUpdateOne, withNotifierID(id))
return &NotifierUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for Notifier.
func (c *NotifierClient) Delete() *NotifierDelete {
mutation := newNotifierMutation(c.config, OpDelete)
return &NotifierDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *NotifierClient) DeleteOne(n *Notifier) *NotifierDeleteOne {
return c.DeleteOneID(n.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *NotifierClient) DeleteOneID(id uuid.UUID) *NotifierDeleteOne {
builder := c.Delete().Where(notifier.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &NotifierDeleteOne{builder}
}
// Query returns a query builder for Notifier.
func (c *NotifierClient) Query() *NotifierQuery {
return &NotifierQuery{
config: c.config,
ctx: &QueryContext{Type: TypeNotifier},
inters: c.Interceptors(),
}
}
// Get returns a Notifier entity by its id.
func (c *NotifierClient) Get(ctx context.Context, id uuid.UUID) (*Notifier, error) {
return c.Query().Where(notifier.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *NotifierClient) GetX(ctx context.Context, id uuid.UUID) *Notifier {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryGroup queries the group edge of a Notifier.
func (c *NotifierClient) QueryGroup(n *Notifier) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := n.ID
step := sqlgraph.NewStep(
sqlgraph.From(notifier.Table, notifier.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, notifier.GroupTable, notifier.GroupColumn),
)
fromV = sqlgraph.Neighbors(n.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryUser queries the user edge of a Notifier.
func (c *NotifierClient) QueryUser(n *Notifier) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := n.ID
step := sqlgraph.NewStep(
sqlgraph.From(notifier.Table, notifier.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, notifier.UserTable, notifier.UserColumn),
)
fromV = sqlgraph.Neighbors(n.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *NotifierClient) Hooks() []Hook {
return c.hooks.Notifier
}
// Interceptors returns the client interceptors.
func (c *NotifierClient) Interceptors() []Interceptor {
return c.inters.Notifier
}
func (c *NotifierClient) mutate(ctx context.Context, m *NotifierMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&NotifierCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&NotifierUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&NotifierUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&NotifierDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown Notifier mutation op: %q", m.Op())
}
}
// UserClient is a client for the User schema.
type UserClient struct {
config
@ -2153,6 +2329,22 @@ func (c *UserClient) QueryAuthTokens(u *User) *AuthTokensQuery {
return query
}
// QueryNotifiers queries the notifiers edge of a User.
func (c *UserClient) QueryNotifiers(u *User) *NotifierQuery {
query := (&NotifierClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := u.ID
step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, id),
sqlgraph.To(notifier.Table, notifier.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, user.NotifiersTable, user.NotifiersColumn),
)
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *UserClient) Hooks() []Hook {
return c.hooks.User

View file

@ -38,6 +38,7 @@ type (
Label []ent.Hook
Location []ent.Hook
MaintenanceEntry []ent.Hook
Notifier []ent.Hook
User []ent.Hook
}
inters struct {
@ -52,6 +53,7 @@ type (
Label []ent.Interceptor
Location []ent.Interceptor
MaintenanceEntry []ent.Interceptor
Notifier []ent.Interceptor
User []ent.Interceptor
}
)

View file

@ -22,6 +22,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/ent/label"
"github.com/hay-kot/homebox/backend/internal/data/ent/location"
"github.com/hay-kot/homebox/backend/internal/data/ent/maintenanceentry"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -61,6 +62,7 @@ func columnChecker(table string) func(string) error {
label.Table: label.ValidColumn,
location.Table: location.ValidColumn,
maintenanceentry.Table: maintenanceentry.ValidColumn,
notifier.Table: notifier.ValidColumn,
user.Table: user.ValidColumn,
}
check, ok := checks[table]

View file

@ -44,9 +44,11 @@ type GroupEdges struct {
Documents []*Document `json:"documents,omitempty"`
// InvitationTokens holds the value of the invitation_tokens edge.
InvitationTokens []*GroupInvitationToken `json:"invitation_tokens,omitempty"`
// Notifiers holds the value of the notifiers edge.
Notifiers []*Notifier `json:"notifiers,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [6]bool
loadedTypes [7]bool
}
// UsersOrErr returns the Users value or an error if the edge
@ -103,6 +105,15 @@ func (e GroupEdges) InvitationTokensOrErr() ([]*GroupInvitationToken, error) {
return nil, &NotLoadedError{edge: "invitation_tokens"}
}
// NotifiersOrErr returns the Notifiers value or an error if the edge
// was not loaded in eager-loading.
func (e GroupEdges) NotifiersOrErr() ([]*Notifier, error) {
if e.loadedTypes[6] {
return e.Notifiers, nil
}
return nil, &NotLoadedError{edge: "notifiers"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*Group) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
@ -194,6 +205,11 @@ func (gr *Group) QueryInvitationTokens() *GroupInvitationTokenQuery {
return NewGroupClient(gr.config).QueryInvitationTokens(gr)
}
// QueryNotifiers queries the "notifiers" edge of the Group entity.
func (gr *Group) QueryNotifiers() *NotifierQuery {
return NewGroupClient(gr.config).QueryNotifiers(gr)
}
// Update returns a builder for updating this Group.
// Note that you need to call Group.Unwrap() before calling this method if this Group
// was returned from a transaction, and the transaction was committed or rolled back.

View file

@ -34,6 +34,8 @@ const (
EdgeDocuments = "documents"
// EdgeInvitationTokens holds the string denoting the invitation_tokens edge name in mutations.
EdgeInvitationTokens = "invitation_tokens"
// EdgeNotifiers holds the string denoting the notifiers edge name in mutations.
EdgeNotifiers = "notifiers"
// Table holds the table name of the group in the database.
Table = "groups"
// UsersTable is the table that holds the users relation/edge.
@ -78,6 +80,13 @@ const (
InvitationTokensInverseTable = "group_invitation_tokens"
// InvitationTokensColumn is the table column denoting the invitation_tokens relation/edge.
InvitationTokensColumn = "group_invitation_tokens"
// NotifiersTable is the table that holds the notifiers relation/edge.
NotifiersTable = "notifiers"
// NotifiersInverseTable is the table name for the Notifier entity.
// It exists in this package in order to avoid circular dependency with the "notifier" package.
NotifiersInverseTable = "notifiers"
// NotifiersColumn is the table column denoting the notifiers relation/edge.
NotifiersColumn = "group_id"
)
// Columns holds all SQL columns for group fields.

View file

@ -398,6 +398,33 @@ func HasInvitationTokensWith(preds ...predicate.GroupInvitationToken) predicate.
})
}
// HasNotifiers applies the HasEdge predicate on the "notifiers" edge.
func HasNotifiers() predicate.Group {
return predicate.Group(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, NotifiersTable, NotifiersColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasNotifiersWith applies the HasEdge predicate on the "notifiers" edge with a given conditions (other predicates).
func HasNotifiersWith(preds ...predicate.Notifier) predicate.Group {
return predicate.Group(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(NotifiersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, NotifiersTable, NotifiersColumn),
)
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.Group) predicate.Group {
return predicate.Group(func(s *sql.Selector) {

View file

@ -17,6 +17,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/ent/item"
"github.com/hay-kot/homebox/backend/internal/data/ent/label"
"github.com/hay-kot/homebox/backend/internal/data/ent/location"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -179,6 +180,21 @@ func (gc *GroupCreate) AddInvitationTokens(g ...*GroupInvitationToken) *GroupCre
return gc.AddInvitationTokenIDs(ids...)
}
// AddNotifierIDs adds the "notifiers" edge to the Notifier entity by IDs.
func (gc *GroupCreate) AddNotifierIDs(ids ...uuid.UUID) *GroupCreate {
gc.mutation.AddNotifierIDs(ids...)
return gc
}
// AddNotifiers adds the "notifiers" edges to the Notifier entity.
func (gc *GroupCreate) AddNotifiers(n ...*Notifier) *GroupCreate {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return gc.AddNotifierIDs(ids...)
}
// Mutation returns the GroupMutation object of the builder.
func (gc *GroupCreate) Mutation() *GroupMutation {
return gc.mutation
@ -421,6 +437,25 @@ func (gc *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := gc.mutation.NotifiersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.NotifiersTable,
Columns: []string{group.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}

View file

@ -18,6 +18,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/ent/item"
"github.com/hay-kot/homebox/backend/internal/data/ent/label"
"github.com/hay-kot/homebox/backend/internal/data/ent/location"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -35,6 +36,7 @@ type GroupQuery struct {
withLabels *LabelQuery
withDocuments *DocumentQuery
withInvitationTokens *GroupInvitationTokenQuery
withNotifiers *NotifierQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@ -203,6 +205,28 @@ func (gq *GroupQuery) QueryInvitationTokens() *GroupInvitationTokenQuery {
return query
}
// QueryNotifiers chains the current query on the "notifiers" edge.
func (gq *GroupQuery) QueryNotifiers() *NotifierQuery {
query := (&NotifierClient{config: gq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := gq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := gq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, selector),
sqlgraph.To(notifier.Table, notifier.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, group.NotifiersTable, group.NotifiersColumn),
)
fromU = sqlgraph.SetNeighbors(gq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first Group entity from the query.
// Returns a *NotFoundError when no Group was found.
func (gq *GroupQuery) First(ctx context.Context) (*Group, error) {
@ -401,6 +425,7 @@ func (gq *GroupQuery) Clone() *GroupQuery {
withLabels: gq.withLabels.Clone(),
withDocuments: gq.withDocuments.Clone(),
withInvitationTokens: gq.withInvitationTokens.Clone(),
withNotifiers: gq.withNotifiers.Clone(),
// clone intermediate query.
sql: gq.sql.Clone(),
path: gq.path,
@ -473,6 +498,17 @@ func (gq *GroupQuery) WithInvitationTokens(opts ...func(*GroupInvitationTokenQue
return gq
}
// WithNotifiers tells the query-builder to eager-load the nodes that are connected to
// the "notifiers" edge. The optional arguments are used to configure the query builder of the edge.
func (gq *GroupQuery) WithNotifiers(opts ...func(*NotifierQuery)) *GroupQuery {
query := (&NotifierClient{config: gq.config}).Query()
for _, opt := range opts {
opt(query)
}
gq.withNotifiers = query
return gq
}
// 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.
//
@ -551,13 +587,14 @@ func (gq *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
var (
nodes = []*Group{}
_spec = gq.querySpec()
loadedTypes = [6]bool{
loadedTypes = [7]bool{
gq.withUsers != nil,
gq.withLocations != nil,
gq.withItems != nil,
gq.withLabels != nil,
gq.withDocuments != nil,
gq.withInvitationTokens != nil,
gq.withNotifiers != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
@ -622,6 +659,13 @@ func (gq *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
return nil, err
}
}
if query := gq.withNotifiers; query != nil {
if err := gq.loadNotifiers(ctx, query, nodes,
func(n *Group) { n.Edges.Notifiers = []*Notifier{} },
func(n *Group, e *Notifier) { n.Edges.Notifiers = append(n.Edges.Notifiers, e) }); err != nil {
return nil, err
}
}
return nodes, nil
}
@ -811,6 +855,33 @@ func (gq *GroupQuery) loadInvitationTokens(ctx context.Context, query *GroupInvi
}
return nil
}
func (gq *GroupQuery) loadNotifiers(ctx context.Context, query *NotifierQuery, nodes []*Group, init func(*Group), assign func(*Group, *Notifier)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Group)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
query.Where(predicate.Notifier(func(s *sql.Selector) {
s.Where(sql.InValues(group.NotifiersColumn, fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.GroupID
node, ok := nodeids[fk]
if !ok {
return fmt.Errorf(`unexpected foreign-key "group_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
return nil
}
func (gq *GroupQuery) sqlCount(ctx context.Context) (int, error) {
_spec := gq.querySpec()

View file

@ -18,6 +18,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/ent/item"
"github.com/hay-kot/homebox/backend/internal/data/ent/label"
"github.com/hay-kot/homebox/backend/internal/data/ent/location"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -151,6 +152,21 @@ func (gu *GroupUpdate) AddInvitationTokens(g ...*GroupInvitationToken) *GroupUpd
return gu.AddInvitationTokenIDs(ids...)
}
// AddNotifierIDs adds the "notifiers" edge to the Notifier entity by IDs.
func (gu *GroupUpdate) AddNotifierIDs(ids ...uuid.UUID) *GroupUpdate {
gu.mutation.AddNotifierIDs(ids...)
return gu
}
// AddNotifiers adds the "notifiers" edges to the Notifier entity.
func (gu *GroupUpdate) AddNotifiers(n ...*Notifier) *GroupUpdate {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return gu.AddNotifierIDs(ids...)
}
// Mutation returns the GroupMutation object of the builder.
func (gu *GroupUpdate) Mutation() *GroupMutation {
return gu.mutation
@ -282,6 +298,27 @@ func (gu *GroupUpdate) RemoveInvitationTokens(g ...*GroupInvitationToken) *Group
return gu.RemoveInvitationTokenIDs(ids...)
}
// ClearNotifiers clears all "notifiers" edges to the Notifier entity.
func (gu *GroupUpdate) ClearNotifiers() *GroupUpdate {
gu.mutation.ClearNotifiers()
return gu
}
// RemoveNotifierIDs removes the "notifiers" edge to Notifier entities by IDs.
func (gu *GroupUpdate) RemoveNotifierIDs(ids ...uuid.UUID) *GroupUpdate {
gu.mutation.RemoveNotifierIDs(ids...)
return gu
}
// RemoveNotifiers removes "notifiers" edges to Notifier entities.
func (gu *GroupUpdate) RemoveNotifiers(n ...*Notifier) *GroupUpdate {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return gu.RemoveNotifierIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (gu *GroupUpdate) Save(ctx context.Context) (int, error) {
gu.defaults()
@ -678,6 +715,60 @@ func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if gu.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.NotifiersTable,
Columns: []string{group.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := gu.mutation.RemovedNotifiersIDs(); len(nodes) > 0 && !gu.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.NotifiersTable,
Columns: []string{group.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := gu.mutation.NotifiersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.NotifiersTable,
Columns: []string{group.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.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, gu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{group.Label}
@ -814,6 +905,21 @@ func (guo *GroupUpdateOne) AddInvitationTokens(g ...*GroupInvitationToken) *Grou
return guo.AddInvitationTokenIDs(ids...)
}
// AddNotifierIDs adds the "notifiers" edge to the Notifier entity by IDs.
func (guo *GroupUpdateOne) AddNotifierIDs(ids ...uuid.UUID) *GroupUpdateOne {
guo.mutation.AddNotifierIDs(ids...)
return guo
}
// AddNotifiers adds the "notifiers" edges to the Notifier entity.
func (guo *GroupUpdateOne) AddNotifiers(n ...*Notifier) *GroupUpdateOne {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return guo.AddNotifierIDs(ids...)
}
// Mutation returns the GroupMutation object of the builder.
func (guo *GroupUpdateOne) Mutation() *GroupMutation {
return guo.mutation
@ -945,6 +1051,27 @@ func (guo *GroupUpdateOne) RemoveInvitationTokens(g ...*GroupInvitationToken) *G
return guo.RemoveInvitationTokenIDs(ids...)
}
// ClearNotifiers clears all "notifiers" edges to the Notifier entity.
func (guo *GroupUpdateOne) ClearNotifiers() *GroupUpdateOne {
guo.mutation.ClearNotifiers()
return guo
}
// RemoveNotifierIDs removes the "notifiers" edge to Notifier entities by IDs.
func (guo *GroupUpdateOne) RemoveNotifierIDs(ids ...uuid.UUID) *GroupUpdateOne {
guo.mutation.RemoveNotifierIDs(ids...)
return guo
}
// RemoveNotifiers removes "notifiers" edges to Notifier entities.
func (guo *GroupUpdateOne) RemoveNotifiers(n ...*Notifier) *GroupUpdateOne {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return guo.RemoveNotifierIDs(ids...)
}
// Where appends a list predicates to the GroupUpdate builder.
func (guo *GroupUpdateOne) Where(ps ...predicate.Group) *GroupUpdateOne {
guo.mutation.Where(ps...)
@ -1371,6 +1498,60 @@ func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if guo.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.NotifiersTable,
Columns: []string{group.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := guo.mutation.RemovedNotifiersIDs(); len(nodes) > 0 && !guo.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.NotifiersTable,
Columns: []string{group.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := guo.mutation.NotifiersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.NotifiersTable,
Columns: []string{group.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &Group{config: guo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues

View file

@ -48,6 +48,10 @@ func (me *MaintenanceEntry) GetID() uuid.UUID {
return me.ID
}
func (n *Notifier) GetID() uuid.UUID {
return n.ID
}
func (u *User) GetID() uuid.UUID {
return u.ID
}

View file

@ -141,6 +141,18 @@ func (f MaintenanceEntryFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.V
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.MaintenanceEntryMutation", m)
}
// The NotifierFunc type is an adapter to allow the use of ordinary
// function as Notifier mutator.
type NotifierFunc func(context.Context, *ent.NotifierMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f NotifierFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.NotifierMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.NotifierMutation", m)
}
// The UserFunc type is an adapter to allow the use of ordinary
// function as User mutator.
type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error)

View file

@ -75,12 +75,12 @@ type Item struct {
// ItemEdges holds the relations/edges for other nodes in the graph.
type ItemEdges struct {
// Group holds the value of the group edge.
Group *Group `json:"group,omitempty"`
// Parent holds the value of the parent edge.
Parent *Item `json:"parent,omitempty"`
// Children holds the value of the children edge.
Children []*Item `json:"children,omitempty"`
// Group holds the value of the group edge.
Group *Group `json:"group,omitempty"`
// Label holds the value of the label edge.
Label []*Label `json:"label,omitempty"`
// Location holds the value of the location edge.
@ -96,10 +96,23 @@ type ItemEdges struct {
loadedTypes [8]bool
}
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ItemEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[0] {
if e.Group == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label}
}
return e.Group, nil
}
return nil, &NotLoadedError{edge: "group"}
}
// ParentOrErr returns the Parent value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ItemEdges) ParentOrErr() (*Item, error) {
if e.loadedTypes[0] {
if e.loadedTypes[1] {
if e.Parent == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: item.Label}
@ -112,25 +125,12 @@ func (e ItemEdges) ParentOrErr() (*Item, error) {
// ChildrenOrErr returns the Children value or an error if the edge
// was not loaded in eager-loading.
func (e ItemEdges) ChildrenOrErr() ([]*Item, error) {
if e.loadedTypes[1] {
if e.loadedTypes[2] {
return e.Children, nil
}
return nil, &NotLoadedError{edge: "children"}
}
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ItemEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[2] {
if e.Group == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label}
}
return e.Group, nil
}
return nil, &NotLoadedError{edge: "group"}
}
// LabelOrErr returns the Label value or an error if the edge
// was not loaded in eager-loading.
func (e ItemEdges) LabelOrErr() ([]*Label, error) {
@ -388,6 +388,11 @@ func (i *Item) assignValues(columns []string, values []any) error {
return nil
}
// QueryGroup queries the "group" edge of the Item entity.
func (i *Item) QueryGroup() *GroupQuery {
return NewItemClient(i.config).QueryGroup(i)
}
// QueryParent queries the "parent" edge of the Item entity.
func (i *Item) QueryParent() *ItemQuery {
return NewItemClient(i.config).QueryParent(i)
@ -398,11 +403,6 @@ func (i *Item) QueryChildren() *ItemQuery {
return NewItemClient(i.config).QueryChildren(i)
}
// QueryGroup queries the "group" edge of the Item entity.
func (i *Item) QueryGroup() *GroupQuery {
return NewItemClient(i.config).QueryGroup(i)
}
// QueryLabel queries the "label" edge of the Item entity.
func (i *Item) QueryLabel() *LabelQuery {
return NewItemClient(i.config).QueryLabel(i)

View file

@ -59,12 +59,12 @@ const (
FieldSoldPrice = "sold_price"
// FieldSoldNotes holds the string denoting the sold_notes field in the database.
FieldSoldNotes = "sold_notes"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeParent holds the string denoting the parent edge name in mutations.
EdgeParent = "parent"
// EdgeChildren holds the string denoting the children edge name in mutations.
EdgeChildren = "children"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeLabel holds the string denoting the label edge name in mutations.
EdgeLabel = "label"
// EdgeLocation holds the string denoting the location edge name in mutations.
@ -77,6 +77,13 @@ const (
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.
GroupTable = "items"
// GroupInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_items"
// ParentTable is the table that holds the parent relation/edge.
ParentTable = "items"
// ParentColumn is the table column denoting the parent relation/edge.
@ -85,13 +92,6 @@ const (
ChildrenTable = "items"
// ChildrenColumn is the table column denoting the children relation/edge.
ChildrenColumn = "item_children"
// GroupTable is the table that holds the group relation/edge.
GroupTable = "items"
// GroupInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_items"
// LabelTable is the table that holds the label relation/edge. The primary key declared below.
LabelTable = "label_items"
// LabelInverseTable is the table name for the Label entity.

View file

@ -1406,6 +1406,33 @@ func SoldNotesContainsFold(v string) predicate.Item {
return predicate.Item(sql.FieldContainsFold(FieldSoldNotes, v))
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasParent applies the HasEdge predicate on the "parent" edge.
func HasParent() predicate.Item {
return predicate.Item(func(s *sql.Selector) {
@ -1460,33 +1487,6 @@ func HasChildrenWith(preds ...predicate.Item) predicate.Item {
})
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasLabel applies the HasEdge predicate on the "label" edge.
func HasLabel() predicate.Item {
return predicate.Item(func(s *sql.Selector) {

View file

@ -355,6 +355,17 @@ func (ic *ItemCreate) SetNillableID(u *uuid.UUID) *ItemCreate {
return ic
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (ic *ItemCreate) SetGroupID(id uuid.UUID) *ItemCreate {
ic.mutation.SetGroupID(id)
return ic
}
// SetGroup sets the "group" edge to the Group entity.
func (ic *ItemCreate) SetGroup(g *Group) *ItemCreate {
return ic.SetGroupID(g.ID)
}
// SetParentID sets the "parent" edge to the Item entity by ID.
func (ic *ItemCreate) SetParentID(id uuid.UUID) *ItemCreate {
ic.mutation.SetParentID(id)
@ -389,17 +400,6 @@ func (ic *ItemCreate) AddChildren(i ...*Item) *ItemCreate {
return ic.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (ic *ItemCreate) SetGroupID(id uuid.UUID) *ItemCreate {
ic.mutation.SetGroupID(id)
return ic
}
// SetGroup sets the "group" edge to the Group entity.
func (ic *ItemCreate) SetGroup(g *Group) *ItemCreate {
return ic.SetGroupID(g.ID)
}
// AddLabelIDs adds the "label" edge to the Label entity by IDs.
func (ic *ItemCreate) AddLabelIDs(ids ...uuid.UUID) *ItemCreate {
ic.mutation.AddLabelIDs(ids...)
@ -763,6 +763,26 @@ func (ic *ItemCreate) createSpec() (*Item, *sqlgraph.CreateSpec) {
_spec.SetField(item.FieldSoldNotes, field.TypeString, value)
_node.SoldNotes = value
}
if nodes := ic.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.group_items = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := ic.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@ -802,26 +822,6 @@ func (ic *ItemCreate) createSpec() (*Item, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := ic.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.group_items = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := ic.mutation.LabelIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,

View file

@ -29,9 +29,9 @@ type ItemQuery struct {
order []OrderFunc
inters []Interceptor
predicates []predicate.Item
withGroup *GroupQuery
withParent *ItemQuery
withChildren *ItemQuery
withGroup *GroupQuery
withLabel *LabelQuery
withLocation *LocationQuery
withFields *ItemFieldQuery
@ -74,6 +74,28 @@ func (iq *ItemQuery) Order(o ...OrderFunc) *ItemQuery {
return iq
}
// QueryGroup chains the current query on the "group" edge.
func (iq *ItemQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: iq.config}).Query()
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(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, item.GroupTable, item.GroupColumn),
)
fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryParent chains the current query on the "parent" edge.
func (iq *ItemQuery) QueryParent() *ItemQuery {
query := (&ItemClient{config: iq.config}).Query()
@ -118,28 +140,6 @@ func (iq *ItemQuery) QueryChildren() *ItemQuery {
return query
}
// QueryGroup chains the current query on the "group" edge.
func (iq *ItemQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: iq.config}).Query()
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(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, item.GroupTable, item.GroupColumn),
)
fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryLabel chains the current query on the "label" edge.
func (iq *ItemQuery) QueryLabel() *LabelQuery {
query := (&LabelClient{config: iq.config}).Query()
@ -442,9 +442,9 @@ func (iq *ItemQuery) Clone() *ItemQuery {
order: append([]OrderFunc{}, iq.order...),
inters: append([]Interceptor{}, iq.inters...),
predicates: append([]predicate.Item{}, iq.predicates...),
withGroup: iq.withGroup.Clone(),
withParent: iq.withParent.Clone(),
withChildren: iq.withChildren.Clone(),
withGroup: iq.withGroup.Clone(),
withLabel: iq.withLabel.Clone(),
withLocation: iq.withLocation.Clone(),
withFields: iq.withFields.Clone(),
@ -456,6 +456,17 @@ func (iq *ItemQuery) Clone() *ItemQuery {
}
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (iq *ItemQuery) WithGroup(opts ...func(*GroupQuery)) *ItemQuery {
query := (&GroupClient{config: iq.config}).Query()
for _, opt := range opts {
opt(query)
}
iq.withGroup = query
return iq
}
// WithParent tells the query-builder to eager-load the nodes that are connected to
// the "parent" edge. The optional arguments are used to configure the query builder of the edge.
func (iq *ItemQuery) WithParent(opts ...func(*ItemQuery)) *ItemQuery {
@ -478,17 +489,6 @@ func (iq *ItemQuery) WithChildren(opts ...func(*ItemQuery)) *ItemQuery {
return iq
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (iq *ItemQuery) WithGroup(opts ...func(*GroupQuery)) *ItemQuery {
query := (&GroupClient{config: iq.config}).Query()
for _, opt := range opts {
opt(query)
}
iq.withGroup = query
return iq
}
// WithLabel tells the query-builder to eager-load the nodes that are connected to
// the "label" edge. The optional arguments are used to configure the query builder of the edge.
func (iq *ItemQuery) WithLabel(opts ...func(*LabelQuery)) *ItemQuery {
@ -624,9 +624,9 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
withFKs = iq.withFKs
_spec = iq.querySpec()
loadedTypes = [8]bool{
iq.withGroup != nil,
iq.withParent != nil,
iq.withChildren != nil,
iq.withGroup != nil,
iq.withLabel != nil,
iq.withLocation != nil,
iq.withFields != nil,
@ -634,7 +634,7 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
iq.withAttachments != nil,
}
)
if iq.withParent != nil || iq.withGroup != nil || iq.withLocation != nil {
if iq.withGroup != nil || iq.withParent != nil || iq.withLocation != nil {
withFKs = true
}
if withFKs {
@ -658,6 +658,12 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
if len(nodes) == 0 {
return nodes, nil
}
if query := iq.withGroup; query != nil {
if err := iq.loadGroup(ctx, query, nodes, nil,
func(n *Item, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
if query := iq.withParent; query != nil {
if err := iq.loadParent(ctx, query, nodes, nil,
func(n *Item, e *Item) { n.Edges.Parent = e }); err != nil {
@ -671,12 +677,6 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
return nil, err
}
}
if query := iq.withGroup; query != nil {
if err := iq.loadGroup(ctx, query, nodes, nil,
func(n *Item, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
if query := iq.withLabel; query != nil {
if err := iq.loadLabel(ctx, query, nodes,
func(n *Item) { n.Edges.Label = []*Label{} },
@ -714,6 +714,38 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
return nodes, nil
}
func (iq *ItemQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Item, init func(*Item), assign func(*Item, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Item)
for i := range nodes {
if nodes[i].group_items == nil {
continue
}
fk := *nodes[i].group_items
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(group.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 "group_items" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (iq *ItemQuery) loadParent(ctx context.Context, query *ItemQuery, nodes []*Item, init func(*Item), assign func(*Item, *Item)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Item)
@ -777,38 +809,6 @@ func (iq *ItemQuery) loadChildren(ctx context.Context, query *ItemQuery, nodes [
}
return nil
}
func (iq *ItemQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Item, init func(*Item), assign func(*Item, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Item)
for i := range nodes {
if nodes[i].group_items == nil {
continue
}
fk := *nodes[i].group_items
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(group.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 "group_items" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (iq *ItemQuery) loadLabel(ctx context.Context, query *LabelQuery, nodes []*Item, init func(*Item), assign func(*Item, *Label)) error {
edgeIDs := make([]driver.Value, len(nodes))
byID := make(map[uuid.UUID]*Item)

View file

@ -433,6 +433,17 @@ func (iu *ItemUpdate) ClearSoldNotes() *ItemUpdate {
return iu
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (iu *ItemUpdate) SetGroupID(id uuid.UUID) *ItemUpdate {
iu.mutation.SetGroupID(id)
return iu
}
// SetGroup sets the "group" edge to the Group entity.
func (iu *ItemUpdate) SetGroup(g *Group) *ItemUpdate {
return iu.SetGroupID(g.ID)
}
// SetParentID sets the "parent" edge to the Item entity by ID.
func (iu *ItemUpdate) SetParentID(id uuid.UUID) *ItemUpdate {
iu.mutation.SetParentID(id)
@ -467,17 +478,6 @@ func (iu *ItemUpdate) AddChildren(i ...*Item) *ItemUpdate {
return iu.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (iu *ItemUpdate) SetGroupID(id uuid.UUID) *ItemUpdate {
iu.mutation.SetGroupID(id)
return iu
}
// SetGroup sets the "group" edge to the Group entity.
func (iu *ItemUpdate) SetGroup(g *Group) *ItemUpdate {
return iu.SetGroupID(g.ID)
}
// AddLabelIDs adds the "label" edge to the Label entity by IDs.
func (iu *ItemUpdate) AddLabelIDs(ids ...uuid.UUID) *ItemUpdate {
iu.mutation.AddLabelIDs(ids...)
@ -562,6 +562,12 @@ func (iu *ItemUpdate) Mutation() *ItemMutation {
return iu.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (iu *ItemUpdate) ClearGroup() *ItemUpdate {
iu.mutation.ClearGroup()
return iu
}
// ClearParent clears the "parent" edge to the Item entity.
func (iu *ItemUpdate) ClearParent() *ItemUpdate {
iu.mutation.ClearParent()
@ -589,12 +595,6 @@ func (iu *ItemUpdate) RemoveChildren(i ...*Item) *ItemUpdate {
return iu.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity.
func (iu *ItemUpdate) ClearGroup() *ItemUpdate {
iu.mutation.ClearGroup()
return iu
}
// ClearLabel clears all "label" edges to the Label entity.
func (iu *ItemUpdate) ClearLabel() *ItemUpdate {
iu.mutation.ClearLabel()
@ -903,6 +903,41 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) {
if iu.mutation.SoldNotesCleared() {
_spec.ClearField(item.FieldSoldNotes, field.TypeString)
}
if iu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iu.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iu.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@ -992,41 +1027,6 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iu.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iu.mutation.LabelCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,
@ -1696,6 +1696,17 @@ func (iuo *ItemUpdateOne) ClearSoldNotes() *ItemUpdateOne {
return iuo
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (iuo *ItemUpdateOne) SetGroupID(id uuid.UUID) *ItemUpdateOne {
iuo.mutation.SetGroupID(id)
return iuo
}
// SetGroup sets the "group" edge to the Group entity.
func (iuo *ItemUpdateOne) SetGroup(g *Group) *ItemUpdateOne {
return iuo.SetGroupID(g.ID)
}
// SetParentID sets the "parent" edge to the Item entity by ID.
func (iuo *ItemUpdateOne) SetParentID(id uuid.UUID) *ItemUpdateOne {
iuo.mutation.SetParentID(id)
@ -1730,17 +1741,6 @@ func (iuo *ItemUpdateOne) AddChildren(i ...*Item) *ItemUpdateOne {
return iuo.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (iuo *ItemUpdateOne) SetGroupID(id uuid.UUID) *ItemUpdateOne {
iuo.mutation.SetGroupID(id)
return iuo
}
// SetGroup sets the "group" edge to the Group entity.
func (iuo *ItemUpdateOne) SetGroup(g *Group) *ItemUpdateOne {
return iuo.SetGroupID(g.ID)
}
// AddLabelIDs adds the "label" edge to the Label entity by IDs.
func (iuo *ItemUpdateOne) AddLabelIDs(ids ...uuid.UUID) *ItemUpdateOne {
iuo.mutation.AddLabelIDs(ids...)
@ -1825,6 +1825,12 @@ func (iuo *ItemUpdateOne) Mutation() *ItemMutation {
return iuo.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (iuo *ItemUpdateOne) ClearGroup() *ItemUpdateOne {
iuo.mutation.ClearGroup()
return iuo
}
// ClearParent clears the "parent" edge to the Item entity.
func (iuo *ItemUpdateOne) ClearParent() *ItemUpdateOne {
iuo.mutation.ClearParent()
@ -1852,12 +1858,6 @@ func (iuo *ItemUpdateOne) RemoveChildren(i ...*Item) *ItemUpdateOne {
return iuo.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity.
func (iuo *ItemUpdateOne) ClearGroup() *ItemUpdateOne {
iuo.mutation.ClearGroup()
return iuo
}
// ClearLabel clears all "label" edges to the Label entity.
func (iuo *ItemUpdateOne) ClearLabel() *ItemUpdateOne {
iuo.mutation.ClearLabel()
@ -2196,6 +2196,41 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error)
if iuo.mutation.SoldNotesCleared() {
_spec.ClearField(item.FieldSoldNotes, field.TypeString)
}
if iuo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iuo.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iuo.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@ -2285,41 +2320,6 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iuo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iuo.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.GroupTable,
Columns: []string{item.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iuo.mutation.LabelCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2M,

View file

@ -35,12 +35,12 @@ type Location struct {
// LocationEdges holds the relations/edges for other nodes in the graph.
type LocationEdges struct {
// Group holds the value of the group edge.
Group *Group `json:"group,omitempty"`
// Parent holds the value of the parent edge.
Parent *Location `json:"parent,omitempty"`
// Children holds the value of the children edge.
Children []*Location `json:"children,omitempty"`
// Group holds the value of the group edge.
Group *Group `json:"group,omitempty"`
// Items holds the value of the items edge.
Items []*Item `json:"items,omitempty"`
// loadedTypes holds the information for reporting if a
@ -48,10 +48,23 @@ type LocationEdges struct {
loadedTypes [4]bool
}
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e LocationEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[0] {
if e.Group == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label}
}
return e.Group, nil
}
return nil, &NotLoadedError{edge: "group"}
}
// ParentOrErr returns the Parent value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e LocationEdges) ParentOrErr() (*Location, error) {
if e.loadedTypes[0] {
if e.loadedTypes[1] {
if e.Parent == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: location.Label}
@ -64,25 +77,12 @@ func (e LocationEdges) ParentOrErr() (*Location, error) {
// ChildrenOrErr returns the Children value or an error if the edge
// was not loaded in eager-loading.
func (e LocationEdges) ChildrenOrErr() ([]*Location, error) {
if e.loadedTypes[1] {
if e.loadedTypes[2] {
return e.Children, nil
}
return nil, &NotLoadedError{edge: "children"}
}
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e LocationEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[2] {
if e.Group == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label}
}
return e.Group, nil
}
return nil, &NotLoadedError{edge: "group"}
}
// ItemsOrErr returns the Items value or an error if the edge
// was not loaded in eager-loading.
func (e LocationEdges) ItemsOrErr() ([]*Item, error) {
@ -171,6 +171,11 @@ func (l *Location) assignValues(columns []string, values []any) error {
return nil
}
// QueryGroup queries the "group" edge of the Location entity.
func (l *Location) QueryGroup() *GroupQuery {
return NewLocationClient(l.config).QueryGroup(l)
}
// QueryParent queries the "parent" edge of the Location entity.
func (l *Location) QueryParent() *LocationQuery {
return NewLocationClient(l.config).QueryParent(l)
@ -181,11 +186,6 @@ func (l *Location) QueryChildren() *LocationQuery {
return NewLocationClient(l.config).QueryChildren(l)
}
// QueryGroup queries the "group" edge of the Location entity.
func (l *Location) QueryGroup() *GroupQuery {
return NewLocationClient(l.config).QueryGroup(l)
}
// QueryItems queries the "items" edge of the Location entity.
func (l *Location) QueryItems() *ItemQuery {
return NewLocationClient(l.config).QueryItems(l)

View file

@ -21,16 +21,23 @@ const (
FieldName = "name"
// FieldDescription holds the string denoting the description field in the database.
FieldDescription = "description"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeParent holds the string denoting the parent edge name in mutations.
EdgeParent = "parent"
// EdgeChildren holds the string denoting the children edge name in mutations.
EdgeChildren = "children"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeItems holds the string denoting the items edge name in mutations.
EdgeItems = "items"
// Table holds the table name of the location in the database.
Table = "locations"
// GroupTable is the table that holds the group relation/edge.
GroupTable = "locations"
// GroupInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_locations"
// ParentTable is the table that holds the parent relation/edge.
ParentTable = "locations"
// ParentColumn is the table column denoting the parent relation/edge.
@ -39,13 +46,6 @@ const (
ChildrenTable = "locations"
// ChildrenColumn is the table column denoting the children relation/edge.
ChildrenColumn = "location_children"
// GroupTable is the table that holds the group relation/edge.
GroupTable = "locations"
// GroupInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_locations"
// ItemsTable is the table that holds the items relation/edge.
ItemsTable = "items"
// ItemsInverseTable is the table name for the Item entity.

View file

@ -296,6 +296,33 @@ func DescriptionContainsFold(v string) predicate.Location {
return predicate.Location(sql.FieldContainsFold(FieldDescription, v))
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasParent applies the HasEdge predicate on the "parent" edge.
func HasParent() predicate.Location {
return predicate.Location(func(s *sql.Selector) {
@ -350,33 +377,6 @@ func HasChildrenWith(preds ...predicate.Location) predicate.Location {
})
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasItems applies the HasEdge predicate on the "items" edge.
func HasItems() predicate.Location {
return predicate.Location(func(s *sql.Selector) {

View file

@ -85,6 +85,17 @@ func (lc *LocationCreate) SetNillableID(u *uuid.UUID) *LocationCreate {
return lc
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (lc *LocationCreate) SetGroupID(id uuid.UUID) *LocationCreate {
lc.mutation.SetGroupID(id)
return lc
}
// SetGroup sets the "group" edge to the Group entity.
func (lc *LocationCreate) SetGroup(g *Group) *LocationCreate {
return lc.SetGroupID(g.ID)
}
// SetParentID sets the "parent" edge to the Location entity by ID.
func (lc *LocationCreate) SetParentID(id uuid.UUID) *LocationCreate {
lc.mutation.SetParentID(id)
@ -119,17 +130,6 @@ func (lc *LocationCreate) AddChildren(l ...*Location) *LocationCreate {
return lc.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (lc *LocationCreate) SetGroupID(id uuid.UUID) *LocationCreate {
lc.mutation.SetGroupID(id)
return lc
}
// SetGroup sets the "group" edge to the Group entity.
func (lc *LocationCreate) SetGroup(g *Group) *LocationCreate {
return lc.SetGroupID(g.ID)
}
// AddItemIDs adds the "items" edge to the Item entity by IDs.
func (lc *LocationCreate) AddItemIDs(ids ...uuid.UUID) *LocationCreate {
lc.mutation.AddItemIDs(ids...)
@ -269,6 +269,26 @@ func (lc *LocationCreate) createSpec() (*Location, *sqlgraph.CreateSpec) {
_spec.SetField(location.FieldDescription, field.TypeString, value)
_node.Description = value
}
if nodes := lc.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.group_locations = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := lc.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@ -308,26 +328,6 @@ func (lc *LocationCreate) createSpec() (*Location, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := lc.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.group_locations = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := lc.mutation.ItemsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,

View file

@ -25,9 +25,9 @@ type LocationQuery struct {
order []OrderFunc
inters []Interceptor
predicates []predicate.Location
withGroup *GroupQuery
withParent *LocationQuery
withChildren *LocationQuery
withGroup *GroupQuery
withItems *ItemQuery
withFKs bool
// intermediate query (i.e. traversal path).
@ -66,6 +66,28 @@ func (lq *LocationQuery) Order(o ...OrderFunc) *LocationQuery {
return lq
}
// QueryGroup chains the current query on the "group" edge.
func (lq *LocationQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: lq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := lq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := lq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, selector),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, location.GroupTable, location.GroupColumn),
)
fromU = sqlgraph.SetNeighbors(lq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryParent chains the current query on the "parent" edge.
func (lq *LocationQuery) QueryParent() *LocationQuery {
query := (&LocationClient{config: lq.config}).Query()
@ -110,28 +132,6 @@ func (lq *LocationQuery) QueryChildren() *LocationQuery {
return query
}
// QueryGroup chains the current query on the "group" edge.
func (lq *LocationQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: lq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := lq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := lq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, selector),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, location.GroupTable, location.GroupColumn),
)
fromU = sqlgraph.SetNeighbors(lq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryItems chains the current query on the "items" edge.
func (lq *LocationQuery) QueryItems() *ItemQuery {
query := (&ItemClient{config: lq.config}).Query()
@ -346,9 +346,9 @@ func (lq *LocationQuery) Clone() *LocationQuery {
order: append([]OrderFunc{}, lq.order...),
inters: append([]Interceptor{}, lq.inters...),
predicates: append([]predicate.Location{}, lq.predicates...),
withGroup: lq.withGroup.Clone(),
withParent: lq.withParent.Clone(),
withChildren: lq.withChildren.Clone(),
withGroup: lq.withGroup.Clone(),
withItems: lq.withItems.Clone(),
// clone intermediate query.
sql: lq.sql.Clone(),
@ -356,6 +356,17 @@ func (lq *LocationQuery) Clone() *LocationQuery {
}
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (lq *LocationQuery) WithGroup(opts ...func(*GroupQuery)) *LocationQuery {
query := (&GroupClient{config: lq.config}).Query()
for _, opt := range opts {
opt(query)
}
lq.withGroup = query
return lq
}
// WithParent tells the query-builder to eager-load the nodes that are connected to
// the "parent" edge. The optional arguments are used to configure the query builder of the edge.
func (lq *LocationQuery) WithParent(opts ...func(*LocationQuery)) *LocationQuery {
@ -378,17 +389,6 @@ func (lq *LocationQuery) WithChildren(opts ...func(*LocationQuery)) *LocationQue
return lq
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (lq *LocationQuery) WithGroup(opts ...func(*GroupQuery)) *LocationQuery {
query := (&GroupClient{config: lq.config}).Query()
for _, opt := range opts {
opt(query)
}
lq.withGroup = query
return lq
}
// WithItems tells the query-builder to eager-load the nodes that are connected to
// the "items" edge. The optional arguments are used to configure the query builder of the edge.
func (lq *LocationQuery) WithItems(opts ...func(*ItemQuery)) *LocationQuery {
@ -480,13 +480,13 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc
withFKs = lq.withFKs
_spec = lq.querySpec()
loadedTypes = [4]bool{
lq.withGroup != nil,
lq.withParent != nil,
lq.withChildren != nil,
lq.withGroup != nil,
lq.withItems != nil,
}
)
if lq.withParent != nil || lq.withGroup != nil {
if lq.withGroup != nil || lq.withParent != nil {
withFKs = true
}
if withFKs {
@ -510,6 +510,12 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc
if len(nodes) == 0 {
return nodes, nil
}
if query := lq.withGroup; query != nil {
if err := lq.loadGroup(ctx, query, nodes, nil,
func(n *Location, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
if query := lq.withParent; query != nil {
if err := lq.loadParent(ctx, query, nodes, nil,
func(n *Location, e *Location) { n.Edges.Parent = e }); err != nil {
@ -523,12 +529,6 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc
return nil, err
}
}
if query := lq.withGroup; query != nil {
if err := lq.loadGroup(ctx, query, nodes, nil,
func(n *Location, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
if query := lq.withItems; query != nil {
if err := lq.loadItems(ctx, query, nodes,
func(n *Location) { n.Edges.Items = []*Item{} },
@ -539,6 +539,38 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc
return nodes, nil
}
func (lq *LocationQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Location, init func(*Location), assign func(*Location, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Location)
for i := range nodes {
if nodes[i].group_locations == nil {
continue
}
fk := *nodes[i].group_locations
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(group.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 "group_locations" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (lq *LocationQuery) loadParent(ctx context.Context, query *LocationQuery, nodes []*Location, init func(*Location), assign func(*Location, *Location)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Location)
@ -602,38 +634,6 @@ func (lq *LocationQuery) loadChildren(ctx context.Context, query *LocationQuery,
}
return nil
}
func (lq *LocationQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Location, init func(*Location), assign func(*Location, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Location)
for i := range nodes {
if nodes[i].group_locations == nil {
continue
}
fk := *nodes[i].group_locations
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(group.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 "group_locations" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (lq *LocationQuery) loadItems(ctx context.Context, query *ItemQuery, nodes []*Location, init func(*Location), assign func(*Location, *Item)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Location)

View file

@ -63,6 +63,17 @@ func (lu *LocationUpdate) ClearDescription() *LocationUpdate {
return lu
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (lu *LocationUpdate) SetGroupID(id uuid.UUID) *LocationUpdate {
lu.mutation.SetGroupID(id)
return lu
}
// SetGroup sets the "group" edge to the Group entity.
func (lu *LocationUpdate) SetGroup(g *Group) *LocationUpdate {
return lu.SetGroupID(g.ID)
}
// SetParentID sets the "parent" edge to the Location entity by ID.
func (lu *LocationUpdate) SetParentID(id uuid.UUID) *LocationUpdate {
lu.mutation.SetParentID(id)
@ -97,17 +108,6 @@ func (lu *LocationUpdate) AddChildren(l ...*Location) *LocationUpdate {
return lu.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (lu *LocationUpdate) SetGroupID(id uuid.UUID) *LocationUpdate {
lu.mutation.SetGroupID(id)
return lu
}
// SetGroup sets the "group" edge to the Group entity.
func (lu *LocationUpdate) SetGroup(g *Group) *LocationUpdate {
return lu.SetGroupID(g.ID)
}
// AddItemIDs adds the "items" edge to the Item entity by IDs.
func (lu *LocationUpdate) AddItemIDs(ids ...uuid.UUID) *LocationUpdate {
lu.mutation.AddItemIDs(ids...)
@ -128,6 +128,12 @@ func (lu *LocationUpdate) Mutation() *LocationMutation {
return lu.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (lu *LocationUpdate) ClearGroup() *LocationUpdate {
lu.mutation.ClearGroup()
return lu
}
// ClearParent clears the "parent" edge to the Location entity.
func (lu *LocationUpdate) ClearParent() *LocationUpdate {
lu.mutation.ClearParent()
@ -155,12 +161,6 @@ func (lu *LocationUpdate) RemoveChildren(l ...*Location) *LocationUpdate {
return lu.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity.
func (lu *LocationUpdate) ClearGroup() *LocationUpdate {
lu.mutation.ClearGroup()
return lu
}
// ClearItems clears all "items" edges to the Item entity.
func (lu *LocationUpdate) ClearItems() *LocationUpdate {
lu.mutation.ClearItems()
@ -260,6 +260,41 @@ func (lu *LocationUpdate) sqlSave(ctx context.Context) (n int, err error) {
if lu.mutation.DescriptionCleared() {
_spec.ClearField(location.FieldDescription, field.TypeString)
}
if lu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := lu.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if lu.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@ -349,41 +384,6 @@ func (lu *LocationUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if lu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := lu.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if lu.mutation.ItemsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
@ -490,6 +490,17 @@ func (luo *LocationUpdateOne) ClearDescription() *LocationUpdateOne {
return luo
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (luo *LocationUpdateOne) SetGroupID(id uuid.UUID) *LocationUpdateOne {
luo.mutation.SetGroupID(id)
return luo
}
// SetGroup sets the "group" edge to the Group entity.
func (luo *LocationUpdateOne) SetGroup(g *Group) *LocationUpdateOne {
return luo.SetGroupID(g.ID)
}
// SetParentID sets the "parent" edge to the Location entity by ID.
func (luo *LocationUpdateOne) SetParentID(id uuid.UUID) *LocationUpdateOne {
luo.mutation.SetParentID(id)
@ -524,17 +535,6 @@ func (luo *LocationUpdateOne) AddChildren(l ...*Location) *LocationUpdateOne {
return luo.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (luo *LocationUpdateOne) SetGroupID(id uuid.UUID) *LocationUpdateOne {
luo.mutation.SetGroupID(id)
return luo
}
// SetGroup sets the "group" edge to the Group entity.
func (luo *LocationUpdateOne) SetGroup(g *Group) *LocationUpdateOne {
return luo.SetGroupID(g.ID)
}
// AddItemIDs adds the "items" edge to the Item entity by IDs.
func (luo *LocationUpdateOne) AddItemIDs(ids ...uuid.UUID) *LocationUpdateOne {
luo.mutation.AddItemIDs(ids...)
@ -555,6 +555,12 @@ func (luo *LocationUpdateOne) Mutation() *LocationMutation {
return luo.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (luo *LocationUpdateOne) ClearGroup() *LocationUpdateOne {
luo.mutation.ClearGroup()
return luo
}
// ClearParent clears the "parent" edge to the Location entity.
func (luo *LocationUpdateOne) ClearParent() *LocationUpdateOne {
luo.mutation.ClearParent()
@ -582,12 +588,6 @@ func (luo *LocationUpdateOne) RemoveChildren(l ...*Location) *LocationUpdateOne
return luo.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity.
func (luo *LocationUpdateOne) ClearGroup() *LocationUpdateOne {
luo.mutation.ClearGroup()
return luo
}
// ClearItems clears all "items" edges to the Item entity.
func (luo *LocationUpdateOne) ClearItems() *LocationUpdateOne {
luo.mutation.ClearItems()
@ -717,6 +717,41 @@ func (luo *LocationUpdateOne) sqlSave(ctx context.Context) (_node *Location, err
if luo.mutation.DescriptionCleared() {
_spec.ClearField(location.FieldDescription, field.TypeString)
}
if luo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := luo.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if luo.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@ -806,41 +841,6 @@ func (luo *LocationUpdateOne) sqlSave(ctx context.Context) (_node *Location, err
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if luo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := luo.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.GroupTable,
Columns: []string{location.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if luo.mutation.ItemsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,

View file

@ -344,6 +344,59 @@ var (
},
},
}
// NotifiersColumns holds the columns for the "notifiers" table.
NotifiersColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
{Name: "name", Type: field.TypeString, Size: 255},
{Name: "url", Type: field.TypeString, Size: 2083},
{Name: "is_active", Type: field.TypeBool, Default: true},
{Name: "group_id", Type: field.TypeUUID},
{Name: "user_id", Type: field.TypeUUID},
}
// NotifiersTable holds the schema information for the "notifiers" table.
NotifiersTable = &schema.Table{
Name: "notifiers",
Columns: NotifiersColumns,
PrimaryKey: []*schema.Column{NotifiersColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "notifiers_groups_notifiers",
Columns: []*schema.Column{NotifiersColumns[6]},
RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.Cascade,
},
{
Symbol: "notifiers_users_notifiers",
Columns: []*schema.Column{NotifiersColumns[7]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.Cascade,
},
},
Indexes: []*schema.Index{
{
Name: "notifier_user_id",
Unique: false,
Columns: []*schema.Column{NotifiersColumns[7]},
},
{
Name: "notifier_user_id_is_active",
Unique: false,
Columns: []*schema.Column{NotifiersColumns[7], NotifiersColumns[5]},
},
{
Name: "notifier_group_id",
Unique: false,
Columns: []*schema.Column{NotifiersColumns[6]},
},
{
Name: "notifier_group_id_is_active",
Unique: false,
Columns: []*schema.Column{NotifiersColumns[6], NotifiersColumns[5]},
},
},
}
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
@ -353,8 +406,8 @@ var (
{Name: "email", Type: field.TypeString, Unique: true, Size: 255},
{Name: "password", Type: field.TypeString, Size: 255},
{Name: "is_superuser", Type: field.TypeBool, Default: false},
{Name: "role", Type: field.TypeEnum, Enums: []string{"user", "owner"}, Default: "user"},
{Name: "superuser", Type: field.TypeBool, Default: false},
{Name: "role", Type: field.TypeEnum, Enums: []string{"user", "owner"}, Default: "user"},
{Name: "activated_on", Type: field.TypeTime, Nullable: true},
{Name: "group_users", Type: field.TypeUUID},
}
@ -410,6 +463,7 @@ var (
LabelsTable,
LocationsTable,
MaintenanceEntriesTable,
NotifiersTable,
UsersTable,
LabelItemsTable,
}
@ -430,6 +484,8 @@ func init() {
LocationsTable.ForeignKeys[0].RefTable = GroupsTable
LocationsTable.ForeignKeys[1].RefTable = LocationsTable
MaintenanceEntriesTable.ForeignKeys[0].RefTable = ItemsTable
NotifiersTable.ForeignKeys[0].RefTable = GroupsTable
NotifiersTable.ForeignKeys[1].RefTable = UsersTable
UsersTable.ForeignKeys[0].RefTable = GroupsTable
LabelItemsTable.ForeignKeys[0].RefTable = LabelsTable
LabelItemsTable.ForeignKeys[1].RefTable = ItemsTable

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,216 @@
// 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/homebox/backend/internal/data/ent/group"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
// Notifier is the model entity for the Notifier schema.
type Notifier 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"`
// GroupID holds the value of the "group_id" field.
GroupID uuid.UUID `json:"group_id,omitempty"`
// UserID holds the value of the "user_id" field.
UserID uuid.UUID `json:"user_id,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// URL holds the value of the "url" field.
URL string `json:"-"`
// IsActive holds the value of the "is_active" field.
IsActive bool `json:"is_active,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the NotifierQuery when eager-loading is set.
Edges NotifierEdges `json:"edges"`
}
// NotifierEdges holds the relations/edges for other nodes in the graph.
type NotifierEdges struct {
// Group holds the value of the group edge.
Group *Group `json:"group,omitempty"`
// User holds the value of the user edge.
User *User `json:"user,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [2]bool
}
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e NotifierEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[0] {
if e.Group == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label}
}
return e.Group, nil
}
return nil, &NotLoadedError{edge: "group"}
}
// UserOrErr returns the User value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e NotifierEdges) UserOrErr() (*User, error) {
if e.loadedTypes[1] {
if e.User == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: user.Label}
}
return e.User, nil
}
return nil, &NotLoadedError{edge: "user"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*Notifier) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case notifier.FieldIsActive:
values[i] = new(sql.NullBool)
case notifier.FieldName, notifier.FieldURL:
values[i] = new(sql.NullString)
case notifier.FieldCreatedAt, notifier.FieldUpdatedAt:
values[i] = new(sql.NullTime)
case notifier.FieldID, notifier.FieldGroupID, notifier.FieldUserID:
values[i] = new(uuid.UUID)
default:
return nil, fmt.Errorf("unexpected column %q for type Notifier", columns[i])
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the Notifier fields.
func (n *Notifier) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case notifier.FieldID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field id", values[i])
} else if value != nil {
n.ID = *value
}
case notifier.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 {
n.CreatedAt = value.Time
}
case notifier.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 {
n.UpdatedAt = value.Time
}
case notifier.FieldGroupID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field group_id", values[i])
} else if value != nil {
n.GroupID = *value
}
case notifier.FieldUserID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field user_id", values[i])
} else if value != nil {
n.UserID = *value
}
case notifier.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
n.Name = value.String
}
case notifier.FieldURL:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field url", values[i])
} else if value.Valid {
n.URL = value.String
}
case notifier.FieldIsActive:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field is_active", values[i])
} else if value.Valid {
n.IsActive = value.Bool
}
}
}
return nil
}
// QueryGroup queries the "group" edge of the Notifier entity.
func (n *Notifier) QueryGroup() *GroupQuery {
return NewNotifierClient(n.config).QueryGroup(n)
}
// QueryUser queries the "user" edge of the Notifier entity.
func (n *Notifier) QueryUser() *UserQuery {
return NewNotifierClient(n.config).QueryUser(n)
}
// Update returns a builder for updating this Notifier.
// Note that you need to call Notifier.Unwrap() before calling this method if this Notifier
// was returned from a transaction, and the transaction was committed or rolled back.
func (n *Notifier) Update() *NotifierUpdateOne {
return NewNotifierClient(n.config).UpdateOne(n)
}
// Unwrap unwraps the Notifier 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 (n *Notifier) Unwrap() *Notifier {
_tx, ok := n.config.driver.(*txDriver)
if !ok {
panic("ent: Notifier is not a transactional entity")
}
n.config.driver = _tx.drv
return n
}
// String implements the fmt.Stringer.
func (n *Notifier) String() string {
var builder strings.Builder
builder.WriteString("Notifier(")
builder.WriteString(fmt.Sprintf("id=%v, ", n.ID))
builder.WriteString("created_at=")
builder.WriteString(n.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(n.UpdatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("group_id=")
builder.WriteString(fmt.Sprintf("%v", n.GroupID))
builder.WriteString(", ")
builder.WriteString("user_id=")
builder.WriteString(fmt.Sprintf("%v", n.UserID))
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(n.Name)
builder.WriteString(", ")
builder.WriteString("url=<sensitive>")
builder.WriteString(", ")
builder.WriteString("is_active=")
builder.WriteString(fmt.Sprintf("%v", n.IsActive))
builder.WriteByte(')')
return builder.String()
}
// Notifiers is a parsable slice of Notifier.
type Notifiers []*Notifier

View file

@ -0,0 +1,89 @@
// Code generated by ent, DO NOT EDIT.
package notifier
import (
"time"
"github.com/google/uuid"
)
const (
// Label holds the string label denoting the notifier type in the database.
Label = "notifier"
// 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"
// FieldGroupID holds the string denoting the group_id field in the database.
FieldGroupID = "group_id"
// FieldUserID holds the string denoting the user_id field in the database.
FieldUserID = "user_id"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldURL holds the string denoting the url field in the database.
FieldURL = "url"
// FieldIsActive holds the string denoting the is_active field in the database.
FieldIsActive = "is_active"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeUser holds the string denoting the user edge name in mutations.
EdgeUser = "user"
// Table holds the table name of the notifier in the database.
Table = "notifiers"
// GroupTable is the table that holds the group relation/edge.
GroupTable = "notifiers"
// GroupInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_id"
// UserTable is the table that holds the user relation/edge.
UserTable = "notifiers"
// UserInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
UserInverseTable = "users"
// UserColumn is the table column denoting the user relation/edge.
UserColumn = "user_id"
)
// Columns holds all SQL columns for notifier fields.
var Columns = []string{
FieldID,
FieldCreatedAt,
FieldUpdatedAt,
FieldGroupID,
FieldUserID,
FieldName,
FieldURL,
FieldIsActive,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
// NameValidator is a validator for the "name" field. It is called by the builders before save.
NameValidator func(string) error
// URLValidator is a validator for the "url" field. It is called by the builders before save.
URLValidator func(string) error
// DefaultIsActive holds the default value on creation for the "is_active" field.
DefaultIsActive bool
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() uuid.UUID
)

View file

@ -0,0 +1,438 @@
// Code generated by ent, DO NOT EDIT.
package notifier
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldLTE(FieldID, id))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldCreatedAt, v))
}
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
func UpdatedAt(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldUpdatedAt, v))
}
// GroupID applies equality check predicate on the "group_id" field. It's identical to GroupIDEQ.
func GroupID(v uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldGroupID, v))
}
// UserID applies equality check predicate on the "user_id" field. It's identical to UserIDEQ.
func UserID(v uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldUserID, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldName, v))
}
// URL applies equality check predicate on the "url" field. It's identical to URLEQ.
func URL(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldURL, v))
}
// IsActive applies equality check predicate on the "is_active" field. It's identical to IsActiveEQ.
func IsActive(v bool) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldIsActive, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldLTE(FieldCreatedAt, v))
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldUpdatedAt, v))
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldUpdatedAt, v))
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldIn(FieldUpdatedAt, vs...))
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldNotIn(FieldUpdatedAt, vs...))
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldGT(FieldUpdatedAt, v))
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldGTE(FieldUpdatedAt, v))
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldLT(FieldUpdatedAt, v))
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.Notifier {
return predicate.Notifier(sql.FieldLTE(FieldUpdatedAt, v))
}
// GroupIDEQ applies the EQ predicate on the "group_id" field.
func GroupIDEQ(v uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldGroupID, v))
}
// GroupIDNEQ applies the NEQ predicate on the "group_id" field.
func GroupIDNEQ(v uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldGroupID, v))
}
// GroupIDIn applies the In predicate on the "group_id" field.
func GroupIDIn(vs ...uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldIn(FieldGroupID, vs...))
}
// GroupIDNotIn applies the NotIn predicate on the "group_id" field.
func GroupIDNotIn(vs ...uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldNotIn(FieldGroupID, vs...))
}
// UserIDEQ applies the EQ predicate on the "user_id" field.
func UserIDEQ(v uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldUserID, v))
}
// UserIDNEQ applies the NEQ predicate on the "user_id" field.
func UserIDNEQ(v uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldUserID, v))
}
// UserIDIn applies the In predicate on the "user_id" field.
func UserIDIn(vs ...uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldIn(FieldUserID, vs...))
}
// UserIDNotIn applies the NotIn predicate on the "user_id" field.
func UserIDNotIn(vs ...uuid.UUID) predicate.Notifier {
return predicate.Notifier(sql.FieldNotIn(FieldUserID, vs...))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldName, v))
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldName, v))
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.Notifier {
return predicate.Notifier(sql.FieldIn(FieldName, vs...))
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.Notifier {
return predicate.Notifier(sql.FieldNotIn(FieldName, vs...))
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldGT(FieldName, v))
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldGTE(FieldName, v))
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldLT(FieldName, v))
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldLTE(FieldName, v))
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldContains(FieldName, v))
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldHasPrefix(FieldName, v))
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldHasSuffix(FieldName, v))
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldEqualFold(FieldName, v))
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldContainsFold(FieldName, v))
}
// URLEQ applies the EQ predicate on the "url" field.
func URLEQ(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldURL, v))
}
// URLNEQ applies the NEQ predicate on the "url" field.
func URLNEQ(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldURL, v))
}
// URLIn applies the In predicate on the "url" field.
func URLIn(vs ...string) predicate.Notifier {
return predicate.Notifier(sql.FieldIn(FieldURL, vs...))
}
// URLNotIn applies the NotIn predicate on the "url" field.
func URLNotIn(vs ...string) predicate.Notifier {
return predicate.Notifier(sql.FieldNotIn(FieldURL, vs...))
}
// URLGT applies the GT predicate on the "url" field.
func URLGT(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldGT(FieldURL, v))
}
// URLGTE applies the GTE predicate on the "url" field.
func URLGTE(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldGTE(FieldURL, v))
}
// URLLT applies the LT predicate on the "url" field.
func URLLT(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldLT(FieldURL, v))
}
// URLLTE applies the LTE predicate on the "url" field.
func URLLTE(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldLTE(FieldURL, v))
}
// URLContains applies the Contains predicate on the "url" field.
func URLContains(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldContains(FieldURL, v))
}
// URLHasPrefix applies the HasPrefix predicate on the "url" field.
func URLHasPrefix(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldHasPrefix(FieldURL, v))
}
// URLHasSuffix applies the HasSuffix predicate on the "url" field.
func URLHasSuffix(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldHasSuffix(FieldURL, v))
}
// URLEqualFold applies the EqualFold predicate on the "url" field.
func URLEqualFold(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldEqualFold(FieldURL, v))
}
// URLContainsFold applies the ContainsFold predicate on the "url" field.
func URLContainsFold(v string) predicate.Notifier {
return predicate.Notifier(sql.FieldContainsFold(FieldURL, v))
}
// IsActiveEQ applies the EQ predicate on the "is_active" field.
func IsActiveEQ(v bool) predicate.Notifier {
return predicate.Notifier(sql.FieldEQ(FieldIsActive, v))
}
// IsActiveNEQ applies the NEQ predicate on the "is_active" field.
func IsActiveNEQ(v bool) predicate.Notifier {
return predicate.Notifier(sql.FieldNEQ(FieldIsActive, v))
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Notifier {
return predicate.Notifier(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.Notifier {
return predicate.Notifier(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasUser applies the HasEdge predicate on the "user" edge.
func HasUser() predicate.Notifier {
return predicate.Notifier(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
func HasUserWith(preds ...predicate.User) predicate.Notifier {
return predicate.Notifier(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(UserInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, UserTable, UserColumn),
)
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.Notifier) predicate.Notifier {
return predicate.Notifier(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.Notifier) predicate.Notifier {
return predicate.Notifier(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.Notifier) predicate.Notifier {
return predicate.Notifier(func(s *sql.Selector) {
p(s.Not())
})
}

View file

@ -0,0 +1,384 @@
// 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/homebox/backend/internal/data/ent/group"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
// NotifierCreate is the builder for creating a Notifier entity.
type NotifierCreate struct {
config
mutation *NotifierMutation
hooks []Hook
}
// SetCreatedAt sets the "created_at" field.
func (nc *NotifierCreate) SetCreatedAt(t time.Time) *NotifierCreate {
nc.mutation.SetCreatedAt(t)
return nc
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (nc *NotifierCreate) SetNillableCreatedAt(t *time.Time) *NotifierCreate {
if t != nil {
nc.SetCreatedAt(*t)
}
return nc
}
// SetUpdatedAt sets the "updated_at" field.
func (nc *NotifierCreate) SetUpdatedAt(t time.Time) *NotifierCreate {
nc.mutation.SetUpdatedAt(t)
return nc
}
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
func (nc *NotifierCreate) SetNillableUpdatedAt(t *time.Time) *NotifierCreate {
if t != nil {
nc.SetUpdatedAt(*t)
}
return nc
}
// SetGroupID sets the "group_id" field.
func (nc *NotifierCreate) SetGroupID(u uuid.UUID) *NotifierCreate {
nc.mutation.SetGroupID(u)
return nc
}
// SetUserID sets the "user_id" field.
func (nc *NotifierCreate) SetUserID(u uuid.UUID) *NotifierCreate {
nc.mutation.SetUserID(u)
return nc
}
// SetName sets the "name" field.
func (nc *NotifierCreate) SetName(s string) *NotifierCreate {
nc.mutation.SetName(s)
return nc
}
// SetURL sets the "url" field.
func (nc *NotifierCreate) SetURL(s string) *NotifierCreate {
nc.mutation.SetURL(s)
return nc
}
// SetIsActive sets the "is_active" field.
func (nc *NotifierCreate) SetIsActive(b bool) *NotifierCreate {
nc.mutation.SetIsActive(b)
return nc
}
// SetNillableIsActive sets the "is_active" field if the given value is not nil.
func (nc *NotifierCreate) SetNillableIsActive(b *bool) *NotifierCreate {
if b != nil {
nc.SetIsActive(*b)
}
return nc
}
// SetID sets the "id" field.
func (nc *NotifierCreate) SetID(u uuid.UUID) *NotifierCreate {
nc.mutation.SetID(u)
return nc
}
// SetNillableID sets the "id" field if the given value is not nil.
func (nc *NotifierCreate) SetNillableID(u *uuid.UUID) *NotifierCreate {
if u != nil {
nc.SetID(*u)
}
return nc
}
// SetGroup sets the "group" edge to the Group entity.
func (nc *NotifierCreate) SetGroup(g *Group) *NotifierCreate {
return nc.SetGroupID(g.ID)
}
// SetUser sets the "user" edge to the User entity.
func (nc *NotifierCreate) SetUser(u *User) *NotifierCreate {
return nc.SetUserID(u.ID)
}
// Mutation returns the NotifierMutation object of the builder.
func (nc *NotifierCreate) Mutation() *NotifierMutation {
return nc.mutation
}
// Save creates the Notifier in the database.
func (nc *NotifierCreate) Save(ctx context.Context) (*Notifier, error) {
nc.defaults()
return withHooks[*Notifier, NotifierMutation](ctx, nc.sqlSave, nc.mutation, nc.hooks)
}
// SaveX calls Save and panics if Save returns an error.
func (nc *NotifierCreate) SaveX(ctx context.Context) *Notifier {
v, err := nc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (nc *NotifierCreate) Exec(ctx context.Context) error {
_, err := nc.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (nc *NotifierCreate) ExecX(ctx context.Context) {
if err := nc.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (nc *NotifierCreate) defaults() {
if _, ok := nc.mutation.CreatedAt(); !ok {
v := notifier.DefaultCreatedAt()
nc.mutation.SetCreatedAt(v)
}
if _, ok := nc.mutation.UpdatedAt(); !ok {
v := notifier.DefaultUpdatedAt()
nc.mutation.SetUpdatedAt(v)
}
if _, ok := nc.mutation.IsActive(); !ok {
v := notifier.DefaultIsActive
nc.mutation.SetIsActive(v)
}
if _, ok := nc.mutation.ID(); !ok {
v := notifier.DefaultID()
nc.mutation.SetID(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (nc *NotifierCreate) check() error {
if _, ok := nc.mutation.CreatedAt(); !ok {
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Notifier.created_at"`)}
}
if _, ok := nc.mutation.UpdatedAt(); !ok {
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Notifier.updated_at"`)}
}
if _, ok := nc.mutation.GroupID(); !ok {
return &ValidationError{Name: "group_id", err: errors.New(`ent: missing required field "Notifier.group_id"`)}
}
if _, ok := nc.mutation.UserID(); !ok {
return &ValidationError{Name: "user_id", err: errors.New(`ent: missing required field "Notifier.user_id"`)}
}
if _, ok := nc.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Notifier.name"`)}
}
if v, ok := nc.mutation.Name(); ok {
if err := notifier.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Notifier.name": %w`, err)}
}
}
if _, ok := nc.mutation.URL(); !ok {
return &ValidationError{Name: "url", err: errors.New(`ent: missing required field "Notifier.url"`)}
}
if v, ok := nc.mutation.URL(); ok {
if err := notifier.URLValidator(v); err != nil {
return &ValidationError{Name: "url", err: fmt.Errorf(`ent: validator failed for field "Notifier.url": %w`, err)}
}
}
if _, ok := nc.mutation.IsActive(); !ok {
return &ValidationError{Name: "is_active", err: errors.New(`ent: missing required field "Notifier.is_active"`)}
}
if _, ok := nc.mutation.GroupID(); !ok {
return &ValidationError{Name: "group", err: errors.New(`ent: missing required edge "Notifier.group"`)}
}
if _, ok := nc.mutation.UserID(); !ok {
return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "Notifier.user"`)}
}
return nil
}
func (nc *NotifierCreate) sqlSave(ctx context.Context) (*Notifier, error) {
if err := nc.check(); err != nil {
return nil, err
}
_node, _spec := nc.createSpec()
if err := sqlgraph.CreateNode(ctx, nc.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
}
}
nc.mutation.id = &_node.ID
nc.mutation.done = true
return _node, nil
}
func (nc *NotifierCreate) createSpec() (*Notifier, *sqlgraph.CreateSpec) {
var (
_node = &Notifier{config: nc.config}
_spec = sqlgraph.NewCreateSpec(notifier.Table, sqlgraph.NewFieldSpec(notifier.FieldID, field.TypeUUID))
)
if id, ok := nc.mutation.ID(); ok {
_node.ID = id
_spec.ID.Value = &id
}
if value, ok := nc.mutation.CreatedAt(); ok {
_spec.SetField(notifier.FieldCreatedAt, field.TypeTime, value)
_node.CreatedAt = value
}
if value, ok := nc.mutation.UpdatedAt(); ok {
_spec.SetField(notifier.FieldUpdatedAt, field.TypeTime, value)
_node.UpdatedAt = value
}
if value, ok := nc.mutation.Name(); ok {
_spec.SetField(notifier.FieldName, field.TypeString, value)
_node.Name = value
}
if value, ok := nc.mutation.URL(); ok {
_spec.SetField(notifier.FieldURL, field.TypeString, value)
_node.URL = value
}
if value, ok := nc.mutation.IsActive(); ok {
_spec.SetField(notifier.FieldIsActive, field.TypeBool, value)
_node.IsActive = value
}
if nodes := nc.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.GroupTable,
Columns: []string{notifier.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.GroupID = nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := nc.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.UserTable,
Columns: []string{notifier.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: user.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.UserID = nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}
// NotifierCreateBulk is the builder for creating many Notifier entities in bulk.
type NotifierCreateBulk struct {
config
builders []*NotifierCreate
}
// Save creates the Notifier entities in the database.
func (ncb *NotifierCreateBulk) Save(ctx context.Context) ([]*Notifier, error) {
specs := make([]*sqlgraph.CreateSpec, len(ncb.builders))
nodes := make([]*Notifier, len(ncb.builders))
mutators := make([]Mutator, len(ncb.builders))
for i := range ncb.builders {
func(i int, root context.Context) {
builder := ncb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*NotifierMutation)
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, ncb.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, ncb.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, ncb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX is like Save, but panics if an error occurs.
func (ncb *NotifierCreateBulk) SaveX(ctx context.Context) []*Notifier {
v, err := ncb.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (ncb *NotifierCreateBulk) Exec(ctx context.Context) error {
_, err := ncb.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (ncb *NotifierCreateBulk) ExecX(ctx context.Context) {
if err := ncb.Exec(ctx); err != nil {
panic(err)
}
}

View file

@ -0,0 +1,88 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
)
// NotifierDelete is the builder for deleting a Notifier entity.
type NotifierDelete struct {
config
hooks []Hook
mutation *NotifierMutation
}
// Where appends a list predicates to the NotifierDelete builder.
func (nd *NotifierDelete) Where(ps ...predicate.Notifier) *NotifierDelete {
nd.mutation.Where(ps...)
return nd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (nd *NotifierDelete) Exec(ctx context.Context) (int, error) {
return withHooks[int, NotifierMutation](ctx, nd.sqlExec, nd.mutation, nd.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (nd *NotifierDelete) ExecX(ctx context.Context) int {
n, err := nd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (nd *NotifierDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(notifier.Table, sqlgraph.NewFieldSpec(notifier.FieldID, field.TypeUUID))
if ps := nd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, nd.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
nd.mutation.done = true
return affected, err
}
// NotifierDeleteOne is the builder for deleting a single Notifier entity.
type NotifierDeleteOne struct {
nd *NotifierDelete
}
// Where appends a list predicates to the NotifierDelete builder.
func (ndo *NotifierDeleteOne) Where(ps ...predicate.Notifier) *NotifierDeleteOne {
ndo.nd.mutation.Where(ps...)
return ndo
}
// Exec executes the deletion query.
func (ndo *NotifierDeleteOne) Exec(ctx context.Context) error {
n, err := ndo.nd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{notifier.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (ndo *NotifierDeleteOne) ExecX(ctx context.Context) {
if err := ndo.Exec(ctx); err != nil {
panic(err)
}
}

View file

@ -0,0 +1,675 @@
// 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/homebox/backend/internal/data/ent/group"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
// NotifierQuery is the builder for querying Notifier entities.
type NotifierQuery struct {
config
ctx *QueryContext
order []OrderFunc
inters []Interceptor
predicates []predicate.Notifier
withGroup *GroupQuery
withUser *UserQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the NotifierQuery builder.
func (nq *NotifierQuery) Where(ps ...predicate.Notifier) *NotifierQuery {
nq.predicates = append(nq.predicates, ps...)
return nq
}
// Limit the number of records to be returned by this query.
func (nq *NotifierQuery) Limit(limit int) *NotifierQuery {
nq.ctx.Limit = &limit
return nq
}
// Offset to start from.
func (nq *NotifierQuery) Offset(offset int) *NotifierQuery {
nq.ctx.Offset = &offset
return nq
}
// 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 (nq *NotifierQuery) Unique(unique bool) *NotifierQuery {
nq.ctx.Unique = &unique
return nq
}
// Order specifies how the records should be ordered.
func (nq *NotifierQuery) Order(o ...OrderFunc) *NotifierQuery {
nq.order = append(nq.order, o...)
return nq
}
// QueryGroup chains the current query on the "group" edge.
func (nq *NotifierQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: nq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := nq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := nq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(notifier.Table, notifier.FieldID, selector),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, notifier.GroupTable, notifier.GroupColumn),
)
fromU = sqlgraph.SetNeighbors(nq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryUser chains the current query on the "user" edge.
func (nq *NotifierQuery) QueryUser() *UserQuery {
query := (&UserClient{config: nq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := nq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := nq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(notifier.Table, notifier.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, notifier.UserTable, notifier.UserColumn),
)
fromU = sqlgraph.SetNeighbors(nq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first Notifier entity from the query.
// Returns a *NotFoundError when no Notifier was found.
func (nq *NotifierQuery) First(ctx context.Context) (*Notifier, error) {
nodes, err := nq.Limit(1).All(setContextOp(ctx, nq.ctx, "First"))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{notifier.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (nq *NotifierQuery) FirstX(ctx context.Context) *Notifier {
node, err := nq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first Notifier ID from the query.
// Returns a *NotFoundError when no Notifier ID was found.
func (nq *NotifierQuery) FirstID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = nq.Limit(1).IDs(setContextOp(ctx, nq.ctx, "FirstID")); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{notifier.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (nq *NotifierQuery) FirstIDX(ctx context.Context) uuid.UUID {
id, err := nq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single Notifier entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one Notifier entity is found.
// Returns a *NotFoundError when no Notifier entities are found.
func (nq *NotifierQuery) Only(ctx context.Context) (*Notifier, error) {
nodes, err := nq.Limit(2).All(setContextOp(ctx, nq.ctx, "Only"))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{notifier.Label}
default:
return nil, &NotSingularError{notifier.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (nq *NotifierQuery) OnlyX(ctx context.Context) *Notifier {
node, err := nq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only Notifier ID in the query.
// Returns a *NotSingularError when more than one Notifier ID is found.
// Returns a *NotFoundError when no entities are found.
func (nq *NotifierQuery) OnlyID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = nq.Limit(2).IDs(setContextOp(ctx, nq.ctx, "OnlyID")); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{notifier.Label}
default:
err = &NotSingularError{notifier.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (nq *NotifierQuery) OnlyIDX(ctx context.Context) uuid.UUID {
id, err := nq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of Notifiers.
func (nq *NotifierQuery) All(ctx context.Context) ([]*Notifier, error) {
ctx = setContextOp(ctx, nq.ctx, "All")
if err := nq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*Notifier, *NotifierQuery]()
return withInterceptors[[]*Notifier](ctx, nq, qr, nq.inters)
}
// AllX is like All, but panics if an error occurs.
func (nq *NotifierQuery) AllX(ctx context.Context) []*Notifier {
nodes, err := nq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of Notifier IDs.
func (nq *NotifierQuery) IDs(ctx context.Context) (ids []uuid.UUID, err error) {
if nq.ctx.Unique == nil && nq.path != nil {
nq.Unique(true)
}
ctx = setContextOp(ctx, nq.ctx, "IDs")
if err = nq.Select(notifier.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (nq *NotifierQuery) IDsX(ctx context.Context) []uuid.UUID {
ids, err := nq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (nq *NotifierQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, nq.ctx, "Count")
if err := nq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, nq, querierCount[*NotifierQuery](), nq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (nq *NotifierQuery) CountX(ctx context.Context) int {
count, err := nq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (nq *NotifierQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, nq.ctx, "Exist")
switch _, err := nq.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (nq *NotifierQuery) ExistX(ctx context.Context) bool {
exist, err := nq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the NotifierQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (nq *NotifierQuery) Clone() *NotifierQuery {
if nq == nil {
return nil
}
return &NotifierQuery{
config: nq.config,
ctx: nq.ctx.Clone(),
order: append([]OrderFunc{}, nq.order...),
inters: append([]Interceptor{}, nq.inters...),
predicates: append([]predicate.Notifier{}, nq.predicates...),
withGroup: nq.withGroup.Clone(),
withUser: nq.withUser.Clone(),
// clone intermediate query.
sql: nq.sql.Clone(),
path: nq.path,
}
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (nq *NotifierQuery) WithGroup(opts ...func(*GroupQuery)) *NotifierQuery {
query := (&GroupClient{config: nq.config}).Query()
for _, opt := range opts {
opt(query)
}
nq.withGroup = query
return nq
}
// WithUser tells the query-builder to eager-load the nodes that are connected to
// the "user" edge. The optional arguments are used to configure the query builder of the edge.
func (nq *NotifierQuery) WithUser(opts ...func(*UserQuery)) *NotifierQuery {
query := (&UserClient{config: nq.config}).Query()
for _, opt := range opts {
opt(query)
}
nq.withUser = query
return nq
}
// 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.Notifier.Query().
// GroupBy(notifier.FieldCreatedAt).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (nq *NotifierQuery) GroupBy(field string, fields ...string) *NotifierGroupBy {
nq.ctx.Fields = append([]string{field}, fields...)
grbuild := &NotifierGroupBy{build: nq}
grbuild.flds = &nq.ctx.Fields
grbuild.label = notifier.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// CreatedAt time.Time `json:"created_at,omitempty"`
// }
//
// client.Notifier.Query().
// Select(notifier.FieldCreatedAt).
// Scan(ctx, &v)
func (nq *NotifierQuery) Select(fields ...string) *NotifierSelect {
nq.ctx.Fields = append(nq.ctx.Fields, fields...)
sbuild := &NotifierSelect{NotifierQuery: nq}
sbuild.label = notifier.Label
sbuild.flds, sbuild.scan = &nq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a NotifierSelect configured with the given aggregations.
func (nq *NotifierQuery) Aggregate(fns ...AggregateFunc) *NotifierSelect {
return nq.Select().Aggregate(fns...)
}
func (nq *NotifierQuery) prepareQuery(ctx context.Context) error {
for _, inter := range nq.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, nq); err != nil {
return err
}
}
}
for _, f := range nq.ctx.Fields {
if !notifier.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if nq.path != nil {
prev, err := nq.path(ctx)
if err != nil {
return err
}
nq.sql = prev
}
return nil
}
func (nq *NotifierQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Notifier, error) {
var (
nodes = []*Notifier{}
_spec = nq.querySpec()
loadedTypes = [2]bool{
nq.withGroup != nil,
nq.withUser != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*Notifier).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &Notifier{config: nq.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, nq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := nq.withGroup; query != nil {
if err := nq.loadGroup(ctx, query, nodes, nil,
func(n *Notifier, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
if query := nq.withUser; query != nil {
if err := nq.loadUser(ctx, query, nodes, nil,
func(n *Notifier, e *User) { n.Edges.User = e }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (nq *NotifierQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Notifier, init func(*Notifier), assign func(*Notifier, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Notifier)
for i := range nodes {
fk := nodes[i].GroupID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(group.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 "group_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (nq *NotifierQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*Notifier, init func(*Notifier), assign func(*Notifier, *User)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Notifier)
for i := range nodes {
fk := nodes[i].UserID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(user.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 "user_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (nq *NotifierQuery) sqlCount(ctx context.Context) (int, error) {
_spec := nq.querySpec()
_spec.Node.Columns = nq.ctx.Fields
if len(nq.ctx.Fields) > 0 {
_spec.Unique = nq.ctx.Unique != nil && *nq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, nq.driver, _spec)
}
func (nq *NotifierQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(notifier.Table, notifier.Columns, sqlgraph.NewFieldSpec(notifier.FieldID, field.TypeUUID))
_spec.From = nq.sql
if unique := nq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if nq.path != nil {
_spec.Unique = true
}
if fields := nq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, notifier.FieldID)
for i := range fields {
if fields[i] != notifier.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := nq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := nq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := nq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := nq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (nq *NotifierQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(nq.driver.Dialect())
t1 := builder.Table(notifier.Table)
columns := nq.ctx.Fields
if len(columns) == 0 {
columns = notifier.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if nq.sql != nil {
selector = nq.sql
selector.Select(selector.Columns(columns...)...)
}
if nq.ctx.Unique != nil && *nq.ctx.Unique {
selector.Distinct()
}
for _, p := range nq.predicates {
p(selector)
}
for _, p := range nq.order {
p(selector)
}
if offset := nq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := nq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// NotifierGroupBy is the group-by builder for Notifier entities.
type NotifierGroupBy struct {
selector
build *NotifierQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (ngb *NotifierGroupBy) Aggregate(fns ...AggregateFunc) *NotifierGroupBy {
ngb.fns = append(ngb.fns, fns...)
return ngb
}
// Scan applies the selector query and scans the result into the given value.
func (ngb *NotifierGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ngb.build.ctx, "GroupBy")
if err := ngb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*NotifierQuery, *NotifierGroupBy](ctx, ngb.build, ngb, ngb.build.inters, v)
}
func (ngb *NotifierGroupBy) sqlScan(ctx context.Context, root *NotifierQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(ngb.fns))
for _, fn := range ngb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*ngb.flds)+len(ngb.fns))
for _, f := range *ngb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*ngb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := ngb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// NotifierSelect is the builder for selecting fields of Notifier entities.
type NotifierSelect struct {
*NotifierQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (ns *NotifierSelect) Aggregate(fns ...AggregateFunc) *NotifierSelect {
ns.fns = append(ns.fns, fns...)
return ns
}
// Scan applies the selector query and scans the result into the given value.
func (ns *NotifierSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ns.ctx, "Select")
if err := ns.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*NotifierQuery, *NotifierSelect](ctx, ns.NotifierQuery, ns, ns.inters, v)
}
func (ns *NotifierSelect) sqlScan(ctx context.Context, root *NotifierQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(ns.fns))
for _, fn := range ns.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*ns.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := ns.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View file

@ -0,0 +1,541 @@
// 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/homebox/backend/internal/data/ent/group"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
// NotifierUpdate is the builder for updating Notifier entities.
type NotifierUpdate struct {
config
hooks []Hook
mutation *NotifierMutation
}
// Where appends a list predicates to the NotifierUpdate builder.
func (nu *NotifierUpdate) Where(ps ...predicate.Notifier) *NotifierUpdate {
nu.mutation.Where(ps...)
return nu
}
// SetUpdatedAt sets the "updated_at" field.
func (nu *NotifierUpdate) SetUpdatedAt(t time.Time) *NotifierUpdate {
nu.mutation.SetUpdatedAt(t)
return nu
}
// SetGroupID sets the "group_id" field.
func (nu *NotifierUpdate) SetGroupID(u uuid.UUID) *NotifierUpdate {
nu.mutation.SetGroupID(u)
return nu
}
// SetUserID sets the "user_id" field.
func (nu *NotifierUpdate) SetUserID(u uuid.UUID) *NotifierUpdate {
nu.mutation.SetUserID(u)
return nu
}
// SetName sets the "name" field.
func (nu *NotifierUpdate) SetName(s string) *NotifierUpdate {
nu.mutation.SetName(s)
return nu
}
// SetURL sets the "url" field.
func (nu *NotifierUpdate) SetURL(s string) *NotifierUpdate {
nu.mutation.SetURL(s)
return nu
}
// SetIsActive sets the "is_active" field.
func (nu *NotifierUpdate) SetIsActive(b bool) *NotifierUpdate {
nu.mutation.SetIsActive(b)
return nu
}
// SetNillableIsActive sets the "is_active" field if the given value is not nil.
func (nu *NotifierUpdate) SetNillableIsActive(b *bool) *NotifierUpdate {
if b != nil {
nu.SetIsActive(*b)
}
return nu
}
// SetGroup sets the "group" edge to the Group entity.
func (nu *NotifierUpdate) SetGroup(g *Group) *NotifierUpdate {
return nu.SetGroupID(g.ID)
}
// SetUser sets the "user" edge to the User entity.
func (nu *NotifierUpdate) SetUser(u *User) *NotifierUpdate {
return nu.SetUserID(u.ID)
}
// Mutation returns the NotifierMutation object of the builder.
func (nu *NotifierUpdate) Mutation() *NotifierMutation {
return nu.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (nu *NotifierUpdate) ClearGroup() *NotifierUpdate {
nu.mutation.ClearGroup()
return nu
}
// ClearUser clears the "user" edge to the User entity.
func (nu *NotifierUpdate) ClearUser() *NotifierUpdate {
nu.mutation.ClearUser()
return nu
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (nu *NotifierUpdate) Save(ctx context.Context) (int, error) {
nu.defaults()
return withHooks[int, NotifierMutation](ctx, nu.sqlSave, nu.mutation, nu.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (nu *NotifierUpdate) SaveX(ctx context.Context) int {
affected, err := nu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (nu *NotifierUpdate) Exec(ctx context.Context) error {
_, err := nu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (nu *NotifierUpdate) ExecX(ctx context.Context) {
if err := nu.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (nu *NotifierUpdate) defaults() {
if _, ok := nu.mutation.UpdatedAt(); !ok {
v := notifier.UpdateDefaultUpdatedAt()
nu.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (nu *NotifierUpdate) check() error {
if v, ok := nu.mutation.Name(); ok {
if err := notifier.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Notifier.name": %w`, err)}
}
}
if v, ok := nu.mutation.URL(); ok {
if err := notifier.URLValidator(v); err != nil {
return &ValidationError{Name: "url", err: fmt.Errorf(`ent: validator failed for field "Notifier.url": %w`, err)}
}
}
if _, ok := nu.mutation.GroupID(); nu.mutation.GroupCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Notifier.group"`)
}
if _, ok := nu.mutation.UserID(); nu.mutation.UserCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Notifier.user"`)
}
return nil
}
func (nu *NotifierUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := nu.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(notifier.Table, notifier.Columns, sqlgraph.NewFieldSpec(notifier.FieldID, field.TypeUUID))
if ps := nu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := nu.mutation.UpdatedAt(); ok {
_spec.SetField(notifier.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := nu.mutation.Name(); ok {
_spec.SetField(notifier.FieldName, field.TypeString, value)
}
if value, ok := nu.mutation.URL(); ok {
_spec.SetField(notifier.FieldURL, field.TypeString, value)
}
if value, ok := nu.mutation.IsActive(); ok {
_spec.SetField(notifier.FieldIsActive, field.TypeBool, value)
}
if nu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.GroupTable,
Columns: []string{notifier.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := nu.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.GroupTable,
Columns: []string{notifier.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if nu.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.UserTable,
Columns: []string{notifier.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: user.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := nu.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.UserTable,
Columns: []string{notifier.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: user.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, nu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{notifier.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
nu.mutation.done = true
return n, nil
}
// NotifierUpdateOne is the builder for updating a single Notifier entity.
type NotifierUpdateOne struct {
config
fields []string
hooks []Hook
mutation *NotifierMutation
}
// SetUpdatedAt sets the "updated_at" field.
func (nuo *NotifierUpdateOne) SetUpdatedAt(t time.Time) *NotifierUpdateOne {
nuo.mutation.SetUpdatedAt(t)
return nuo
}
// SetGroupID sets the "group_id" field.
func (nuo *NotifierUpdateOne) SetGroupID(u uuid.UUID) *NotifierUpdateOne {
nuo.mutation.SetGroupID(u)
return nuo
}
// SetUserID sets the "user_id" field.
func (nuo *NotifierUpdateOne) SetUserID(u uuid.UUID) *NotifierUpdateOne {
nuo.mutation.SetUserID(u)
return nuo
}
// SetName sets the "name" field.
func (nuo *NotifierUpdateOne) SetName(s string) *NotifierUpdateOne {
nuo.mutation.SetName(s)
return nuo
}
// SetURL sets the "url" field.
func (nuo *NotifierUpdateOne) SetURL(s string) *NotifierUpdateOne {
nuo.mutation.SetURL(s)
return nuo
}
// SetIsActive sets the "is_active" field.
func (nuo *NotifierUpdateOne) SetIsActive(b bool) *NotifierUpdateOne {
nuo.mutation.SetIsActive(b)
return nuo
}
// SetNillableIsActive sets the "is_active" field if the given value is not nil.
func (nuo *NotifierUpdateOne) SetNillableIsActive(b *bool) *NotifierUpdateOne {
if b != nil {
nuo.SetIsActive(*b)
}
return nuo
}
// SetGroup sets the "group" edge to the Group entity.
func (nuo *NotifierUpdateOne) SetGroup(g *Group) *NotifierUpdateOne {
return nuo.SetGroupID(g.ID)
}
// SetUser sets the "user" edge to the User entity.
func (nuo *NotifierUpdateOne) SetUser(u *User) *NotifierUpdateOne {
return nuo.SetUserID(u.ID)
}
// Mutation returns the NotifierMutation object of the builder.
func (nuo *NotifierUpdateOne) Mutation() *NotifierMutation {
return nuo.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (nuo *NotifierUpdateOne) ClearGroup() *NotifierUpdateOne {
nuo.mutation.ClearGroup()
return nuo
}
// ClearUser clears the "user" edge to the User entity.
func (nuo *NotifierUpdateOne) ClearUser() *NotifierUpdateOne {
nuo.mutation.ClearUser()
return nuo
}
// Where appends a list predicates to the NotifierUpdate builder.
func (nuo *NotifierUpdateOne) Where(ps ...predicate.Notifier) *NotifierUpdateOne {
nuo.mutation.Where(ps...)
return nuo
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (nuo *NotifierUpdateOne) Select(field string, fields ...string) *NotifierUpdateOne {
nuo.fields = append([]string{field}, fields...)
return nuo
}
// Save executes the query and returns the updated Notifier entity.
func (nuo *NotifierUpdateOne) Save(ctx context.Context) (*Notifier, error) {
nuo.defaults()
return withHooks[*Notifier, NotifierMutation](ctx, nuo.sqlSave, nuo.mutation, nuo.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (nuo *NotifierUpdateOne) SaveX(ctx context.Context) *Notifier {
node, err := nuo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (nuo *NotifierUpdateOne) Exec(ctx context.Context) error {
_, err := nuo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (nuo *NotifierUpdateOne) ExecX(ctx context.Context) {
if err := nuo.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (nuo *NotifierUpdateOne) defaults() {
if _, ok := nuo.mutation.UpdatedAt(); !ok {
v := notifier.UpdateDefaultUpdatedAt()
nuo.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (nuo *NotifierUpdateOne) check() error {
if v, ok := nuo.mutation.Name(); ok {
if err := notifier.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Notifier.name": %w`, err)}
}
}
if v, ok := nuo.mutation.URL(); ok {
if err := notifier.URLValidator(v); err != nil {
return &ValidationError{Name: "url", err: fmt.Errorf(`ent: validator failed for field "Notifier.url": %w`, err)}
}
}
if _, ok := nuo.mutation.GroupID(); nuo.mutation.GroupCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Notifier.group"`)
}
if _, ok := nuo.mutation.UserID(); nuo.mutation.UserCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Notifier.user"`)
}
return nil
}
func (nuo *NotifierUpdateOne) sqlSave(ctx context.Context) (_node *Notifier, err error) {
if err := nuo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(notifier.Table, notifier.Columns, sqlgraph.NewFieldSpec(notifier.FieldID, field.TypeUUID))
id, ok := nuo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Notifier.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := nuo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, notifier.FieldID)
for _, f := range fields {
if !notifier.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != notifier.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := nuo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := nuo.mutation.UpdatedAt(); ok {
_spec.SetField(notifier.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := nuo.mutation.Name(); ok {
_spec.SetField(notifier.FieldName, field.TypeString, value)
}
if value, ok := nuo.mutation.URL(); ok {
_spec.SetField(notifier.FieldURL, field.TypeString, value)
}
if value, ok := nuo.mutation.IsActive(); ok {
_spec.SetField(notifier.FieldIsActive, field.TypeBool, value)
}
if nuo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.GroupTable,
Columns: []string{notifier.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := nuo.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.GroupTable,
Columns: []string{notifier.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: group.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if nuo.mutation.UserCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.UserTable,
Columns: []string{notifier.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: user.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := nuo.mutation.UserIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: notifier.UserTable,
Columns: []string{notifier.UserColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: user.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &Notifier{config: nuo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, nuo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{notifier.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
nuo.mutation.done = true
return _node, nil
}

View file

@ -39,5 +39,8 @@ type Location func(*sql.Selector)
// MaintenanceEntry is the predicate function for maintenanceentry builders.
type MaintenanceEntry func(*sql.Selector)
// Notifier is the predicate function for notifier builders.
type Notifier func(*sql.Selector)
// User is the predicate function for user builders.
type User func(*sql.Selector)

View file

@ -16,6 +16,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/ent/label"
"github.com/hay-kot/homebox/backend/internal/data/ent/location"
"github.com/hay-kot/homebox/backend/internal/data/ent/maintenanceentry"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/schema"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -476,6 +477,65 @@ func init() {
maintenanceentryDescID := maintenanceentryMixinFields0[0].Descriptor()
// maintenanceentry.DefaultID holds the default value on creation for the id field.
maintenanceentry.DefaultID = maintenanceentryDescID.Default.(func() uuid.UUID)
notifierMixin := schema.Notifier{}.Mixin()
notifierMixinFields0 := notifierMixin[0].Fields()
_ = notifierMixinFields0
notifierFields := schema.Notifier{}.Fields()
_ = notifierFields
// notifierDescCreatedAt is the schema descriptor for created_at field.
notifierDescCreatedAt := notifierMixinFields0[1].Descriptor()
// notifier.DefaultCreatedAt holds the default value on creation for the created_at field.
notifier.DefaultCreatedAt = notifierDescCreatedAt.Default.(func() time.Time)
// notifierDescUpdatedAt is the schema descriptor for updated_at field.
notifierDescUpdatedAt := notifierMixinFields0[2].Descriptor()
// notifier.DefaultUpdatedAt holds the default value on creation for the updated_at field.
notifier.DefaultUpdatedAt = notifierDescUpdatedAt.Default.(func() time.Time)
// notifier.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
notifier.UpdateDefaultUpdatedAt = notifierDescUpdatedAt.UpdateDefault.(func() time.Time)
// notifierDescName is the schema descriptor for name field.
notifierDescName := notifierFields[0].Descriptor()
// notifier.NameValidator is a validator for the "name" field. It is called by the builders before save.
notifier.NameValidator = func() func(string) error {
validators := notifierDescName.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(name string) error {
for _, fn := range fns {
if err := fn(name); err != nil {
return err
}
}
return nil
}
}()
// notifierDescURL is the schema descriptor for url field.
notifierDescURL := notifierFields[1].Descriptor()
// notifier.URLValidator is a validator for the "url" field. It is called by the builders before save.
notifier.URLValidator = func() func(string) error {
validators := notifierDescURL.Validators
fns := [...]func(string) error{
validators[0].(func(string) error),
validators[1].(func(string) error),
}
return func(url string) error {
for _, fn := range fns {
if err := fn(url); err != nil {
return err
}
}
return nil
}
}()
// notifierDescIsActive is the schema descriptor for is_active field.
notifierDescIsActive := notifierFields[2].Descriptor()
// notifier.DefaultIsActive holds the default value on creation for the is_active field.
notifier.DefaultIsActive = notifierDescIsActive.Default.(bool)
// notifierDescID is the schema descriptor for id field.
notifierDescID := notifierMixinFields0[0].Descriptor()
// notifier.DefaultID holds the default value on creation for the id field.
notifier.DefaultID = notifierDescID.Default.(func() uuid.UUID)
userMixin := schema.User{}.Mixin()
userMixinFields0 := userMixin[0].Fields()
_ = userMixinFields0
@ -550,7 +610,7 @@ func init() {
// user.DefaultIsSuperuser holds the default value on creation for the is_superuser field.
user.DefaultIsSuperuser = userDescIsSuperuser.Default.(bool)
// userDescSuperuser is the schema descriptor for superuser field.
userDescSuperuser := userFields[5].Descriptor()
userDescSuperuser := userFields[4].Descriptor()
// user.DefaultSuperuser holds the default value on creation for the superuser field.
user.DefaultSuperuser = userDescSuperuser.Default.(bool)
// userDescID is the schema descriptor for id field.

View file

@ -16,6 +16,7 @@ type Document struct {
func (Document) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.BaseMixin{},
GroupMixin{ref: "documents"},
}
}
@ -34,10 +35,6 @@ func (Document) Fields() []ent.Field {
// Edges of the Document.
func (Document) Edges() []ent.Edge {
return []ent.Edge{
edge.From("group", Group.Type).
Ref("documents").
Required().
Unique(),
edge.To("attachments", Attachment.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,

View file

@ -5,6 +5,8 @@ import (
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/mixin"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent/schema/mixins"
)
@ -33,30 +35,53 @@ func (Group) Fields() []ent.Field {
// Edges of the Home.
func (Group) Edges() []ent.Edge {
owned := func(name string, t any) ent.Edge {
return edge.To(name, t).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
})
}
return []ent.Edge{
edge.To("users", User.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("locations", Location.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("items", Item.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("labels", Label.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("documents", Document.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("invitation_tokens", GroupInvitationToken.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
owned("users", User.Type),
owned("locations", Location.Type),
owned("items", Item.Type),
owned("labels", Label.Type),
owned("documents", Document.Type),
owned("invitation_tokens", GroupInvitationToken.Type),
owned("notifiers", Notifier.Type),
// $scaffold_edge
}
}
// GroupMixin when embedded in an ent.Schema, adds a reference to
// the Group entity.
type GroupMixin struct {
ref string
field string
mixin.Schema
}
func (g GroupMixin) Fields() []ent.Field {
if g.field != "" {
return []ent.Field{
field.UUID(g.field, uuid.UUID{}),
}
}
return nil
}
func (g GroupMixin) Edges() []ent.Edge {
edge := edge.From("group", Group.Type).
Ref(g.ref).
Unique().
Required()
if g.field != "" {
edge = edge.Field(g.field)
}
return []ent.Edge{edge}
}

View file

@ -18,6 +18,7 @@ func (Item) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.BaseMixin{},
mixins.DetailsMixin{},
GroupMixin{ref: "items"},
}
}
@ -98,30 +99,24 @@ func (Item) Fields() []ent.Field {
// Edges of the Item.
func (Item) Edges() []ent.Edge {
owned := func(s string, t any) ent.Edge {
return edge.To(s, t).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
})
}
return []ent.Edge{
edge.To("children", Item.Type).
From("parent").
Unique(),
edge.From("group", Group.Type).
Ref("items").
Required().
Unique(),
edge.From("label", Label.Type).
Ref("items"),
edge.From("location", Location.Type).
Ref("items").
Unique(),
edge.To("fields", ItemField.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("maintenance_entries", MaintenanceEntry.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("attachments", Attachment.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
owned("fields", ItemField.Type),
owned("maintenance_entries", MaintenanceEntry.Type),
owned("attachments", Attachment.Type),
}
}

View file

@ -16,6 +16,7 @@ func (Label) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.BaseMixin{},
mixins.DetailsMixin{},
GroupMixin{ref: "labels"},
}
}
@ -31,10 +32,6 @@ func (Label) Fields() []ent.Field {
// Edges of the Label.
func (Label) Edges() []ent.Edge {
return []ent.Edge{
edge.From("group", Group.Type).
Ref("labels").
Required().
Unique(),
edge.To("items", Item.Type),
}
}

View file

@ -16,6 +16,7 @@ func (Location) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.BaseMixin{},
mixins.DetailsMixin{},
GroupMixin{ref: "locations"},
}
}
@ -30,10 +31,6 @@ func (Location) Edges() []ent.Edge {
edge.To("children", Location.Type).
From("parent").
Unique(),
edge.From("group", Group.Type).
Ref("locations").
Unique().
Required(),
edge.To("items", Item.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,

View file

@ -0,0 +1,51 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
"github.com/hay-kot/homebox/backend/internal/data/ent/schema/mixins"
)
type Notifier struct {
ent.Schema
}
func (Notifier) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.BaseMixin{},
GroupMixin{
ref: "notifiers",
field: "group_id",
},
UserMixin{
ref: "notifiers",
field: "user_id",
},
}
}
// Fields of the Notifier.
func (Notifier) Fields() []ent.Field {
return []ent.Field{
field.String("name").
MaxLen(255).
NotEmpty(),
field.String("url").
Sensitive().
MaxLen(2083). // supposed max length of URL
NotEmpty(),
field.Bool("is_active").
Default(true),
}
}
func (Notifier) Indexes() []ent.Index {
return []ent.Index{
index.Fields("user_id"),
index.Fields("user_id", "is_active"),
index.Fields("group_id"),
index.Fields("group_id", "is_active"),
}
}

View file

@ -5,6 +5,8 @@ import (
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/mixin"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent/schema/mixins"
)
@ -16,6 +18,7 @@ type User struct {
func (User) Mixin() []ent.Mixin {
return []ent.Mixin{
mixins.BaseMixin{},
GroupMixin{ref: "users"},
}
}
@ -35,11 +38,11 @@ func (User) Fields() []ent.Field {
Sensitive(),
field.Bool("is_superuser").
Default(false),
field.Bool("superuser").
Default(false),
field.Enum("role").
Default("user").
Values("user", "owner"),
field.Bool("superuser").
Default(false),
field.Time("activated_on").
Optional(),
}
@ -48,13 +51,45 @@ func (User) Fields() []ent.Field {
// Edges of the User.
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.From("group", Group.Type).
Ref("users").
Required().
Unique(),
edge.To("auth_tokens", AuthTokens.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
edge.To("notifiers", Notifier.Type).
Annotations(entsql.Annotation{
OnDelete: entsql.Cascade,
}),
}
}
// UserMixin when embedded in an ent.Schema, adds a reference to
// the Group entity.
type UserMixin struct {
ref string
field string
mixin.Schema
}
func (g UserMixin) Fields() []ent.Field {
if g.field != "" {
return []ent.Field{
field.UUID(g.field, uuid.UUID{}),
}
}
return nil
}
func (g UserMixin) Edges() []ent.Edge {
edge := edge.From("user", User.Type).
Ref(g.ref).
Unique().
Required()
if g.field != "" {
edge = edge.Field(g.field)
}
return []ent.Edge{edge}
}

View file

@ -34,6 +34,8 @@ type Tx struct {
Location *LocationClient
// MaintenanceEntry is the client for interacting with the MaintenanceEntry builders.
MaintenanceEntry *MaintenanceEntryClient
// Notifier is the client for interacting with the Notifier builders.
Notifier *NotifierClient
// User is the client for interacting with the User builders.
User *UserClient
@ -178,6 +180,7 @@ func (tx *Tx) init() {
tx.Label = NewLabelClient(tx.config)
tx.Location = NewLocationClient(tx.config)
tx.MaintenanceEntry = NewMaintenanceEntryClient(tx.config)
tx.Notifier = NewNotifierClient(tx.config)
tx.User = NewUserClient(tx.config)
}

View file

@ -30,10 +30,10 @@ type User struct {
Password string `json:"-"`
// IsSuperuser holds the value of the "is_superuser" field.
IsSuperuser bool `json:"is_superuser,omitempty"`
// Role holds the value of the "role" field.
Role user.Role `json:"role,omitempty"`
// Superuser holds the value of the "superuser" field.
Superuser bool `json:"superuser,omitempty"`
// Role holds the value of the "role" field.
Role user.Role `json:"role,omitempty"`
// ActivatedOn holds the value of the "activated_on" field.
ActivatedOn time.Time `json:"activated_on,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
@ -48,9 +48,11 @@ type UserEdges struct {
Group *Group `json:"group,omitempty"`
// AuthTokens holds the value of the auth_tokens edge.
AuthTokens []*AuthTokens `json:"auth_tokens,omitempty"`
// Notifiers holds the value of the notifiers edge.
Notifiers []*Notifier `json:"notifiers,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
@ -75,6 +77,15 @@ func (e UserEdges) AuthTokensOrErr() ([]*AuthTokens, error) {
return nil, &NotLoadedError{edge: "auth_tokens"}
}
// NotifiersOrErr returns the Notifiers value or an error if the edge
// was not loaded in eager-loading.
func (e UserEdges) NotifiersOrErr() ([]*Notifier, error) {
if e.loadedTypes[2] {
return e.Notifiers, nil
}
return nil, &NotLoadedError{edge: "notifiers"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*User) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
@ -147,18 +158,18 @@ func (u *User) assignValues(columns []string, values []any) error {
} else if value.Valid {
u.IsSuperuser = value.Bool
}
case user.FieldRole:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field role", values[i])
} else if value.Valid {
u.Role = user.Role(value.String)
}
case user.FieldSuperuser:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field superuser", values[i])
} else if value.Valid {
u.Superuser = value.Bool
}
case user.FieldRole:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field role", values[i])
} else if value.Valid {
u.Role = user.Role(value.String)
}
case user.FieldActivatedOn:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field activated_on", values[i])
@ -187,6 +198,11 @@ func (u *User) QueryAuthTokens() *AuthTokensQuery {
return NewUserClient(u.config).QueryAuthTokens(u)
}
// QueryNotifiers queries the "notifiers" edge of the User entity.
func (u *User) QueryNotifiers() *NotifierQuery {
return NewUserClient(u.config).QueryNotifiers(u)
}
// Update returns a builder for updating this User.
// Note that you need to call User.Unwrap() before calling this method if this User
// was returned from a transaction, and the transaction was committed or rolled back.
@ -227,12 +243,12 @@ func (u *User) String() string {
builder.WriteString("is_superuser=")
builder.WriteString(fmt.Sprintf("%v", u.IsSuperuser))
builder.WriteString(", ")
builder.WriteString("role=")
builder.WriteString(fmt.Sprintf("%v", u.Role))
builder.WriteString(", ")
builder.WriteString("superuser=")
builder.WriteString(fmt.Sprintf("%v", u.Superuser))
builder.WriteString(", ")
builder.WriteString("role=")
builder.WriteString(fmt.Sprintf("%v", u.Role))
builder.WriteString(", ")
builder.WriteString("activated_on=")
builder.WriteString(u.ActivatedOn.Format(time.ANSIC))
builder.WriteByte(')')

View file

@ -26,16 +26,18 @@ const (
FieldPassword = "password"
// FieldIsSuperuser holds the string denoting the is_superuser field in the database.
FieldIsSuperuser = "is_superuser"
// FieldRole holds the string denoting the role field in the database.
FieldRole = "role"
// FieldSuperuser holds the string denoting the superuser field in the database.
FieldSuperuser = "superuser"
// FieldRole holds the string denoting the role field in the database.
FieldRole = "role"
// FieldActivatedOn holds the string denoting the activated_on field in the database.
FieldActivatedOn = "activated_on"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeAuthTokens holds the string denoting the auth_tokens edge name in mutations.
EdgeAuthTokens = "auth_tokens"
// EdgeNotifiers holds the string denoting the notifiers edge name in mutations.
EdgeNotifiers = "notifiers"
// Table holds the table name of the user in the database.
Table = "users"
// GroupTable is the table that holds the group relation/edge.
@ -52,6 +54,13 @@ const (
AuthTokensInverseTable = "auth_tokens"
// AuthTokensColumn is the table column denoting the auth_tokens relation/edge.
AuthTokensColumn = "user_auth_tokens"
// NotifiersTable is the table that holds the notifiers relation/edge.
NotifiersTable = "notifiers"
// NotifiersInverseTable is the table name for the Notifier entity.
// It exists in this package in order to avoid circular dependency with the "notifier" package.
NotifiersInverseTable = "notifiers"
// NotifiersColumn is the table column denoting the notifiers relation/edge.
NotifiersColumn = "user_id"
)
// Columns holds all SQL columns for user fields.
@ -63,8 +72,8 @@ var Columns = []string{
FieldEmail,
FieldPassword,
FieldIsSuperuser,
FieldRole,
FieldSuperuser,
FieldRole,
FieldActivatedOn,
}

View file

@ -381,6 +381,16 @@ func IsSuperuserNEQ(v bool) predicate.User {
return predicate.User(sql.FieldNEQ(FieldIsSuperuser, v))
}
// SuperuserEQ applies the EQ predicate on the "superuser" field.
func SuperuserEQ(v bool) predicate.User {
return predicate.User(sql.FieldEQ(FieldSuperuser, v))
}
// SuperuserNEQ applies the NEQ predicate on the "superuser" field.
func SuperuserNEQ(v bool) predicate.User {
return predicate.User(sql.FieldNEQ(FieldSuperuser, v))
}
// RoleEQ applies the EQ predicate on the "role" field.
func RoleEQ(v Role) predicate.User {
return predicate.User(sql.FieldEQ(FieldRole, v))
@ -401,16 +411,6 @@ func RoleNotIn(vs ...Role) predicate.User {
return predicate.User(sql.FieldNotIn(FieldRole, vs...))
}
// SuperuserEQ applies the EQ predicate on the "superuser" field.
func SuperuserEQ(v bool) predicate.User {
return predicate.User(sql.FieldEQ(FieldSuperuser, v))
}
// SuperuserNEQ applies the NEQ predicate on the "superuser" field.
func SuperuserNEQ(v bool) predicate.User {
return predicate.User(sql.FieldNEQ(FieldSuperuser, v))
}
// ActivatedOnEQ applies the EQ predicate on the "activated_on" field.
func ActivatedOnEQ(v time.Time) predicate.User {
return predicate.User(sql.FieldEQ(FieldActivatedOn, v))
@ -515,6 +515,33 @@ func HasAuthTokensWith(preds ...predicate.AuthTokens) predicate.User {
})
}
// HasNotifiers applies the HasEdge predicate on the "notifiers" edge.
func HasNotifiers() predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, NotifiersTable, NotifiersColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasNotifiersWith applies the HasEdge predicate on the "notifiers" edge with a given conditions (other predicates).
func HasNotifiersWith(preds ...predicate.Notifier) predicate.User {
return predicate.User(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(NotifiersInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, NotifiersTable, NotifiersColumn),
)
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.User) predicate.User {
return predicate.User(func(s *sql.Selector) {

View file

@ -13,6 +13,7 @@ import (
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent/authtokens"
"github.com/hay-kot/homebox/backend/internal/data/ent/group"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -83,20 +84,6 @@ func (uc *UserCreate) SetNillableIsSuperuser(b *bool) *UserCreate {
return uc
}
// SetRole sets the "role" field.
func (uc *UserCreate) SetRole(u user.Role) *UserCreate {
uc.mutation.SetRole(u)
return uc
}
// SetNillableRole sets the "role" field if the given value is not nil.
func (uc *UserCreate) SetNillableRole(u *user.Role) *UserCreate {
if u != nil {
uc.SetRole(*u)
}
return uc
}
// SetSuperuser sets the "superuser" field.
func (uc *UserCreate) SetSuperuser(b bool) *UserCreate {
uc.mutation.SetSuperuser(b)
@ -111,6 +98,20 @@ func (uc *UserCreate) SetNillableSuperuser(b *bool) *UserCreate {
return uc
}
// SetRole sets the "role" field.
func (uc *UserCreate) SetRole(u user.Role) *UserCreate {
uc.mutation.SetRole(u)
return uc
}
// SetNillableRole sets the "role" field if the given value is not nil.
func (uc *UserCreate) SetNillableRole(u *user.Role) *UserCreate {
if u != nil {
uc.SetRole(*u)
}
return uc
}
// SetActivatedOn sets the "activated_on" field.
func (uc *UserCreate) SetActivatedOn(t time.Time) *UserCreate {
uc.mutation.SetActivatedOn(t)
@ -165,6 +166,21 @@ func (uc *UserCreate) AddAuthTokens(a ...*AuthTokens) *UserCreate {
return uc.AddAuthTokenIDs(ids...)
}
// AddNotifierIDs adds the "notifiers" edge to the Notifier entity by IDs.
func (uc *UserCreate) AddNotifierIDs(ids ...uuid.UUID) *UserCreate {
uc.mutation.AddNotifierIDs(ids...)
return uc
}
// AddNotifiers adds the "notifiers" edges to the Notifier entity.
func (uc *UserCreate) AddNotifiers(n ...*Notifier) *UserCreate {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return uc.AddNotifierIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uc *UserCreate) Mutation() *UserMutation {
return uc.mutation
@ -212,14 +228,14 @@ func (uc *UserCreate) defaults() {
v := user.DefaultIsSuperuser
uc.mutation.SetIsSuperuser(v)
}
if _, ok := uc.mutation.Role(); !ok {
v := user.DefaultRole
uc.mutation.SetRole(v)
}
if _, ok := uc.mutation.Superuser(); !ok {
v := user.DefaultSuperuser
uc.mutation.SetSuperuser(v)
}
if _, ok := uc.mutation.Role(); !ok {
v := user.DefaultRole
uc.mutation.SetRole(v)
}
if _, ok := uc.mutation.ID(); !ok {
v := user.DefaultID()
uc.mutation.SetID(v)
@ -261,6 +277,9 @@ func (uc *UserCreate) check() error {
if _, ok := uc.mutation.IsSuperuser(); !ok {
return &ValidationError{Name: "is_superuser", err: errors.New(`ent: missing required field "User.is_superuser"`)}
}
if _, ok := uc.mutation.Superuser(); !ok {
return &ValidationError{Name: "superuser", err: errors.New(`ent: missing required field "User.superuser"`)}
}
if _, ok := uc.mutation.Role(); !ok {
return &ValidationError{Name: "role", err: errors.New(`ent: missing required field "User.role"`)}
}
@ -269,9 +288,6 @@ func (uc *UserCreate) check() error {
return &ValidationError{Name: "role", err: fmt.Errorf(`ent: validator failed for field "User.role": %w`, err)}
}
}
if _, ok := uc.mutation.Superuser(); !ok {
return &ValidationError{Name: "superuser", err: errors.New(`ent: missing required field "User.superuser"`)}
}
if _, ok := uc.mutation.GroupID(); !ok {
return &ValidationError{Name: "group", err: errors.New(`ent: missing required edge "User.group"`)}
}
@ -334,14 +350,14 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
_spec.SetField(user.FieldIsSuperuser, field.TypeBool, value)
_node.IsSuperuser = value
}
if value, ok := uc.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
_node.Role = value
}
if value, ok := uc.mutation.Superuser(); ok {
_spec.SetField(user.FieldSuperuser, field.TypeBool, value)
_node.Superuser = value
}
if value, ok := uc.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
_node.Role = value
}
if value, ok := uc.mutation.ActivatedOn(); ok {
_spec.SetField(user.FieldActivatedOn, field.TypeTime, value)
_node.ActivatedOn = value
@ -385,6 +401,25 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := uc.mutation.NotifiersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.NotifiersTable,
Columns: []string{user.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}

View file

@ -14,6 +14,7 @@ import (
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent/authtokens"
"github.com/hay-kot/homebox/backend/internal/data/ent/group"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -27,6 +28,7 @@ type UserQuery struct {
predicates []predicate.User
withGroup *GroupQuery
withAuthTokens *AuthTokensQuery
withNotifiers *NotifierQuery
withFKs bool
// intermediate query (i.e. traversal path).
sql *sql.Selector
@ -108,6 +110,28 @@ func (uq *UserQuery) QueryAuthTokens() *AuthTokensQuery {
return query
}
// QueryNotifiers chains the current query on the "notifiers" edge.
func (uq *UserQuery) QueryNotifiers() *NotifierQuery {
query := (&NotifierClient{config: uq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := uq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := uq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(user.Table, user.FieldID, selector),
sqlgraph.To(notifier.Table, notifier.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, user.NotifiersTable, user.NotifiersColumn),
)
fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first User entity from the query.
// Returns a *NotFoundError when no User was found.
func (uq *UserQuery) First(ctx context.Context) (*User, error) {
@ -302,6 +326,7 @@ func (uq *UserQuery) Clone() *UserQuery {
predicates: append([]predicate.User{}, uq.predicates...),
withGroup: uq.withGroup.Clone(),
withAuthTokens: uq.withAuthTokens.Clone(),
withNotifiers: uq.withNotifiers.Clone(),
// clone intermediate query.
sql: uq.sql.Clone(),
path: uq.path,
@ -330,6 +355,17 @@ func (uq *UserQuery) WithAuthTokens(opts ...func(*AuthTokensQuery)) *UserQuery {
return uq
}
// WithNotifiers tells the query-builder to eager-load the nodes that are connected to
// the "notifiers" edge. The optional arguments are used to configure the query builder of the edge.
func (uq *UserQuery) WithNotifiers(opts ...func(*NotifierQuery)) *UserQuery {
query := (&NotifierClient{config: uq.config}).Query()
for _, opt := range opts {
opt(query)
}
uq.withNotifiers = query
return uq
}
// 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.
//
@ -409,9 +445,10 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
nodes = []*User{}
withFKs = uq.withFKs
_spec = uq.querySpec()
loadedTypes = [2]bool{
loadedTypes = [3]bool{
uq.withGroup != nil,
uq.withAuthTokens != nil,
uq.withNotifiers != nil,
}
)
if uq.withGroup != nil {
@ -451,6 +488,13 @@ func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, e
return nil, err
}
}
if query := uq.withNotifiers; query != nil {
if err := uq.loadNotifiers(ctx, query, nodes,
func(n *User) { n.Edges.Notifiers = []*Notifier{} },
func(n *User, e *Notifier) { n.Edges.Notifiers = append(n.Edges.Notifiers, e) }); err != nil {
return nil, err
}
}
return nodes, nil
}
@ -517,6 +561,33 @@ func (uq *UserQuery) loadAuthTokens(ctx context.Context, query *AuthTokensQuery,
}
return nil
}
func (uq *UserQuery) loadNotifiers(ctx context.Context, query *NotifierQuery, nodes []*User, init func(*User), assign func(*User, *Notifier)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*User)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
query.Where(predicate.Notifier(func(s *sql.Selector) {
s.Where(sql.InValues(user.NotifiersColumn, fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.UserID
node, ok := nodeids[fk]
if !ok {
return fmt.Errorf(`unexpected foreign-key "user_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
return nil
}
func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) {
_spec := uq.querySpec()

View file

@ -14,6 +14,7 @@ import (
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent/authtokens"
"github.com/hay-kot/homebox/backend/internal/data/ent/group"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
"github.com/hay-kot/homebox/backend/internal/data/ent/predicate"
"github.com/hay-kot/homebox/backend/internal/data/ent/user"
)
@ -69,20 +70,6 @@ func (uu *UserUpdate) SetNillableIsSuperuser(b *bool) *UserUpdate {
return uu
}
// SetRole sets the "role" field.
func (uu *UserUpdate) SetRole(u user.Role) *UserUpdate {
uu.mutation.SetRole(u)
return uu
}
// SetNillableRole sets the "role" field if the given value is not nil.
func (uu *UserUpdate) SetNillableRole(u *user.Role) *UserUpdate {
if u != nil {
uu.SetRole(*u)
}
return uu
}
// SetSuperuser sets the "superuser" field.
func (uu *UserUpdate) SetSuperuser(b bool) *UserUpdate {
uu.mutation.SetSuperuser(b)
@ -97,6 +84,20 @@ func (uu *UserUpdate) SetNillableSuperuser(b *bool) *UserUpdate {
return uu
}
// SetRole sets the "role" field.
func (uu *UserUpdate) SetRole(u user.Role) *UserUpdate {
uu.mutation.SetRole(u)
return uu
}
// SetNillableRole sets the "role" field if the given value is not nil.
func (uu *UserUpdate) SetNillableRole(u *user.Role) *UserUpdate {
if u != nil {
uu.SetRole(*u)
}
return uu
}
// SetActivatedOn sets the "activated_on" field.
func (uu *UserUpdate) SetActivatedOn(t time.Time) *UserUpdate {
uu.mutation.SetActivatedOn(t)
@ -143,6 +144,21 @@ func (uu *UserUpdate) AddAuthTokens(a ...*AuthTokens) *UserUpdate {
return uu.AddAuthTokenIDs(ids...)
}
// AddNotifierIDs adds the "notifiers" edge to the Notifier entity by IDs.
func (uu *UserUpdate) AddNotifierIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.AddNotifierIDs(ids...)
return uu
}
// AddNotifiers adds the "notifiers" edges to the Notifier entity.
func (uu *UserUpdate) AddNotifiers(n ...*Notifier) *UserUpdate {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return uu.AddNotifierIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uu *UserUpdate) Mutation() *UserMutation {
return uu.mutation
@ -175,6 +191,27 @@ func (uu *UserUpdate) RemoveAuthTokens(a ...*AuthTokens) *UserUpdate {
return uu.RemoveAuthTokenIDs(ids...)
}
// ClearNotifiers clears all "notifiers" edges to the Notifier entity.
func (uu *UserUpdate) ClearNotifiers() *UserUpdate {
uu.mutation.ClearNotifiers()
return uu
}
// RemoveNotifierIDs removes the "notifiers" edge to Notifier entities by IDs.
func (uu *UserUpdate) RemoveNotifierIDs(ids ...uuid.UUID) *UserUpdate {
uu.mutation.RemoveNotifierIDs(ids...)
return uu
}
// RemoveNotifiers removes "notifiers" edges to Notifier entities.
func (uu *UserUpdate) RemoveNotifiers(n ...*Notifier) *UserUpdate {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return uu.RemoveNotifierIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (uu *UserUpdate) Save(ctx context.Context) (int, error) {
uu.defaults()
@ -266,12 +303,12 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value, ok := uu.mutation.IsSuperuser(); ok {
_spec.SetField(user.FieldIsSuperuser, field.TypeBool, value)
}
if value, ok := uu.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
}
if value, ok := uu.mutation.Superuser(); ok {
_spec.SetField(user.FieldSuperuser, field.TypeBool, value)
}
if value, ok := uu.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
}
if value, ok := uu.mutation.ActivatedOn(); ok {
_spec.SetField(user.FieldActivatedOn, field.TypeTime, value)
}
@ -367,6 +404,60 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uu.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.NotifiersTable,
Columns: []string{user.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.RemovedNotifiersIDs(); len(nodes) > 0 && !uu.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.NotifiersTable,
Columns: []string{user.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uu.mutation.NotifiersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.NotifiersTable,
Columns: []string{user.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.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, uu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{user.Label}
@ -425,20 +516,6 @@ func (uuo *UserUpdateOne) SetNillableIsSuperuser(b *bool) *UserUpdateOne {
return uuo
}
// SetRole sets the "role" field.
func (uuo *UserUpdateOne) SetRole(u user.Role) *UserUpdateOne {
uuo.mutation.SetRole(u)
return uuo
}
// SetNillableRole sets the "role" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillableRole(u *user.Role) *UserUpdateOne {
if u != nil {
uuo.SetRole(*u)
}
return uuo
}
// SetSuperuser sets the "superuser" field.
func (uuo *UserUpdateOne) SetSuperuser(b bool) *UserUpdateOne {
uuo.mutation.SetSuperuser(b)
@ -453,6 +530,20 @@ func (uuo *UserUpdateOne) SetNillableSuperuser(b *bool) *UserUpdateOne {
return uuo
}
// SetRole sets the "role" field.
func (uuo *UserUpdateOne) SetRole(u user.Role) *UserUpdateOne {
uuo.mutation.SetRole(u)
return uuo
}
// SetNillableRole sets the "role" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillableRole(u *user.Role) *UserUpdateOne {
if u != nil {
uuo.SetRole(*u)
}
return uuo
}
// SetActivatedOn sets the "activated_on" field.
func (uuo *UserUpdateOne) SetActivatedOn(t time.Time) *UserUpdateOne {
uuo.mutation.SetActivatedOn(t)
@ -499,6 +590,21 @@ func (uuo *UserUpdateOne) AddAuthTokens(a ...*AuthTokens) *UserUpdateOne {
return uuo.AddAuthTokenIDs(ids...)
}
// AddNotifierIDs adds the "notifiers" edge to the Notifier entity by IDs.
func (uuo *UserUpdateOne) AddNotifierIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.AddNotifierIDs(ids...)
return uuo
}
// AddNotifiers adds the "notifiers" edges to the Notifier entity.
func (uuo *UserUpdateOne) AddNotifiers(n ...*Notifier) *UserUpdateOne {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return uuo.AddNotifierIDs(ids...)
}
// Mutation returns the UserMutation object of the builder.
func (uuo *UserUpdateOne) Mutation() *UserMutation {
return uuo.mutation
@ -531,6 +637,27 @@ func (uuo *UserUpdateOne) RemoveAuthTokens(a ...*AuthTokens) *UserUpdateOne {
return uuo.RemoveAuthTokenIDs(ids...)
}
// ClearNotifiers clears all "notifiers" edges to the Notifier entity.
func (uuo *UserUpdateOne) ClearNotifiers() *UserUpdateOne {
uuo.mutation.ClearNotifiers()
return uuo
}
// RemoveNotifierIDs removes the "notifiers" edge to Notifier entities by IDs.
func (uuo *UserUpdateOne) RemoveNotifierIDs(ids ...uuid.UUID) *UserUpdateOne {
uuo.mutation.RemoveNotifierIDs(ids...)
return uuo
}
// RemoveNotifiers removes "notifiers" edges to Notifier entities.
func (uuo *UserUpdateOne) RemoveNotifiers(n ...*Notifier) *UserUpdateOne {
ids := make([]uuid.UUID, len(n))
for i := range n {
ids[i] = n[i].ID
}
return uuo.RemoveNotifierIDs(ids...)
}
// Where appends a list predicates to the UserUpdate builder.
func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
uuo.mutation.Where(ps...)
@ -652,12 +779,12 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
if value, ok := uuo.mutation.IsSuperuser(); ok {
_spec.SetField(user.FieldIsSuperuser, field.TypeBool, value)
}
if value, ok := uuo.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
}
if value, ok := uuo.mutation.Superuser(); ok {
_spec.SetField(user.FieldSuperuser, field.TypeBool, value)
}
if value, ok := uuo.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
}
if value, ok := uuo.mutation.ActivatedOn(); ok {
_spec.SetField(user.FieldActivatedOn, field.TypeTime, value)
}
@ -753,6 +880,60 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if uuo.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.NotifiersTable,
Columns: []string{user.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.RemovedNotifiersIDs(); len(nodes) > 0 && !uuo.mutation.NotifiersCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.NotifiersTable,
Columns: []string{user.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := uuo.mutation.NotifiersIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: user.NotifiersTable,
Columns: []string{user.NotifiersColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: notifier.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &User{config: uuo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues

View file

@ -0,0 +1,6 @@
-- create "notifiers" table
CREATE TABLE `notifiers` (`id` uuid NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `name` text NOT NULL, `url` text NOT NULL, `is_active` bool NOT NULL DEFAULT true, `user_id` uuid NOT NULL, PRIMARY KEY (`id`), CONSTRAINT `notifiers_users_notifiers` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE);
-- create index "notifier_user_id" to table: "notifiers"
CREATE INDEX `notifier_user_id` ON `notifiers` (`user_id`);
-- create index "notifier_user_id_is_active" to table: "notifiers"
CREATE INDEX `notifier_user_id_is_active` ON `notifiers` (`user_id`, `is_active`);

View file

@ -0,0 +1,20 @@
-- disable the enforcement of foreign-keys constraints
PRAGMA foreign_keys = off;
-- create "new_notifiers" table
CREATE TABLE `new_notifiers` (`id` uuid NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `name` text NOT NULL, `url` text NOT NULL, `is_active` bool NOT NULL DEFAULT true, `group_id` uuid NOT NULL, `user_id` uuid NOT NULL, PRIMARY KEY (`id`), CONSTRAINT `notifiers_groups_notifiers` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, CONSTRAINT `notifiers_users_notifiers` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE);
-- copy rows from old table "notifiers" to new temporary table "new_notifiers"
INSERT INTO `new_notifiers` (`id`, `created_at`, `updated_at`, `name`, `url`, `is_active`, `user_id`) SELECT `id`, `created_at`, `updated_at`, `name`, `url`, `is_active`, `user_id` FROM `notifiers`;
-- drop "notifiers" table after copying rows
DROP TABLE `notifiers`;
-- rename temporary table "new_notifiers" to "notifiers"
ALTER TABLE `new_notifiers` RENAME TO `notifiers`;
-- create index "notifier_user_id" to table: "notifiers"
CREATE INDEX `notifier_user_id` ON `notifiers` (`user_id`);
-- create index "notifier_user_id_is_active" to table: "notifiers"
CREATE INDEX `notifier_user_id_is_active` ON `notifiers` (`user_id`, `is_active`);
-- create index "notifier_group_id" to table: "notifiers"
CREATE INDEX `notifier_group_id` ON `notifiers` (`group_id`);
-- create index "notifier_group_id_is_active" to table: "notifiers"
CREATE INDEX `notifier_group_id_is_active` ON `notifiers` (`group_id`, `is_active`);
-- enable back the enforcement of foreign-keys constraints
PRAGMA foreign_keys = on;

View file

@ -1,4 +1,4 @@
h1:o94ZiQarQV54hzXXKoOUNL/DvHYieveswCLwJaUMGPo=
h1:VjVLPBHzJ8N1Hiw+Aeitb0alnVn9UFilnajCzc+pie8=
20220929052825_init.sql h1:ZlCqm1wzjDmofeAcSX3jE4h4VcdTNGpRg2eabztDy9Q=
20221001210956_group_invitations.sql h1:YQKJFtE39wFOcRNbZQ/d+ZlHwrcfcsZlcv/pLEYdpjw=
20221009173029_add_user_roles.sql h1:vWmzAfgEWQeGk0Vn70zfVPCcfEZth3E0JcvyKTjpYyU=
@ -10,3 +10,5 @@ h1:o94ZiQarQV54hzXXKoOUNL/DvHYieveswCLwJaUMGPo=
20221205234214_add_maintenance_entries.sql h1:B56VzCuDsed1k3/sYUoKlOkP90DcdLufxFK0qYvoafU=
20221205234812_cascade_delete_roles.sql h1:VIiaImR48nCHF3uFbOYOX1E79Ta5HsUBetGaSAbh9Gk=
20230227024134_add_scheduled_date.sql h1:8qO5OBZ0AzsfYEQOAQQrYIjyhSwM+v1A+/ylLSoiyoc=
20230305065819_add_notifier_types.sql h1:r5xrgCKYQ2o9byBqYeAX1zdp94BLdaxf4vq9OmGHNl0=
20230305071524_add_group_id_to_notifiers.sql h1:xDShqbyClcFhvJbwclOHdczgXbdffkxXNWjV61hL/t4=

View file

@ -0,0 +1,32 @@
package repo
type MapFunc[T any, U any] func(T) U
func (a MapFunc[T, U]) Map(v T) U {
return a(v)
}
func (a MapFunc[T, U]) MapEach(v []T) []U {
result := make([]U, len(v))
for i, item := range v {
result[i] = a(item)
}
return result
}
func (a MapFunc[T, U]) MapErr(v T, err error) (U, error) {
if err != nil {
var zero U
return zero, err
}
return a(v), nil
}
func (a MapFunc[T, U]) MapEachErr(v []T, err error) ([]U, error) {
if err != nil {
return nil, err
}
return a.MapEach(v), nil
}

View file

@ -0,0 +1,110 @@
package repo
import (
"context"
"time"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent"
"github.com/hay-kot/homebox/backend/internal/data/ent/notifier"
)
type NotifierRepository struct {
db *ent.Client
mapper MapFunc[*ent.Notifier, NotifierOut]
}
func NewNotifierRepository(db *ent.Client) *NotifierRepository {
return &NotifierRepository{
db: db,
mapper: func(n *ent.Notifier) NotifierOut {
return NotifierOut{
ID: n.ID,
UserID: n.UserID,
GroupID: n.GroupID,
CreatedAt: n.CreatedAt,
UpdatedAt: n.UpdatedAt,
Name: n.Name,
IsActive: n.IsActive,
URL: n.URL,
}
},
}
}
type (
NotifierCreate struct {
Name string `json:"name" validate:"required,min=1,max=255"`
IsActive bool `json:"isActive"`
URL string `json:"url" validate:"required,shoutrrr"`
}
NotifierUpdate struct {
Name string `json:"name" validate:"required,min=1,max=255"`
IsActive bool `json:"isActive"`
URL *string `json:"url" validate:"omitempty,shoutrrr" extensions:"x-nullable" `
}
NotifierOut struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
GroupID uuid.UUID `json:"groupId"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Name string `json:"name"`
IsActive bool `json:"isActive"`
URL string `json:"-"` // URL field is not exposed to the client
}
)
func (r *NotifierRepository) GetByUser(ctx context.Context, userID uuid.UUID) ([]NotifierOut, error) {
notifier, err := r.db.Notifier.Query().
Where(notifier.UserID(userID)).
Order(ent.Asc(notifier.FieldName)).
All(ctx)
return r.mapper.MapEachErr(notifier, err)
}
func (r *NotifierRepository) GetByGroup(ctx context.Context, groupID uuid.UUID) ([]NotifierOut, error) {
notifier, err := r.db.Notifier.Query().
Where(notifier.GroupID(groupID)).
Order(ent.Asc(notifier.FieldName)).
All(ctx)
return r.mapper.MapEachErr(notifier, err)
}
func (r *NotifierRepository) Create(ctx context.Context, groupID, userID uuid.UUID, input NotifierCreate) (NotifierOut, error) {
notifier, err := r.db.Notifier.
Create().
SetGroupID(groupID).
SetUserID(userID).
SetName(input.Name).
SetIsActive(input.IsActive).
SetURL(input.URL).
Save(ctx)
return r.mapper.MapErr(notifier, err)
}
func (r *NotifierRepository) Update(ctx context.Context, userID uuid.UUID, id uuid.UUID, input NotifierUpdate) (NotifierOut, error) {
q := r.db.Notifier.
UpdateOneID(id).
SetName(input.Name).
SetIsActive(input.IsActive)
if input.URL != nil {
q.SetURL(*input.URL)
}
notifier, err := q.Save(ctx)
return r.mapper.MapErr(notifier, err)
}
func (r *NotifierRepository) Delete(ctx context.Context, userID uuid.UUID, ID uuid.UUID) error {
_, err := r.db.Notifier.Delete().Where(notifier.UserID(userID), notifier.ID(ID)).Exec(ctx)
return err
}

View file

@ -13,6 +13,7 @@ type AllRepos struct {
Docs *DocumentRepository
Attachments *AttachmentRepo
MaintEntry *MaintenanceEntryRepository
Notifiers *NotifierRepository
}
func New(db *ent.Client, root string) *AllRepos {
@ -26,5 +27,6 @@ func New(db *ent.Client, root string) *AllRepos {
Docs: &DocumentRepository{db, root},
Attachments: &AttachmentRepo{db},
MaintEntry: &MaintenanceEntryRepository{db},
Notifiers: NewNotifierRepository(db),
}
}

View file

@ -5,7 +5,8 @@ import (
"errors"
)
type UnauthorizedError struct{}
type UnauthorizedError struct {
}
func (err *UnauthorizedError) Error() string {
return "unauthorized"
@ -28,7 +29,7 @@ func (err *InvalidRouteKeyError) Error() string {
return "invalid route key: " + err.key
}
func NewInvalidRouteKeyError(key string) error {
func NewRouteKeyError(key string) error {
return &InvalidRouteKeyError{key}
}

View file

@ -1,11 +1,54 @@
package validate
import "github.com/go-playground/validator/v10"
import (
"strings"
"github.com/go-playground/validator/v10"
)
var validate *validator.Validate
func init() {
validate = validator.New()
err := validate.RegisterValidation("shoutrrr", func(fl validator.FieldLevel) bool {
prefixes := [...]string{
"discord://",
"smtp://",
"gotify://",
"googlechat://",
"ifttt://",
"join://",
"mattermost://",
"matrix://",
"opsgenie://",
"pushbullet://",
"pushover://",
"rocketchat://",
"slack://",
"teams://",
"telegram://",
"zulip://",
}
str := fl.Field().String()
if str == "" {
return false
}
for _, prefix := range prefixes {
if strings.HasPrefix(str, prefix) {
return true
}
}
return false
})
if err != nil {
panic(err)
}
}
// Checks a struct for validation errors and returns any errors the occur. This

View file

@ -0,0 +1,74 @@
package adapters
import (
"net/http"
"github.com/hay-kot/homebox/backend/pkgs/server"
)
// Action is a function that adapts a function to the server.Handler interface.
// It decodes the request body into a value of type T and passes it to the function f.
// The function f is expected to return a value of type Y and an error.
//
// Example:
//
// type Body struct {
// Foo string `json:"foo"`
// }
//
// fn := func(ctx context.Context, b Body) (any, error) {
// // do something with b
// return nil, nil
// }
//
// r.Post("/foo", adapters.Action(fn, http.StatusCreated))
func Action[T any, Y any](f AdapterFunc[T, Y], ok int) server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
v, err := decode[T](r)
if err != nil {
return err
}
res, err := f(r.Context(), v)
if err != nil {
return err
}
return server.Respond(w, ok, res)
}
}
// ActionID functions the same as Action, but it also decodes a UUID from the URL path.
//
// Example:
//
// type Body struct {
// Foo string `json:"foo"`
// }
//
// fn := func(ctx context.Context, ID uuid.UUID, b Body) (any, error) {
// // do something with ID and b
// return nil, nil
// }
//
// r.Post("/foo/{id}", adapters.ActionID(fn, http.StatusCreated))
func ActionID[T any, Y any](param string, f IDFunc[T, Y], ok int) server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ID, err := routeUUID(r, param)
if err != nil {
return err
}
v, err := decode[T](r)
if err != nil {
return err
}
res, err := f(r.Context(), ID, v)
if err != nil {
return err
}
return server.Respond(w, ok, res)
}
}

View file

@ -0,0 +1,10 @@
package adapters
import (
"context"
"github.com/google/uuid"
)
type AdapterFunc[T any, Y any] func(context.Context, T) (Y, error)
type IDFunc[T any, Y any] func(context.Context, uuid.UUID, T) (Y, error)

View file

@ -0,0 +1,62 @@
package adapters
import (
"context"
"net/http"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/pkgs/server"
)
type CommandFunc[T any] func(context.Context) (T, error)
type CommandIDFunc[T any] func(context.Context, uuid.UUID) (T, error)
// Command is an HandlerAdapter that returns a server.HandlerFunc that
// The command adapters are used to handle commands that do not accept a body
// or a query. You can think of them as a way to handle RPC style Rest Endpoints.
//
// Example:
//
// fn := func(ctx context.Context) (interface{}, error) {
// // do something
// return nil, nil
// }
//
// r.Get("/foo", adapters.Command(fn, http.NoContent))
func Command[T any](f CommandFunc[T], ok int) server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
res, err := f(r.Context())
if err != nil {
return err
}
return server.Respond(w, ok, res)
}
}
// CommandID is the same as the Command adapter but it accepts a UUID as a parameter
// in the URL. The parameter name is passed as the first argument.
//
// Example:
//
// fn := func(ctx context.Context, id uuid.UUID) (interface{}, error) {
// // do something
// return nil, nil
// }
//
// r.Get("/foo/{id}", adapters.CommandID("id", fn, http.NoContent))
func CommandID[T any](param string, f CommandIDFunc[T], ok int) server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ID, err := routeUUID(r, param)
if err != nil {
return err
}
res, err := f(r.Context(), ID)
if err != nil {
return err
}
return server.Respond(w, ok, res)
}
}

View file

@ -0,0 +1,52 @@
package adapters
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/gorilla/schema"
"github.com/hay-kot/homebox/backend/internal/sys/validate"
"github.com/hay-kot/homebox/backend/pkgs/server"
)
var queryDecoder = schema.NewDecoder()
func decodeQuery[T any](r *http.Request) (T, error) {
var v T
err := queryDecoder.Decode(&v, r.URL.Query())
if err != nil {
return v, err
}
err = validate.Check(v)
if err != nil {
return v, err
}
return v, nil
}
func decode[T any](r *http.Request) (T, error) {
var v T
err := server.Decode(r, &v)
if err != nil {
return v, err
}
err = validate.Check(v)
if err != nil {
return v, err
}
return v, nil
}
func routeUUID(r *http.Request, key string) (uuid.UUID, error) {
ID, err := uuid.Parse(chi.URLParam(r, key))
if err != nil {
return uuid.Nil, validate.NewRouteKeyError(key)
}
return ID, nil
}

View file

@ -0,0 +1,9 @@
/*
Package adapters offers common adapters for turing regular functions into HTTP Handlers
There are three types of adapters
- Query adapters
- Action adapters
- Command adapters
*/
package adapters

View file

@ -0,0 +1,72 @@
package adapters
import (
"net/http"
"github.com/hay-kot/homebox/backend/pkgs/server"
)
// Query is a server.Handler that decodes a query from the request and calls the provided function.
//
// Example:
//
// type Query struct {
// Foo string `schema:"foo"`
// }
//
// fn := func(ctx context.Context, q Query) (any, error) {
// // do something with q
// return nil, nil
// }
//
// r.Get("/foo", adapters.Query(fn, http.StatusOK))
func Query[T any, Y any](f AdapterFunc[T, Y], ok int) server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
q, err := decodeQuery[T](r)
if err != nil {
return err
}
res, err := f(r.Context(), q)
if err != nil {
return err
}
return server.Respond(w, ok, res)
}
}
// QueryID is a server.Handler that decodes a query and an ID from the request and calls the provided function.
//
// Example:
//
// type Query struct {
// Foo string `schema:"foo"`
// }
//
// fn := func(ctx context.Context, ID uuid.UUID, q Query) (any, error) {
// // do something with ID and q
// return nil, nil
// }
//
// r.Get("/foo/{id}", adapters.QueryID(fn, http.StatusOK))
func QueryID[T any, Y any](param string, f IDFunc[T, Y], ok int) server.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ID, err := routeUUID(r, param)
if err != nil {
return err
}
q, err := decodeQuery[T](r)
if err != nil {
return err
}
res, err := f(r.Context(), ID, q)
if err != nil {
return err
}
return server.Respond(w, ok, res)
}
}

View file

@ -33,6 +33,8 @@ func Errors(log zerolog.Logger) server.Middleware {
Error: err.Error(),
}
case validate.IsFieldError(err):
code = http.StatusUnprocessableEntity
fieldErrors := err.(validate.FieldErrors)
resp.Error = "Validation Error"
resp.Fields = map[string]string{}
@ -43,14 +45,18 @@ func Errors(log zerolog.Logger) server.Middleware {
case validate.IsRequestError(err):
requestError := err.(*validate.RequestError)
resp.Error = requestError.Error()
code = requestError.Status
if requestError.Status == 0 {
code = http.StatusBadRequest
} else {
code = requestError.Status
}
case ent.IsNotFound(err):
resp.Error = "Not Found"
code = http.StatusNotFound
default:
resp.Error = "Unknown Error"
code = http.StatusInternalServerError
}
if err := server.Respond(w, code, resp); err != nil {

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,7 @@ theme:
- navigation.expand
- navigation.sections
- navigation.tabs.sticky
- navigation.tabs
favicon: assets/img/favicon.svg
logo: assets/img/favicon.svg
@ -32,6 +33,8 @@ plugins:
extra_css:
- assets/stylesheets/extras.css
extra_javascript:
- assets/js/redoc.js
markdown_extensions:
- pymdownx.emoji:
@ -47,8 +50,10 @@ markdown_extensions:
- pymdownx.superfences
nav:
- Home: index.md
- Quick Start: quick-start.md
- Tips and Tricks: tips-tricks.md
- Import and Export: import-csv.md
- Building The Binary: build.md
- Home:
- Home: index.md
- Quick Start: quick-start.md
- Tips and Tricks: tips-tricks.md
- Import and Export: import-csv.md
- Building The Binary: build.md
- API: "https://redocly.github.io/redoc/?url=https://hay-kot.github.io/homebox/api/openapi-2.0.json"

651
docs/poetry.lock generated
View file

@ -1,651 +0,0 @@
# This file is automatically @generated by Poetry and should not be changed by hand.
[[package]]
name = "certifi"
version = "2022.12.7"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
]
[[package]]
name = "charset-normalizer"
version = "3.0.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
python-versions = "*"
files = [
{file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"},
{file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"},
{file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"},
{file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"},
{file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"},
{file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"},
{file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"},
{file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"},
{file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"},
{file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"},
]
[[package]]
name = "click"
version = "8.1.3"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.5"
description = "Cross-platform colored terminal text."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
{file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
]
[[package]]
name = "ghp-import"
version = "2.1.0"
description = "Copy your docs directly to the gh-pages branch."
category = "main"
optional = false
python-versions = "*"
files = [
{file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
{file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
]
[package.dependencies]
python-dateutil = ">=2.8.1"
[package.extras]
dev = ["flake8", "markdown", "twine", "wheel"]
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
[[package]]
name = "Jinja2"
version = "3.1.2"
description = "A very fast and expressive template engine."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
]
[package.dependencies]
MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
[[package]]
name = "Markdown"
version = "3.3.7"
description = "Python implementation of Markdown."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"},
{file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"},
]
[package.extras]
testing = ["coverage", "pyyaml"]
[[package]]
name = "MarkupSafe"
version = "2.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
]
[[package]]
name = "mergedeep"
version = "1.3.4"
description = "A deep merge function for 🐍."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
{file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
]
[[package]]
name = "mkdocs"
version = "1.4.2"
description = "Project documentation with Markdown."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "mkdocs-1.4.2-py3-none-any.whl", hash = "sha256:c8856a832c1e56702577023cd64cc5f84948280c1c0fcc6af4cd39006ea6aa8c"},
{file = "mkdocs-1.4.2.tar.gz", hash = "sha256:8947af423a6d0facf41ea1195b8e1e8c85ad94ac95ae307fe11232e0424b11c5"},
]
[package.dependencies]
click = ">=7.0"
colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""}
ghp-import = ">=1.0"
jinja2 = ">=2.11.1"
markdown = ">=3.2.1,<3.4"
mergedeep = ">=1.3.4"
packaging = ">=20.5"
pyyaml = ">=5.1"
pyyaml-env-tag = ">=0.1"
watchdog = ">=2.0"
[package.extras]
i18n = ["babel (>=2.9.0)"]
min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"]
[[package]]
name = "mkdocs-material"
version = "9.0.5"
description = "Documentation that simply works"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "mkdocs_material-9.0.5-py3-none-any.whl", hash = "sha256:53194bf8ae7dfb527fef2892a6ee291d3efc7b57d010b04dbb818b4ee88074a5"},
{file = "mkdocs_material-9.0.5.tar.gz", hash = "sha256:bbfed71788223b4c548a6e637cb7a9ee5b6ad6593c6d5b04e57c9c4d2c39d76b"},
]
[package.dependencies]
colorama = ">=0.4"
jinja2 = ">=3.0"
markdown = ">=3.2"
mkdocs = ">=1.4.2"
mkdocs-material-extensions = ">=1.1"
pygments = ">=2.14"
pymdown-extensions = ">=9.9.1"
regex = ">=2022.4.24"
requests = ">=2.26"
[[package]]
name = "mkdocs-material-extensions"
version = "1.1.1"
description = "Extension pack for Python Markdown and MkDocs Material."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "mkdocs_material_extensions-1.1.1-py3-none-any.whl", hash = "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945"},
{file = "mkdocs_material_extensions-1.1.1.tar.gz", hash = "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93"},
]
[[package]]
name = "packaging"
version = "21.3"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
[package.dependencies]
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "pygments"
version = "2.14.0"
description = "Pygments is a syntax highlighting package written in Python."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"},
{file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"},
]
[package.extras]
plugins = ["importlib-metadata"]
[[package]]
name = "pymdown-extensions"
version = "9.9.1"
description = "Extension pack for Python Markdown."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "pymdown_extensions-9.9.1-py3-none-any.whl", hash = "sha256:8a8973933ab45b6fe8f5f8da1de25766356b1f91dee107bf4a34efd158dc340b"},
{file = "pymdown_extensions-9.9.1.tar.gz", hash = "sha256:abed29926960bbb3b40f5ed5fa6375e29724d4e3cb86ced7c2bbd37ead1afeea"},
]
[package.dependencies]
markdown = ">=3.2"
[[package]]
name = "pyparsing"
version = "3.0.9"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
category = "main"
optional = false
python-versions = ">=3.6.8"
files = [
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
]
[package.extras]
diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
files = [
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
]
[package.dependencies]
six = ">=1.5"
[[package]]
name = "PyYAML"
version = "6.0"
description = "YAML parser and emitter for Python"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
]
[[package]]
name = "pyyaml_env_tag"
version = "0.1"
description = "A custom YAML tag for referencing environment variables in YAML files. "
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
]
[package.dependencies]
pyyaml = "*"
[[package]]
name = "regex"
version = "2022.10.31"
description = "Alternative regular expression module, to replace re."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "regex-2022.10.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8ff454ef0bb061e37df03557afda9d785c905dab15584860f982e88be73015f"},
{file = "regex-2022.10.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1eba476b1b242620c266edf6325b443a2e22b633217a9835a52d8da2b5c051f9"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0e5af9a9effb88535a472e19169e09ce750c3d442fb222254a276d77808620b"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d03fe67b2325cb3f09be029fd5da8df9e6974f0cde2c2ac6a79d2634e791dd57"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9d0b68ac1743964755ae2d89772c7e6fb0118acd4d0b7464eaf3921c6b49dd4"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a45b6514861916c429e6059a55cf7db74670eaed2052a648e3e4d04f070e001"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b0886885f7323beea6f552c28bff62cbe0983b9fbb94126531693ea6c5ebb90"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5aefb84a301327ad115e9d346c8e2760009131d9d4b4c6b213648d02e2abe144"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:702d8fc6f25bbf412ee706bd73019da5e44a8400861dfff7ff31eb5b4a1276dc"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a3c1ebd4ed8e76e886507c9eddb1a891673686c813adf889b864a17fafcf6d66"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:50921c140561d3db2ab9f5b11c5184846cde686bb5a9dc64cae442926e86f3af"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7db345956ecce0c99b97b042b4ca7326feeec6b75facd8390af73b18e2650ffc"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:763b64853b0a8f4f9cfb41a76a4a85a9bcda7fdda5cb057016e7706fde928e66"},
{file = "regex-2022.10.31-cp310-cp310-win32.whl", hash = "sha256:44136355e2f5e06bf6b23d337a75386371ba742ffa771440b85bed367c1318d1"},
{file = "regex-2022.10.31-cp310-cp310-win_amd64.whl", hash = "sha256:bfff48c7bd23c6e2aec6454aaf6edc44444b229e94743b34bdcdda2e35126cf5"},
{file = "regex-2022.10.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b4b1fe58cd102d75ef0552cf17242705ce0759f9695334a56644ad2d83903fe"},
{file = "regex-2022.10.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:542e3e306d1669b25936b64917285cdffcd4f5c6f0247636fec037187bd93542"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c27cc1e4b197092e50ddbf0118c788d9977f3f8f35bfbbd3e76c1846a3443df7"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8e38472739028e5f2c3a4aded0ab7eadc447f0d84f310c7a8bb697ec417229e"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76c598ca73ec73a2f568e2a72ba46c3b6c8690ad9a07092b18e48ceb936e9f0c"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28d3309ebd6d6b2cf82969b5179bed5fefe6142c70f354ece94324fa11bf6a1"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9af69f6746120998cd9c355e9c3c6aec7dff70d47247188feb4f829502be8ab4"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a5f9505efd574d1e5b4a76ac9dd92a12acb2b309551e9aa874c13c11caefbe4f"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5ff525698de226c0ca743bfa71fc6b378cda2ddcf0d22d7c37b1cc925c9650a5"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe7fda2fe7c8890d454f2cbc91d6c01baf206fbc96d89a80241a02985118c0c"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2cdc55ca07b4e70dda898d2ab7150ecf17c990076d3acd7a5f3b25cb23a69f1c"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:44a6c2f6374e0033873e9ed577a54a3602b4f609867794c1a3ebba65e4c93ee7"},
{file = "regex-2022.10.31-cp311-cp311-win32.whl", hash = "sha256:d8716f82502997b3d0895d1c64c3b834181b1eaca28f3f6336a71777e437c2af"},
{file = "regex-2022.10.31-cp311-cp311-win_amd64.whl", hash = "sha256:61edbca89aa3f5ef7ecac8c23d975fe7261c12665f1d90a6b1af527bba86ce61"},
{file = "regex-2022.10.31-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a069c8483466806ab94ea9068c34b200b8bfc66b6762f45a831c4baaa9e8cdd"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d26166acf62f731f50bdd885b04b38828436d74e8e362bfcb8df221d868b5d9b"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac741bf78b9bb432e2d314439275235f41656e189856b11fb4e774d9f7246d81"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75f591b2055523fc02a4bbe598aa867df9e953255f0b7f7715d2a36a9c30065c"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bddd61d2a3261f025ad0f9ee2586988c6a00c780a2fb0a92cea2aa702c54"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef4163770525257876f10e8ece1cf25b71468316f61451ded1a6f44273eedeb5"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7b280948d00bd3973c1998f92e22aa3ecb76682e3a4255f33e1020bd32adf443"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:d0213671691e341f6849bf33cd9fad21f7b1cb88b89e024f33370733fec58742"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:22e7ebc231d28393dfdc19b185d97e14a0f178bedd78e85aad660e93b646604e"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:8ad241da7fac963d7573cc67a064c57c58766b62a9a20c452ca1f21050868dfa"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:586b36ebda81e6c1a9c5a5d0bfdc236399ba6595e1397842fd4a45648c30f35e"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0653d012b3bf45f194e5e6a41df9258811ac8fc395579fa82958a8b76286bea4"},
{file = "regex-2022.10.31-cp36-cp36m-win32.whl", hash = "sha256:144486e029793a733e43b2e37df16a16df4ceb62102636ff3db6033994711066"},
{file = "regex-2022.10.31-cp36-cp36m-win_amd64.whl", hash = "sha256:c14b63c9d7bab795d17392c7c1f9aaabbffd4cf4387725a0ac69109fb3b550c6"},
{file = "regex-2022.10.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4cac3405d8dda8bc6ed499557625585544dd5cbf32072dcc72b5a176cb1271c8"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23cbb932cc53a86ebde0fb72e7e645f9a5eec1a5af7aa9ce333e46286caef783"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74bcab50a13960f2a610cdcd066e25f1fd59e23b69637c92ad470784a51b1347"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d680ef3e4d405f36f0d6d1ea54e740366f061645930072d39bca16a10d8c93"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6910b56b700bea7be82c54ddf2e0ed792a577dfaa4a76b9af07d550af435c6"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:659175b2144d199560d99a8d13b2228b85e6019b6e09e556209dfb8c37b78a11"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1ddf14031a3882f684b8642cb74eea3af93a2be68893901b2b387c5fd92a03ec"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b683e5fd7f74fb66e89a1ed16076dbab3f8e9f34c18b1979ded614fe10cdc4d9"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2bde29cc44fa81c0a0c8686992c3080b37c488df167a371500b2a43ce9f026d1"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4919899577ba37f505aaebdf6e7dc812d55e8f097331312db7f1aab18767cce8"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:9c94f7cc91ab16b36ba5ce476f1904c91d6c92441f01cd61a8e2729442d6fcf5"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ae1e96785696b543394a4e3f15f3f225d44f3c55dafe3f206493031419fedf95"},
{file = "regex-2022.10.31-cp37-cp37m-win32.whl", hash = "sha256:c670f4773f2f6f1957ff8a3962c7dd12e4be54d05839b216cb7fd70b5a1df394"},
{file = "regex-2022.10.31-cp37-cp37m-win_amd64.whl", hash = "sha256:8e0caeff18b96ea90fc0eb6e3bdb2b10ab5b01a95128dfeccb64a7238decf5f0"},
{file = "regex-2022.10.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:131d4be09bea7ce2577f9623e415cab287a3c8e0624f778c1d955ec7c281bd4d"},
{file = "regex-2022.10.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e613a98ead2005c4ce037c7b061f2409a1a4e45099edb0ef3200ee26ed2a69a8"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052b670fafbe30966bbe5d025e90b2a491f85dfe5b2583a163b5e60a85a321ad"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa62a07ac93b7cb6b7d0389d8ef57ffc321d78f60c037b19dfa78d6b17c928ee"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5352bea8a8f84b89d45ccc503f390a6be77917932b1c98c4cdc3565137acc714"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f61c9944f0be2dc2b75689ba409938c14876c19d02f7585af4460b6a21403e"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29c04741b9ae13d1e94cf93fca257730b97ce6ea64cfe1eba11cf9ac4e85afb6"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:543883e3496c8b6d58bd036c99486c3c8387c2fc01f7a342b760c1ea3158a318"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7a8b43ee64ca8f4befa2bea4083f7c52c92864d8518244bfa6e88c751fa8fff"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6a9a19bea8495bb419dc5d38c4519567781cd8d571c72efc6aa959473d10221a"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6ffd55b5aedc6f25fd8d9f905c9376ca44fcf768673ffb9d160dd6f409bfda73"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4bdd56ee719a8f751cf5a593476a441c4e56c9b64dc1f0f30902858c4ef8771d"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ca88da1bd78990b536c4a7765f719803eb4f8f9971cc22d6ca965c10a7f2c4c"},
{file = "regex-2022.10.31-cp38-cp38-win32.whl", hash = "sha256:5a260758454580f11dd8743fa98319bb046037dfab4f7828008909d0aa5292bc"},
{file = "regex-2022.10.31-cp38-cp38-win_amd64.whl", hash = "sha256:5e6a5567078b3eaed93558842346c9d678e116ab0135e22eb72db8325e90b453"},
{file = "regex-2022.10.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5217c25229b6a85049416a5c1e6451e9060a1edcf988641e309dbe3ab26d3e49"},
{file = "regex-2022.10.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4bf41b8b0a80708f7e0384519795e80dcb44d7199a35d52c15cc674d10b3081b"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf0da36a212978be2c2e2e2d04bdff46f850108fccc1851332bcae51c8907cc"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d403d781b0e06d2922435ce3b8d2376579f0c217ae491e273bab8d092727d244"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a37d51fa9a00d265cf73f3de3930fa9c41548177ba4f0faf76e61d512c774690"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4f781ffedd17b0b834c8731b75cce2639d5a8afe961c1e58ee7f1f20b3af185"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d243b36fbf3d73c25e48014961e83c19c9cc92530516ce3c43050ea6276a2ab7"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:370f6e97d02bf2dd20d7468ce4f38e173a124e769762d00beadec3bc2f4b3bc4"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:597f899f4ed42a38df7b0e46714880fb4e19a25c2f66e5c908805466721760f5"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7dbdce0c534bbf52274b94768b3498abdf675a691fec5f751b6057b3030f34c1"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:22960019a842777a9fa5134c2364efaed5fbf9610ddc5c904bd3a400973b0eb8"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7f5a3ffc731494f1a57bd91c47dc483a1e10048131ffb52d901bfe2beb6102e8"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7ef6b5942e6bfc5706301a18a62300c60db9af7f6368042227ccb7eeb22d0892"},
{file = "regex-2022.10.31-cp39-cp39-win32.whl", hash = "sha256:395161bbdbd04a8333b9ff9763a05e9ceb4fe210e3c7690f5e68cedd3d65d8e1"},
{file = "regex-2022.10.31-cp39-cp39-win_amd64.whl", hash = "sha256:957403a978e10fb3ca42572a23e6f7badff39aa1ce2f4ade68ee452dc6807692"},
{file = "regex-2022.10.31.tar.gz", hash = "sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83"},
]
[[package]]
name = "requests"
version = "2.28.2"
description = "Python HTTP for Humans."
category = "main"
optional = false
python-versions = ">=3.7, <4"
files = [
{file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
{file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<1.27"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
[[package]]
name = "urllib3"
version = "1.26.14"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
{file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"},
{file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "watchdog"
version = "2.1.9"
description = "Filesystem events monitoring"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"},
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d"},
{file = "watchdog-2.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658"},
{file = "watchdog-2.1.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591"},
{file = "watchdog-2.1.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33"},
{file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846"},
{file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3"},
{file = "watchdog-2.1.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654"},
{file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39"},
{file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7"},
{file = "watchdog-2.1.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd"},
{file = "watchdog-2.1.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3"},
{file = "watchdog-2.1.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d"},
{file = "watchdog-2.1.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9"},
{file = "watchdog-2.1.9-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213"},
{file = "watchdog-2.1.9-py3-none-manylinux2014_armv7l.whl", hash = "sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892"},
{file = "watchdog-2.1.9-py3-none-manylinux2014_i686.whl", hash = "sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153"},
{file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64.whl", hash = "sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306"},
{file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412"},
{file = "watchdog-2.1.9-py3-none-manylinux2014_s390x.whl", hash = "sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1"},
{file = "watchdog-2.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6"},
{file = "watchdog-2.1.9-py3-none-win32.whl", hash = "sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1"},
{file = "watchdog-2.1.9-py3-none-win_amd64.whl", hash = "sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c"},
{file = "watchdog-2.1.9-py3-none-win_ia64.whl", hash = "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428"},
{file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"},
]
[package.extras]
watchmedo = ["PyYAML (>=3.10)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "a0df662c99e9a84d2274616cea45eb315004b70884a296b6db240d790943f1b5"

View file

@ -1,15 +0,0 @@
[tool.poetry]
name = "docs"
version = "0.1.0"
description = ""
authors = ["Hayden <64056131+hay-kot@users.noreply.github.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.10"
mkdocs-material = "^9.0.5"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

1
docs/requirements.txt Normal file
View file

@ -0,0 +1 @@
mkdocs-material==9.1.1

View file

@ -1,8 +1,8 @@
<template>
<div v-if="!inline" class="form-control w-full">
<label class="label cursor-pointer">
<span class="label-text"> {{ label }}</span>
<input v-model="value" type="checkbox" class="checkbox checkbox-primary" />
<span class="label-text"> {{ label }}</span>
</label>
</div>
<div v-else class="label cursor-pointer sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">

View file

@ -0,0 +1,59 @@
import { faker } from "@faker-js/faker";
import { describe, expect, test } from "vitest";
import { factories } from "../factories";
describe("basic notifier workflows", () => {
test("user should be able to create, update, and delete a notifier", async () => {
const { client } = await factories.client.singleUse();
// Create Notifier
const result = await client.notifiers.create({
name: faker.name.firstName(),
url: "discord://" + faker.random.alphaNumeric(10),
isActive: true,
});
expect(result.error).toBeFalsy();
expect(result.status).toBe(201);
expect(result.data).toBeTruthy();
const notifier = result.data;
// Update Notifier with new URL
{
const updateData = {
name: faker.name.firstName(),
url: "discord://" + faker.random.alphaNumeric(10),
isActive: true,
};
const updateResult = await client.notifiers.update(notifier.id, updateData);
expect(updateResult.error).toBeFalsy();
expect(updateResult.status).toBe(200);
expect(updateResult.data).toBeTruthy();
expect(updateResult.data.name).not.toBe(notifier.name);
}
// Update Notifier with empty URL
{
const updateData = {
name: faker.name.firstName(),
url: null,
isActive: true,
};
const updateResult = await client.notifiers.update(notifier.id, updateData);
expect(updateResult.error).toBeFalsy();
expect(updateResult.status).toBe(200);
expect(updateResult.data).toBeTruthy();
expect(updateResult.data.name).not.toBe(notifier.name);
}
// Delete Notifier
{
const deleteResult = await client.notifiers.delete(notifier.id);
expect(deleteResult.error).toBeFalsy();
expect(deleteResult.status).toBe(204);
}
});
});

View file

@ -0,0 +1,28 @@
import { BaseAPI, route } from "../base";
import { NotifierCreate, NotifierOut, NotifierUpdate } from "../types/data-contracts";
export class NotifiersAPI extends BaseAPI {
getAll() {
return this.http.get<NotifierOut[]>({ url: route("/notifiers") });
}
create(body: NotifierCreate) {
return this.http.post<NotifierCreate, NotifierOut>({ url: route("/notifiers"), body });
}
update(id: string, body: NotifierUpdate) {
if (body.url === "") {
body.url = null;
}
return this.http.put<NotifierUpdate, NotifierOut>({ url: route(`/notifiers/${id}`), body });
}
delete(id: string) {
return this.http.delete<void>({ url: route(`/notifiers/${id}`) });
}
test(url: string) {
return this.http.post<{ url: string }, null>({ url: route(`/notifiers/test`), body: { url } });
}
}

View file

@ -267,6 +267,36 @@ export interface MaintenanceLog {
itemId: string;
}
export interface NotifierCreate {
isActive: boolean;
/**
* @minLength 1
* @maxLength 255
*/
name: string;
url: string;
}
export interface NotifierOut {
createdAt: Date | string;
groupId: string;
id: string;
isActive: boolean;
name: string;
updatedAt: Date | string;
userId: string;
}
export interface NotifierUpdate {
isActive: boolean;
/**
* @minLength 1
* @maxLength 255
*/
name: string;
url: string | null;
}
export interface PaginationResultItemSummary {
items: ItemSummary[];
page: number;

View file

@ -8,6 +8,7 @@ import { ActionsAPI } from "./classes/actions";
import { StatsAPI } from "./classes/stats";
import { AssetsApi } from "./classes/assets";
import { ReportsAPI } from "./classes/reports";
import { NotifiersAPI } from "./classes/notifiers";
import { Requests } from "~~/lib/requests";
export class UserClient extends BaseAPI {
@ -20,6 +21,7 @@ export class UserClient extends BaseAPI {
stats: StatsAPI;
assets: AssetsApi;
reports: ReportsAPI;
notifiers: NotifiersAPI;
constructor(requests: Requests, attachmentToken: string) {
super(requests, attachmentToken);
@ -33,6 +35,7 @@ export class UserClient extends BaseAPI {
this.stats = new StatsAPI(requests);
this.assets = new AssetsApi(requests);
this.reports = new ReportsAPI(requests);
this.notifiers = new NotifiersAPI(requests);
Object.freeze(this);
}

View file

@ -2,6 +2,7 @@
import { Detail } from "~~/components/global/DetailsSection/types";
import { themes } from "~~/lib/data/themes";
import { currencies, Currency } from "~~/lib/data/currency";
import { NotifierCreate, NotifierOut } from "~~/lib/api/types/data-contracts";
definePageMeta({
middleware: ["auth"],
@ -167,6 +168,118 @@
passwordChange.current = "";
passwordChange.loading = false;
}
// ===========================================================
// Notifiers
const notifiers = useAsyncData(async () => {
const { data } = await api.notifiers.getAll();
return data;
});
const targetID = ref("");
const notifier = ref<NotifierCreate | null>(null);
const notifierDialog = ref(false);
function openNotifierDialog(v: NotifierOut | null) {
if (v) {
targetID.value = v.id;
notifier.value = {
name: v.name,
url: "",
isActive: v.isActive,
};
} else {
notifier.value = {
name: "",
url: "",
isActive: true,
};
}
notifierDialog.value = true;
}
async function createNotifier() {
if (!notifier.value) {
return;
}
if (targetID.value) {
await editNotifier();
return;
}
const result = await api.notifiers.create({
name: notifier.value.name,
url: notifier.value.url || "",
isActive: notifier.value.isActive,
});
if (result.error) {
notify.error("Failed to create notifier.");
}
notifier.value = null;
notifierDialog.value = false;
await notifiers.refresh();
}
async function editNotifier() {
if (!notifier.value) {
return;
}
const result = await api.notifiers.update(targetID.value, {
name: notifier.value.name,
url: notifier.value.url || "",
isActive: notifier.value.isActive,
});
if (result.error) {
notify.error("Failed to update notifier.");
}
notifier.value = null;
notifierDialog.value = false;
targetID.value = "";
await notifiers.refresh();
}
async function deleteNotifier(id: string) {
const result = await confirm.open("Are you sure you want to delete this notifier?");
if (result.isCanceled) {
return;
}
const { error } = await api.notifiers.delete(id);
if (error) {
notify.error("Failed to delete notifier.");
return;
}
await notifiers.refresh();
}
async function testNotifier() {
if (!notifier.value) {
return;
}
const { error } = await api.notifiers.test(notifier.value.url);
if (error) {
notify.error("Failed to test notifier.");
return;
}
notify.success("Notifier test successful.");
}
</script>
<template>
@ -190,6 +303,24 @@
</div>
</BaseModal>
<BaseModal v-model="notifierDialog">
<template #title> {{ notifier ? "Edit" : "Create" }} Notifier </template>
<form @submit.prevent="createNotifier">
<template v-if="notifier">
<FormTextField v-model="notifier.name" label="Name" />
<FormTextField v-model="notifier.url" label="URL" />
<div class="max-w-[100px]">
<FormCheckbox v-model="notifier.isActive" label="Enabled" />
</div>
</template>
<div class="flex gap-2 justify-between mt-4">
<BaseButton :disabled="!(notifier && notifier.url)" type="button" @click="testNotifier"> Test </BaseButton>
<BaseButton type="submit"> Submit </BaseButton>
</div>
</form>
</BaseModal>
<BaseContainer class="flex flex-col gap-4 mb-6">
<BaseCard>
<template #title>
@ -218,6 +349,50 @@
</div>
</BaseCard>
<BaseCard>
<template #title>
<BaseSectionHeader>
<Icon name="mdi-megaphone" class="mr-2 -mt-1 text-base-600" />
<span class="text-base-600"> Notifiers </span>
<template #description> Get notifications for up coming maintenance reminders </template>
</BaseSectionHeader>
</template>
<div v-if="notifiers.data.value" class="mx-4 divide-y divide-gray-400 rounded-md border border-gray-400">
<article v-for="n in notifiers.data.value" :key="n.id" class="p-2">
<div class="flex flex-wrap items-center gap-2">
<p class="mr-auto text-lg">{{ n.name }}</p>
<div class="flex gap-2 justify-end">
<div class="tooltip" data-tip="Delete">
<button class="btn btn-sm btn-square" @click="deleteNotifier(n.id)">
<Icon name="mdi-delete" />
</button>
</div>
<div class="tooltip" data-tip="Edit">
<button class="btn btn-sm btn-square" @click="openNotifierDialog(n)">
<Icon name="mdi-pencil" />
</button>
</div>
</div>
</div>
<div class="flex justify-between py-1 flex-wrap text-sm">
<p>
<span v-if="n.isActive" class="badge badge-success"> Active </span>
<span v-else class="badge badge-error"> Inactive</span>
</p>
<p>
Created
<DateTime format="relative" datetime-type="time" :date="n.createdAt" />
</p>
</div>
</article>
</div>
<div class="p-4">
<BaseButton size="sm" @click="openNotifierDialog"> Create </BaseButton>
</div>
</BaseCard>
<BaseCard>
<template #title>
<BaseSectionHeader class="pb-0">
@ -233,8 +408,8 @@
<FormSelect v-model="currency" label="Currency Format" :items="currencies" />
<p class="m-2 text-sm">Example: {{ currencyExample }}</p>
<div class="mt-4 flex justify-end">
<BaseButton @click="updateGroup"> Update Group </BaseButton>
<div class="mt-4">
<BaseButton size="sm" @click="updateGroup"> Update Group </BaseButton>
</div>
</div>
</BaseCard>
@ -299,7 +474,7 @@
</BaseSectionHeader>
<div class="py-4 border-t-2 border-gray-300">
<BaseButton class="btn-error" @click="deleteProfile"> Delete Account </BaseButton>
<BaseButton size="sm" class="btn-error" @click="deleteProfile"> Delete Account </BaseButton>
</div>
</template>
</BaseCard>