From 9bfed31400ce57f717a56e691c49b350b78a9aae Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Sat, 30 Sep 2023 15:59:25 +0100 Subject: [PATCH] add update category endpoint and unique slug+metadata to categories --- api/openapi.yaml | 58 ++ app/resources/category/db.go | 63 +- app/resources/category/dto.go | 4 + app/resources/category/repo.go | 52 +- app/services/category/service.go | 33 + app/transports/openapi/bindings/categories.go | 16 + go.sum | 8 + internal/ent/category.go | 29 +- internal/ent/category/category.go | 6 + internal/ent/category/where.go | 80 +++ internal/ent/category_create.go | 123 ++++ internal/ent/category_update.go | 54 ++ internal/ent/migrate/schema.go | 4 +- internal/ent/mutation.go | 134 +++- internal/ent/runtime.go | 8 +- internal/ent/schema/category.go | 6 +- internal/openapi/generated.go | 591 ++++++++++++++---- web/src/api/openapi/categories.ts | 17 + .../openapi/schemas/categoryCommonProps.ts | 4 + .../openapi/schemas/categoryInitialProps.ts | 4 + .../openapi/schemas/categoryMutableProps.ts | 19 + web/src/api/openapi/schemas/categorySlug.ts | 12 + .../api/openapi/schemas/categoryUpdateBody.ts | 10 + .../schemas/categoryUpdateOKResponse.ts | 13 + web/src/api/openapi/schemas/index.ts | 4 + 25 files changed, 1155 insertions(+), 197 deletions(-) create mode 100644 web/src/api/openapi/schemas/categoryMutableProps.ts create mode 100644 web/src/api/openapi/schemas/categorySlug.ts create mode 100644 web/src/api/openapi/schemas/categoryUpdateBody.ts create mode 100644 web/src/api/openapi/schemas/categoryUpdateOKResponse.ts diff --git a/api/openapi.yaml b/api/openapi.yaml index 7be4ba569..4b375ba8f 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -469,6 +469,19 @@ paths: default: { $ref: "#/components/responses/InternalServerError" } "200": { $ref: "#/components/responses/CategoryListOK" } + /v1/categories/{category_id}: + patch: + operationId: CategoryUpdate + description: Create a category for organising posts. + tags: [categories] + parameters: [$ref: "#/components/parameters/CategoryIDParam"] + requestBody: { $ref: "#/components/requestBodies/CategoryUpdate" } + responses: + default: { $ref: "#/components/responses/InternalServerError" } + "400": { $ref: "#/components/responses/BadRequest" } + "401": { $ref: "#/components/responses/Unauthorised" } + "200": { $ref: "#/components/responses/CategoryUpdateOK" } + # # 888 888 888 # 888 888 888 @@ -849,6 +862,14 @@ components: schema: type: string + CategoryIDParam: + description: Unique category ID. + name: category_id + in: path + required: true + schema: + $ref: "#/components/schemas/Identifier" + CollectionIDParam: description: Unique collection ID. name: collection_id @@ -927,6 +948,11 @@ components: application/json: schema: { $ref: "#/components/schemas/CategoryIdentifierList" } + CategoryUpdate: + content: + application/json: + schema: { $ref: "#/components/schemas/CategoryMutableProps" } + ThreadCreate: content: application/json: @@ -1098,6 +1124,13 @@ components: schema: $ref: "#/components/schemas/Category" + CategoryUpdateOK: + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/Category" + CategoryListOK: description: OK content: @@ -1896,6 +1929,8 @@ components: properties: name: $ref: "#/components/schemas/CategoryName" + slug: + $ref: "#/components/schemas/CategorySlug" description: type: string colour: @@ -1904,6 +1939,7 @@ components: type: integer admin: type: boolean + meta: { $ref: "#/components/schemas/Metadata" } CategoryInitialProps: type: object @@ -1911,17 +1947,39 @@ components: properties: name: $ref: "#/components/schemas/CategoryName" + slug: + $ref: "#/components/schemas/CategorySlug" description: type: string colour: type: string admin: type: boolean + meta: { $ref: "#/components/schemas/Metadata" } + + CategoryMutableProps: + type: object + properties: + name: + $ref: "#/components/schemas/CategoryName" + slug: + $ref: "#/components/schemas/CategorySlug" + description: + type: string + colour: + type: string + admin: + type: boolean + meta: { $ref: "#/components/schemas/Metadata" } CategoryName: description: A category's user-facing name. type: string + CategorySlug: + description: A category's URL-safe slug. + type: string + CategoryNameList: description: A list of category names. type: array diff --git a/app/resources/category/db.go b/app/resources/category/db.go index 3fbf034a7..463b8ad0f 100644 --- a/app/resources/category/db.go +++ b/app/resources/category/db.go @@ -9,6 +9,7 @@ import ( "github.com/Southclaws/fault/fctx" "github.com/Southclaws/fault/fmsg" "github.com/Southclaws/fault/ftag" + "github.com/gosimple/slug" "github.com/rs/xid" "go.uber.org/multierr" @@ -16,7 +17,6 @@ import ( "github.com/Southclaws/storyden/internal/ent/category" "github.com/Southclaws/storyden/internal/ent/post" "github.com/Southclaws/storyden/internal/ent/predicate" - "github.com/Southclaws/storyden/internal/utils" ) type database struct { @@ -27,27 +27,22 @@ func New(db *ent.Client) Repository { return &database{db} } -func (d *database) CreateCategory(ctx context.Context, name, desc, colour string, sort int, admin bool, opts ...option) (*Category, error) { - insert := Category{ - Name: name, - Description: desc, - Colour: colour, - Sort: sort, - Admin: admin, - } +func (d *database) CreateCategory(ctx context.Context, name, desc, colour string, sort int, admin bool, opts ...Option) (*Category, error) { + create := d.db.Category.Create() + mutation := create.Mutation() + + mutation.SetName(name) + mutation.SetSlug(slug.Make(name)) + mutation.SetDescription(desc) + mutation.SetColour(colour) + mutation.SetSort(sort) + mutation.SetAdmin(admin) - for _, v := range opts { - v(&insert) + for _, fn := range opts { + fn(mutation) } - id, err := d.db.Category. - Create(). - SetName(insert.Name). - SetDescription(insert.Description). - SetColour(insert.Colour). - SetSort(insert.Sort). - SetAdmin(insert.Admin). - SetNillableID(utils.OptionalID(xid.ID(insert.ID))). + id, err := create. OnConflictColumns(category.FieldID). UpdateNewValues(). ID(ctx) @@ -178,33 +173,15 @@ func (d *database) Reorder(ctx context.Context, ids []CategoryID) ([]*Category, return newcats, nil } -func (d *database) UpdateCategory(ctx context.Context, id CategoryID, name, desc, colour *string, sort *int, admin *bool) (*Category, error) { - u := d.db.Category.UpdateOneID(xid.ID(id)) - - // TODO: Write a less explicit, more ergonomic way to do this: - - //nocheck:wsl - if name != nil { - u.SetName(*name) - } - - if desc != nil { - u.SetDescription(*desc) - } - - if colour != nil { - u.SetColour(*colour) - } - - if sort != nil { - u.SetSort(*sort) - } +func (d *database) UpdateCategory(ctx context.Context, id CategoryID, opts ...Option) (*Category, error) { + update := d.db.Category.UpdateOneID(xid.ID(id)) + mutation := update.Mutation() - if admin != nil { - u.SetAdmin(*admin) + for _, fn := range opts { + fn(mutation) } - c, err := u.Save(ctx) + c, err := update.Save(ctx) if err != nil { return nil, fault.Wrap(err, fctx.With(ctx), ftag.With(ftag.Internal)) } diff --git a/app/resources/category/dto.go b/app/resources/category/dto.go index 1c02da2d9..ddadcf28c 100644 --- a/app/resources/category/dto.go +++ b/app/resources/category/dto.go @@ -21,12 +21,14 @@ type PostMeta struct { type Category struct { ID CategoryID Name string + Slug string Description string Colour string Sort int Admin bool Recent []PostMeta PostCount int + Metadata map[string]any } func PostMetaFromModel(p *ent.Post) *PostMeta { @@ -55,10 +57,12 @@ func FromModel(c *ent.Category) *Category { return &Category{ ID: CategoryID(c.ID), Name: c.Name, + Slug: c.Slug, Description: c.Description, Colour: c.Colour, Sort: c.Sort, Admin: c.Admin, Recent: recent, + Metadata: c.Metadata, } } diff --git a/app/resources/category/repo.go b/app/resources/category/repo.go index 48325618c..08541e7bf 100644 --- a/app/resources/category/repo.go +++ b/app/resources/category/repo.go @@ -2,9 +2,13 @@ package category import ( "context" + + "github.com/rs/xid" + + "github.com/Southclaws/storyden/internal/ent" ) -type option func(*Category) +type Option func(*ent.CategoryMutation) type Repository interface { CreateCategory(ctx context.Context, @@ -13,16 +17,52 @@ type Repository interface { colour string, sort int, admin bool, - opts ...option) (*Category, error) + opts ...Option) (*Category, error) GetCategories(ctx context.Context, admin bool) ([]*Category, error) Reorder(ctx context.Context, ids []CategoryID) ([]*Category, error) - UpdateCategory(ctx context.Context, id CategoryID, name, desc, colour *string, sort *int, admin *bool) (*Category, error) + UpdateCategory(ctx context.Context, id CategoryID, opts ...Option) (*Category, error) DeleteCategory(ctx context.Context, id CategoryID, moveto CategoryID) (*Category, error) } -func WithID(id CategoryID) option { - return func(c *Category) { - c.ID = id +func WithID(id CategoryID) Option { + return func(cm *ent.CategoryMutation) { + cm.SetID(xid.ID(id)) + } +} + +func WithName(v string) Option { + return func(cm *ent.CategoryMutation) { + cm.SetName(v) + } +} + +func WithSlug(v string) Option { + return func(cm *ent.CategoryMutation) { + cm.SetSlug(v) + } +} + +func WithDescription(v string) Option { + return func(cm *ent.CategoryMutation) { + cm.SetDescription(v) + } +} + +func WithColour(v string) Option { + return func(cm *ent.CategoryMutation) { + cm.SetColour(v) + } +} + +func WithAdmin(v bool) Option { + return func(cm *ent.CategoryMutation) { + cm.SetAdmin(v) + } +} + +func WithMeta(v map[string]any) Option { + return func(cm *ent.CategoryMutation) { + cm.SetMetadata(v) } } diff --git a/app/services/category/service.go b/app/services/category/service.go index 11ea8abb3..91dee3b1d 100644 --- a/app/services/category/service.go +++ b/app/services/category/service.go @@ -18,13 +18,16 @@ import ( type Service interface { Create(ctx context.Context, name string, description string, colour string, admin bool) (*category.Category, error) Reorder(ctx context.Context, ids []category.CategoryID) ([]*category.Category, error) + Update(ctx context.Context, id category.CategoryID, partial Partial) (*category.Category, error) } type Partial struct { Name opt.Optional[string] + Slug opt.Optional[string] Description opt.Optional[string] Colour opt.Optional[string] Admin opt.Optional[bool] + Meta opt.Optional[map[string]any] } func Build() fx.Option { @@ -80,6 +83,36 @@ func (s *service) Reorder(ctx context.Context, ids []category.CategoryID) ([]*ca return cats, nil } +func (s *service) Update(ctx context.Context, id category.CategoryID, partial Partial) (*category.Category, error) { + opts := []category.Option{} + + if v, ok := partial.Name.Get(); ok { + opts = append(opts, category.WithName(v)) + } + if v, ok := partial.Slug.Get(); ok { + opts = append(opts, category.WithSlug(v)) + } + if v, ok := partial.Description.Get(); ok { + opts = append(opts, category.WithDescription(v)) + } + if v, ok := partial.Colour.Get(); ok { + opts = append(opts, category.WithColour(v)) + } + if v, ok := partial.Admin.Get(); ok { + opts = append(opts, category.WithAdmin(v)) + } + if v, ok := partial.Meta.Get(); ok { + opts = append(opts, category.WithMeta(v)) + } + + cat, err := s.category_repo.UpdateCategory(ctx, id, opts...) + if err != nil { + return nil, fault.Wrap(err, fctx.With(ctx)) + } + + return cat, nil +} + func (s *service) authorise(ctx context.Context) error { aid, err := authentication.GetAccountID(ctx) if err != nil { diff --git a/app/transports/openapi/bindings/categories.go b/app/transports/openapi/bindings/categories.go index e9d22cfe5..f0de3e588 100644 --- a/app/transports/openapi/bindings/categories.go +++ b/app/transports/openapi/bindings/categories.go @@ -64,3 +64,19 @@ func (c Categories) CategoryUpdateOrder(ctx context.Context, request openapi.Cat }, }, nil } + +func (c Categories) CategoryUpdate(ctx context.Context, request openapi.CategoryUpdateRequestObject) (openapi.CategoryUpdateResponseObject, error) { + cat, err := c.category_svc.Update(ctx, category.CategoryID(deserialiseID(request.CategoryId)), category_svc.Partial{ + Name: []string{}, + Description: []string{}, + Colour: []string{}, + Admin: []bool{}, + }) + if err != nil { + return nil, fault.Wrap(err, fctx.With(ctx)) + } + + return openapi.CategoryUpdate200JSONResponse{ + CategoryUpdateOKJSONResponse: openapi.CategoryUpdateOKJSONResponse(serialiseCategory(cat)), + }, nil +} diff --git a/go.sum b/go.sum index 17e14116e..031c28257 100644 --- a/go.sum +++ b/go.sum @@ -310,6 +310,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mazznoer/colorgrad v0.9.1 h1:MB80JYVndKWSMEM1beNqnuOowWGhoQc3DXWXkFp6JlM= @@ -342,6 +344,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/ogen-go/ogen v0.59.0 h1:9aSSZ1KCLJIcRyjkO7IHrG0vAI6l1BO877LwTbMcX+k= github.com/ogen-go/ogen v0.59.0/go.mod h1:0MHLcWEbxwdvR+R9E05paQSRh/2vHtVSJgKqmwYyW8M= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw= github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= @@ -398,8 +402,12 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= diff --git a/internal/ent/category.go b/internal/ent/category.go index 8da98de98..9941393ac 100644 --- a/internal/ent/category.go +++ b/internal/ent/category.go @@ -3,6 +3,7 @@ package ent import ( + "encoding/json" "fmt" "strings" "time" @@ -23,6 +24,8 @@ type Category struct { UpdatedAt time.Time `json:"updated_at,omitempty"` // Name holds the value of the "name" field. Name string `json:"name,omitempty"` + // Slug holds the value of the "slug" field. + Slug string `json:"slug,omitempty"` // Description holds the value of the "description" field. Description string `json:"description,omitempty"` // Colour holds the value of the "colour" field. @@ -31,6 +34,8 @@ type Category struct { Sort int `json:"sort,omitempty"` // Admin holds the value of the "admin" field. Admin bool `json:"admin,omitempty"` + // Arbitrary metadata used by clients to store domain specific information. + Metadata map[string]interface{} `json:"metadata,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the CategoryQuery when eager-loading is set. Edges CategoryEdges `json:"edges"` @@ -59,11 +64,13 @@ func (*Category) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) for i := range columns { switch columns[i] { + case category.FieldMetadata: + values[i] = new([]byte) case category.FieldAdmin: values[i] = new(sql.NullBool) case category.FieldSort: values[i] = new(sql.NullInt64) - case category.FieldName, category.FieldDescription, category.FieldColour: + case category.FieldName, category.FieldSlug, category.FieldDescription, category.FieldColour: values[i] = new(sql.NullString) case category.FieldCreatedAt, category.FieldUpdatedAt: values[i] = new(sql.NullTime) @@ -108,6 +115,12 @@ func (c *Category) assignValues(columns []string, values []any) error { } else if value.Valid { c.Name = value.String } + case category.FieldSlug: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field slug", values[i]) + } else if value.Valid { + c.Slug = value.String + } case category.FieldDescription: if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field description", values[i]) @@ -132,6 +145,14 @@ func (c *Category) assignValues(columns []string, values []any) error { } else if value.Valid { c.Admin = value.Bool } + case category.FieldMetadata: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field metadata", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &c.Metadata); err != nil { + return fmt.Errorf("unmarshal field metadata: %w", err) + } + } } } return nil @@ -174,6 +195,9 @@ func (c *Category) String() string { builder.WriteString("name=") builder.WriteString(c.Name) builder.WriteString(", ") + builder.WriteString("slug=") + builder.WriteString(c.Slug) + builder.WriteString(", ") builder.WriteString("description=") builder.WriteString(c.Description) builder.WriteString(", ") @@ -185,6 +209,9 @@ func (c *Category) String() string { builder.WriteString(", ") builder.WriteString("admin=") builder.WriteString(fmt.Sprintf("%v", c.Admin)) + builder.WriteString(", ") + builder.WriteString("metadata=") + builder.WriteString(fmt.Sprintf("%v", c.Metadata)) builder.WriteByte(')') return builder.String() } diff --git a/internal/ent/category/category.go b/internal/ent/category/category.go index 60a24f134..fe66cffa9 100644 --- a/internal/ent/category/category.go +++ b/internal/ent/category/category.go @@ -19,6 +19,8 @@ const ( FieldUpdatedAt = "updated_at" // FieldName holds the string denoting the name field in the database. FieldName = "name" + // FieldSlug holds the string denoting the slug field in the database. + FieldSlug = "slug" // FieldDescription holds the string denoting the description field in the database. FieldDescription = "description" // FieldColour holds the string denoting the colour field in the database. @@ -27,6 +29,8 @@ const ( FieldSort = "sort" // FieldAdmin holds the string denoting the admin field in the database. FieldAdmin = "admin" + // FieldMetadata holds the string denoting the metadata field in the database. + FieldMetadata = "metadata" // EdgePosts holds the string denoting the posts edge name in mutations. EdgePosts = "posts" // Table holds the table name of the category in the database. @@ -46,10 +50,12 @@ var Columns = []string{ FieldCreatedAt, FieldUpdatedAt, FieldName, + FieldSlug, FieldDescription, FieldColour, FieldSort, FieldAdmin, + FieldMetadata, } // ValidColumn reports if the column name is valid (part of the table columns). diff --git a/internal/ent/category/where.go b/internal/ent/category/where.go index 46cd2b512..88462cb46 100644 --- a/internal/ent/category/where.go +++ b/internal/ent/category/where.go @@ -71,6 +71,11 @@ func Name(v string) predicate.Category { return predicate.Category(sql.FieldEQ(FieldName, v)) } +// Slug applies equality check predicate on the "slug" field. It's identical to SlugEQ. +func Slug(v string) predicate.Category { + return predicate.Category(sql.FieldEQ(FieldSlug, v)) +} + // Description applies equality check predicate on the "description" field. It's identical to DescriptionEQ. func Description(v string) predicate.Category { return predicate.Category(sql.FieldEQ(FieldDescription, v)) @@ -236,6 +241,71 @@ func NameContainsFold(v string) predicate.Category { return predicate.Category(sql.FieldContainsFold(FieldName, v)) } +// SlugEQ applies the EQ predicate on the "slug" field. +func SlugEQ(v string) predicate.Category { + return predicate.Category(sql.FieldEQ(FieldSlug, v)) +} + +// SlugNEQ applies the NEQ predicate on the "slug" field. +func SlugNEQ(v string) predicate.Category { + return predicate.Category(sql.FieldNEQ(FieldSlug, v)) +} + +// SlugIn applies the In predicate on the "slug" field. +func SlugIn(vs ...string) predicate.Category { + return predicate.Category(sql.FieldIn(FieldSlug, vs...)) +} + +// SlugNotIn applies the NotIn predicate on the "slug" field. +func SlugNotIn(vs ...string) predicate.Category { + return predicate.Category(sql.FieldNotIn(FieldSlug, vs...)) +} + +// SlugGT applies the GT predicate on the "slug" field. +func SlugGT(v string) predicate.Category { + return predicate.Category(sql.FieldGT(FieldSlug, v)) +} + +// SlugGTE applies the GTE predicate on the "slug" field. +func SlugGTE(v string) predicate.Category { + return predicate.Category(sql.FieldGTE(FieldSlug, v)) +} + +// SlugLT applies the LT predicate on the "slug" field. +func SlugLT(v string) predicate.Category { + return predicate.Category(sql.FieldLT(FieldSlug, v)) +} + +// SlugLTE applies the LTE predicate on the "slug" field. +func SlugLTE(v string) predicate.Category { + return predicate.Category(sql.FieldLTE(FieldSlug, v)) +} + +// SlugContains applies the Contains predicate on the "slug" field. +func SlugContains(v string) predicate.Category { + return predicate.Category(sql.FieldContains(FieldSlug, v)) +} + +// SlugHasPrefix applies the HasPrefix predicate on the "slug" field. +func SlugHasPrefix(v string) predicate.Category { + return predicate.Category(sql.FieldHasPrefix(FieldSlug, v)) +} + +// SlugHasSuffix applies the HasSuffix predicate on the "slug" field. +func SlugHasSuffix(v string) predicate.Category { + return predicate.Category(sql.FieldHasSuffix(FieldSlug, v)) +} + +// SlugEqualFold applies the EqualFold predicate on the "slug" field. +func SlugEqualFold(v string) predicate.Category { + return predicate.Category(sql.FieldEqualFold(FieldSlug, v)) +} + +// SlugContainsFold applies the ContainsFold predicate on the "slug" field. +func SlugContainsFold(v string) predicate.Category { + return predicate.Category(sql.FieldContainsFold(FieldSlug, v)) +} + // DescriptionEQ applies the EQ predicate on the "description" field. func DescriptionEQ(v string) predicate.Category { return predicate.Category(sql.FieldEQ(FieldDescription, v)) @@ -416,6 +486,16 @@ func AdminNEQ(v bool) predicate.Category { return predicate.Category(sql.FieldNEQ(FieldAdmin, v)) } +// MetadataIsNil applies the IsNil predicate on the "metadata" field. +func MetadataIsNil() predicate.Category { + return predicate.Category(sql.FieldIsNull(FieldMetadata)) +} + +// MetadataNotNil applies the NotNil predicate on the "metadata" field. +func MetadataNotNil() predicate.Category { + return predicate.Category(sql.FieldNotNull(FieldMetadata)) +} + // HasPosts applies the HasEdge predicate on the "posts" edge. func HasPosts() predicate.Category { return predicate.Category(func(s *sql.Selector) { diff --git a/internal/ent/category_create.go b/internal/ent/category_create.go index 74d5cdb08..57f6b43a5 100644 --- a/internal/ent/category_create.go +++ b/internal/ent/category_create.go @@ -59,6 +59,12 @@ func (cc *CategoryCreate) SetName(s string) *CategoryCreate { return cc } +// SetSlug sets the "slug" field. +func (cc *CategoryCreate) SetSlug(s string) *CategoryCreate { + cc.mutation.SetSlug(s) + return cc +} + // SetDescription sets the "description" field. func (cc *CategoryCreate) SetDescription(s string) *CategoryCreate { cc.mutation.SetDescription(s) @@ -115,6 +121,12 @@ func (cc *CategoryCreate) SetNillableAdmin(b *bool) *CategoryCreate { return cc } +// SetMetadata sets the "metadata" field. +func (cc *CategoryCreate) SetMetadata(m map[string]interface{}) *CategoryCreate { + cc.mutation.SetMetadata(m) + return cc +} + // SetID sets the "id" field. func (cc *CategoryCreate) SetID(x xid.ID) *CategoryCreate { cc.mutation.SetID(x) @@ -220,6 +232,9 @@ func (cc *CategoryCreate) check() error { if _, ok := cc.mutation.Name(); !ok { return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Category.name"`)} } + if _, ok := cc.mutation.Slug(); !ok { + return &ValidationError{Name: "slug", err: errors.New(`ent: missing required field "Category.slug"`)} + } if _, ok := cc.mutation.Description(); !ok { return &ValidationError{Name: "description", err: errors.New(`ent: missing required field "Category.description"`)} } @@ -285,6 +300,10 @@ func (cc *CategoryCreate) createSpec() (*Category, *sqlgraph.CreateSpec) { _spec.SetField(category.FieldName, field.TypeString, value) _node.Name = value } + if value, ok := cc.mutation.Slug(); ok { + _spec.SetField(category.FieldSlug, field.TypeString, value) + _node.Slug = value + } if value, ok := cc.mutation.Description(); ok { _spec.SetField(category.FieldDescription, field.TypeString, value) _node.Description = value @@ -301,6 +320,10 @@ func (cc *CategoryCreate) createSpec() (*Category, *sqlgraph.CreateSpec) { _spec.SetField(category.FieldAdmin, field.TypeBool, value) _node.Admin = value } + if value, ok := cc.mutation.Metadata(); ok { + _spec.SetField(category.FieldMetadata, field.TypeJSON, value) + _node.Metadata = value + } if nodes := cc.mutation.PostsIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -393,6 +416,18 @@ func (u *CategoryUpsert) UpdateName() *CategoryUpsert { return u } +// SetSlug sets the "slug" field. +func (u *CategoryUpsert) SetSlug(v string) *CategoryUpsert { + u.Set(category.FieldSlug, v) + return u +} + +// UpdateSlug sets the "slug" field to the value that was provided on create. +func (u *CategoryUpsert) UpdateSlug() *CategoryUpsert { + u.SetExcluded(category.FieldSlug) + return u +} + // SetDescription sets the "description" field. func (u *CategoryUpsert) SetDescription(v string) *CategoryUpsert { u.Set(category.FieldDescription, v) @@ -447,6 +482,24 @@ func (u *CategoryUpsert) UpdateAdmin() *CategoryUpsert { return u } +// SetMetadata sets the "metadata" field. +func (u *CategoryUpsert) SetMetadata(v map[string]interface{}) *CategoryUpsert { + u.Set(category.FieldMetadata, v) + return u +} + +// UpdateMetadata sets the "metadata" field to the value that was provided on create. +func (u *CategoryUpsert) UpdateMetadata() *CategoryUpsert { + u.SetExcluded(category.FieldMetadata) + return u +} + +// ClearMetadata clears the value of the "metadata" field. +func (u *CategoryUpsert) ClearMetadata() *CategoryUpsert { + u.SetNull(category.FieldMetadata) + return u +} + // UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. // Using this option is equivalent to using: // @@ -526,6 +579,20 @@ func (u *CategoryUpsertOne) UpdateName() *CategoryUpsertOne { }) } +// SetSlug sets the "slug" field. +func (u *CategoryUpsertOne) SetSlug(v string) *CategoryUpsertOne { + return u.Update(func(s *CategoryUpsert) { + s.SetSlug(v) + }) +} + +// UpdateSlug sets the "slug" field to the value that was provided on create. +func (u *CategoryUpsertOne) UpdateSlug() *CategoryUpsertOne { + return u.Update(func(s *CategoryUpsert) { + s.UpdateSlug() + }) +} + // SetDescription sets the "description" field. func (u *CategoryUpsertOne) SetDescription(v string) *CategoryUpsertOne { return u.Update(func(s *CategoryUpsert) { @@ -589,6 +656,27 @@ func (u *CategoryUpsertOne) UpdateAdmin() *CategoryUpsertOne { }) } +// SetMetadata sets the "metadata" field. +func (u *CategoryUpsertOne) SetMetadata(v map[string]interface{}) *CategoryUpsertOne { + return u.Update(func(s *CategoryUpsert) { + s.SetMetadata(v) + }) +} + +// UpdateMetadata sets the "metadata" field to the value that was provided on create. +func (u *CategoryUpsertOne) UpdateMetadata() *CategoryUpsertOne { + return u.Update(func(s *CategoryUpsert) { + s.UpdateMetadata() + }) +} + +// ClearMetadata clears the value of the "metadata" field. +func (u *CategoryUpsertOne) ClearMetadata() *CategoryUpsertOne { + return u.Update(func(s *CategoryUpsert) { + s.ClearMetadata() + }) +} + // Exec executes the query. func (u *CategoryUpsertOne) Exec(ctx context.Context) error { if len(u.create.conflict) == 0 { @@ -831,6 +919,20 @@ func (u *CategoryUpsertBulk) UpdateName() *CategoryUpsertBulk { }) } +// SetSlug sets the "slug" field. +func (u *CategoryUpsertBulk) SetSlug(v string) *CategoryUpsertBulk { + return u.Update(func(s *CategoryUpsert) { + s.SetSlug(v) + }) +} + +// UpdateSlug sets the "slug" field to the value that was provided on create. +func (u *CategoryUpsertBulk) UpdateSlug() *CategoryUpsertBulk { + return u.Update(func(s *CategoryUpsert) { + s.UpdateSlug() + }) +} + // SetDescription sets the "description" field. func (u *CategoryUpsertBulk) SetDescription(v string) *CategoryUpsertBulk { return u.Update(func(s *CategoryUpsert) { @@ -894,6 +996,27 @@ func (u *CategoryUpsertBulk) UpdateAdmin() *CategoryUpsertBulk { }) } +// SetMetadata sets the "metadata" field. +func (u *CategoryUpsertBulk) SetMetadata(v map[string]interface{}) *CategoryUpsertBulk { + return u.Update(func(s *CategoryUpsert) { + s.SetMetadata(v) + }) +} + +// UpdateMetadata sets the "metadata" field to the value that was provided on create. +func (u *CategoryUpsertBulk) UpdateMetadata() *CategoryUpsertBulk { + return u.Update(func(s *CategoryUpsert) { + s.UpdateMetadata() + }) +} + +// ClearMetadata clears the value of the "metadata" field. +func (u *CategoryUpsertBulk) ClearMetadata() *CategoryUpsertBulk { + return u.Update(func(s *CategoryUpsert) { + s.ClearMetadata() + }) +} + // Exec executes the query. func (u *CategoryUpsertBulk) Exec(ctx context.Context) error { for i, b := range u.create.builders { diff --git a/internal/ent/category_update.go b/internal/ent/category_update.go index e1e13c831..f47937f8b 100644 --- a/internal/ent/category_update.go +++ b/internal/ent/category_update.go @@ -43,6 +43,12 @@ func (cu *CategoryUpdate) SetName(s string) *CategoryUpdate { return cu } +// SetSlug sets the "slug" field. +func (cu *CategoryUpdate) SetSlug(s string) *CategoryUpdate { + cu.mutation.SetSlug(s) + return cu +} + // SetDescription sets the "description" field. func (cu *CategoryUpdate) SetDescription(s string) *CategoryUpdate { cu.mutation.SetDescription(s) @@ -106,6 +112,18 @@ func (cu *CategoryUpdate) SetNillableAdmin(b *bool) *CategoryUpdate { return cu } +// SetMetadata sets the "metadata" field. +func (cu *CategoryUpdate) SetMetadata(m map[string]interface{}) *CategoryUpdate { + cu.mutation.SetMetadata(m) + return cu +} + +// ClearMetadata clears the value of the "metadata" field. +func (cu *CategoryUpdate) ClearMetadata() *CategoryUpdate { + cu.mutation.ClearMetadata() + return cu +} + // AddPostIDs adds the "posts" edge to the Post entity by IDs. func (cu *CategoryUpdate) AddPostIDs(ids ...xid.ID) *CategoryUpdate { cu.mutation.AddPostIDs(ids...) @@ -204,6 +222,9 @@ func (cu *CategoryUpdate) sqlSave(ctx context.Context) (n int, err error) { if value, ok := cu.mutation.Name(); ok { _spec.SetField(category.FieldName, field.TypeString, value) } + if value, ok := cu.mutation.Slug(); ok { + _spec.SetField(category.FieldSlug, field.TypeString, value) + } if value, ok := cu.mutation.Description(); ok { _spec.SetField(category.FieldDescription, field.TypeString, value) } @@ -219,6 +240,12 @@ func (cu *CategoryUpdate) sqlSave(ctx context.Context) (n int, err error) { if value, ok := cu.mutation.Admin(); ok { _spec.SetField(category.FieldAdmin, field.TypeBool, value) } + if value, ok := cu.mutation.Metadata(); ok { + _spec.SetField(category.FieldMetadata, field.TypeJSON, value) + } + if cu.mutation.MetadataCleared() { + _spec.ClearField(category.FieldMetadata, field.TypeJSON) + } if cu.mutation.PostsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -298,6 +325,12 @@ func (cuo *CategoryUpdateOne) SetName(s string) *CategoryUpdateOne { return cuo } +// SetSlug sets the "slug" field. +func (cuo *CategoryUpdateOne) SetSlug(s string) *CategoryUpdateOne { + cuo.mutation.SetSlug(s) + return cuo +} + // SetDescription sets the "description" field. func (cuo *CategoryUpdateOne) SetDescription(s string) *CategoryUpdateOne { cuo.mutation.SetDescription(s) @@ -361,6 +394,18 @@ func (cuo *CategoryUpdateOne) SetNillableAdmin(b *bool) *CategoryUpdateOne { return cuo } +// SetMetadata sets the "metadata" field. +func (cuo *CategoryUpdateOne) SetMetadata(m map[string]interface{}) *CategoryUpdateOne { + cuo.mutation.SetMetadata(m) + return cuo +} + +// ClearMetadata clears the value of the "metadata" field. +func (cuo *CategoryUpdateOne) ClearMetadata() *CategoryUpdateOne { + cuo.mutation.ClearMetadata() + return cuo +} + // AddPostIDs adds the "posts" edge to the Post entity by IDs. func (cuo *CategoryUpdateOne) AddPostIDs(ids ...xid.ID) *CategoryUpdateOne { cuo.mutation.AddPostIDs(ids...) @@ -489,6 +534,9 @@ func (cuo *CategoryUpdateOne) sqlSave(ctx context.Context) (_node *Category, err if value, ok := cuo.mutation.Name(); ok { _spec.SetField(category.FieldName, field.TypeString, value) } + if value, ok := cuo.mutation.Slug(); ok { + _spec.SetField(category.FieldSlug, field.TypeString, value) + } if value, ok := cuo.mutation.Description(); ok { _spec.SetField(category.FieldDescription, field.TypeString, value) } @@ -504,6 +552,12 @@ func (cuo *CategoryUpdateOne) sqlSave(ctx context.Context) (_node *Category, err if value, ok := cuo.mutation.Admin(); ok { _spec.SetField(category.FieldAdmin, field.TypeBool, value) } + if value, ok := cuo.mutation.Metadata(); ok { + _spec.SetField(category.FieldMetadata, field.TypeJSON, value) + } + if cuo.mutation.MetadataCleared() { + _spec.ClearField(category.FieldMetadata, field.TypeJSON) + } if cuo.mutation.PostsCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, diff --git a/internal/ent/migrate/schema.go b/internal/ent/migrate/schema.go index 48c784faf..f09584ed4 100644 --- a/internal/ent/migrate/schema.go +++ b/internal/ent/migrate/schema.go @@ -86,11 +86,13 @@ var ( {Name: "id", Type: field.TypeString, Size: 20}, {Name: "created_at", Type: field.TypeTime}, {Name: "updated_at", Type: field.TypeTime}, - {Name: "name", Type: field.TypeString}, + {Name: "name", Type: field.TypeString, Unique: true}, + {Name: "slug", Type: field.TypeString, Unique: true}, {Name: "description", Type: field.TypeString, Default: "(No description)"}, {Name: "colour", Type: field.TypeString, Default: "#8577ce"}, {Name: "sort", Type: field.TypeInt, Default: -1}, {Name: "admin", Type: field.TypeBool, Default: false}, + {Name: "metadata", Type: field.TypeJSON, Nullable: true}, } // CategoriesTable holds the schema information for the "categories" table. CategoriesTable = &schema.Table{ diff --git a/internal/ent/mutation.go b/internal/ent/mutation.go index 18492a91d..d9febebf3 100644 --- a/internal/ent/mutation.go +++ b/internal/ent/mutation.go @@ -2858,11 +2858,13 @@ type CategoryMutation struct { created_at *time.Time updated_at *time.Time name *string + slug *string description *string colour *string sort *int addsort *int admin *bool + metadata *map[string]interface{} clearedFields map[string]struct{} posts map[xid.ID]struct{} removedposts map[xid.ID]struct{} @@ -3084,6 +3086,42 @@ func (m *CategoryMutation) ResetName() { m.name = nil } +// SetSlug sets the "slug" field. +func (m *CategoryMutation) SetSlug(s string) { + m.slug = &s +} + +// Slug returns the value of the "slug" field in the mutation. +func (m *CategoryMutation) Slug() (r string, exists bool) { + v := m.slug + if v == nil { + return + } + return *v, true +} + +// OldSlug returns the old "slug" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldSlug(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSlug is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSlug requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSlug: %w", err) + } + return oldValue.Slug, nil +} + +// ResetSlug resets all changes to the "slug" field. +func (m *CategoryMutation) ResetSlug() { + m.slug = nil +} + // SetDescription sets the "description" field. func (m *CategoryMutation) SetDescription(s string) { m.description = &s @@ -3248,6 +3286,55 @@ func (m *CategoryMutation) ResetAdmin() { m.admin = nil } +// SetMetadata sets the "metadata" field. +func (m *CategoryMutation) SetMetadata(value map[string]interface{}) { + m.metadata = &value +} + +// Metadata returns the value of the "metadata" field in the mutation. +func (m *CategoryMutation) Metadata() (r map[string]interface{}, exists bool) { + v := m.metadata + if v == nil { + return + } + return *v, true +} + +// OldMetadata returns the old "metadata" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldMetadata(ctx context.Context) (v map[string]interface{}, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldMetadata is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldMetadata requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldMetadata: %w", err) + } + return oldValue.Metadata, nil +} + +// ClearMetadata clears the value of the "metadata" field. +func (m *CategoryMutation) ClearMetadata() { + m.metadata = nil + m.clearedFields[category.FieldMetadata] = struct{}{} +} + +// MetadataCleared returns if the "metadata" field was cleared in this mutation. +func (m *CategoryMutation) MetadataCleared() bool { + _, ok := m.clearedFields[category.FieldMetadata] + return ok +} + +// ResetMetadata resets all changes to the "metadata" field. +func (m *CategoryMutation) ResetMetadata() { + m.metadata = nil + delete(m.clearedFields, category.FieldMetadata) +} + // AddPostIDs adds the "posts" edge to the Post entity by ids. func (m *CategoryMutation) AddPostIDs(ids ...xid.ID) { if m.posts == nil { @@ -3336,7 +3423,7 @@ func (m *CategoryMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *CategoryMutation) Fields() []string { - fields := make([]string, 0, 7) + fields := make([]string, 0, 9) if m.created_at != nil { fields = append(fields, category.FieldCreatedAt) } @@ -3346,6 +3433,9 @@ func (m *CategoryMutation) Fields() []string { if m.name != nil { fields = append(fields, category.FieldName) } + if m.slug != nil { + fields = append(fields, category.FieldSlug) + } if m.description != nil { fields = append(fields, category.FieldDescription) } @@ -3358,6 +3448,9 @@ func (m *CategoryMutation) Fields() []string { if m.admin != nil { fields = append(fields, category.FieldAdmin) } + if m.metadata != nil { + fields = append(fields, category.FieldMetadata) + } return fields } @@ -3372,6 +3465,8 @@ func (m *CategoryMutation) Field(name string) (ent.Value, bool) { return m.UpdatedAt() case category.FieldName: return m.Name() + case category.FieldSlug: + return m.Slug() case category.FieldDescription: return m.Description() case category.FieldColour: @@ -3380,6 +3475,8 @@ func (m *CategoryMutation) Field(name string) (ent.Value, bool) { return m.Sort() case category.FieldAdmin: return m.Admin() + case category.FieldMetadata: + return m.Metadata() } return nil, false } @@ -3395,6 +3492,8 @@ func (m *CategoryMutation) OldField(ctx context.Context, name string) (ent.Value return m.OldUpdatedAt(ctx) case category.FieldName: return m.OldName(ctx) + case category.FieldSlug: + return m.OldSlug(ctx) case category.FieldDescription: return m.OldDescription(ctx) case category.FieldColour: @@ -3403,6 +3502,8 @@ func (m *CategoryMutation) OldField(ctx context.Context, name string) (ent.Value return m.OldSort(ctx) case category.FieldAdmin: return m.OldAdmin(ctx) + case category.FieldMetadata: + return m.OldMetadata(ctx) } return nil, fmt.Errorf("unknown Category field %s", name) } @@ -3433,6 +3534,13 @@ func (m *CategoryMutation) SetField(name string, value ent.Value) error { } m.SetName(v) return nil + case category.FieldSlug: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSlug(v) + return nil case category.FieldDescription: v, ok := value.(string) if !ok { @@ -3461,6 +3569,13 @@ func (m *CategoryMutation) SetField(name string, value ent.Value) error { } m.SetAdmin(v) return nil + case category.FieldMetadata: + v, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetMetadata(v) + return nil } return fmt.Errorf("unknown Category field %s", name) } @@ -3505,7 +3620,11 @@ func (m *CategoryMutation) AddField(name string, value ent.Value) error { // ClearedFields returns all nullable fields that were cleared during this // mutation. func (m *CategoryMutation) ClearedFields() []string { - return nil + var fields []string + if m.FieldCleared(category.FieldMetadata) { + fields = append(fields, category.FieldMetadata) + } + return fields } // FieldCleared returns a boolean indicating if a field with the given name was @@ -3518,6 +3637,11 @@ func (m *CategoryMutation) FieldCleared(name string) bool { // ClearField clears the value of the field with the given name. It returns an // error if the field is not defined in the schema. func (m *CategoryMutation) ClearField(name string) error { + switch name { + case category.FieldMetadata: + m.ClearMetadata() + return nil + } return fmt.Errorf("unknown Category nullable field %s", name) } @@ -3534,6 +3658,9 @@ func (m *CategoryMutation) ResetField(name string) error { case category.FieldName: m.ResetName() return nil + case category.FieldSlug: + m.ResetSlug() + return nil case category.FieldDescription: m.ResetDescription() return nil @@ -3546,6 +3673,9 @@ func (m *CategoryMutation) ResetField(name string) error { case category.FieldAdmin: m.ResetAdmin() return nil + case category.FieldMetadata: + m.ResetMetadata() + return nil } return fmt.Errorf("unknown Category field %s", name) } diff --git a/internal/ent/runtime.go b/internal/ent/runtime.go index 41904951a..9f0ff2abd 100644 --- a/internal/ent/runtime.go +++ b/internal/ent/runtime.go @@ -155,19 +155,19 @@ func init() { // category.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. category.UpdateDefaultUpdatedAt = categoryDescUpdatedAt.UpdateDefault.(func() time.Time) // categoryDescDescription is the schema descriptor for description field. - categoryDescDescription := categoryFields[1].Descriptor() + categoryDescDescription := categoryFields[2].Descriptor() // category.DefaultDescription holds the default value on creation for the description field. category.DefaultDescription = categoryDescDescription.Default.(string) // categoryDescColour is the schema descriptor for colour field. - categoryDescColour := categoryFields[2].Descriptor() + categoryDescColour := categoryFields[3].Descriptor() // category.DefaultColour holds the default value on creation for the colour field. category.DefaultColour = categoryDescColour.Default.(string) // categoryDescSort is the schema descriptor for sort field. - categoryDescSort := categoryFields[3].Descriptor() + categoryDescSort := categoryFields[4].Descriptor() // category.DefaultSort holds the default value on creation for the sort field. category.DefaultSort = categoryDescSort.Default.(int) // categoryDescAdmin is the schema descriptor for admin field. - categoryDescAdmin := categoryFields[4].Descriptor() + categoryDescAdmin := categoryFields[5].Descriptor() // category.DefaultAdmin holds the default value on creation for the admin field. category.DefaultAdmin = categoryDescAdmin.Default.(bool) // categoryDescID is the schema descriptor for id field. diff --git a/internal/ent/schema/category.go b/internal/ent/schema/category.go index 071024ec0..f15e03a6d 100644 --- a/internal/ent/schema/category.go +++ b/internal/ent/schema/category.go @@ -18,11 +18,15 @@ func (Category) Mixin() []ent.Mixin { // Fields of Category. func (Category) Fields() []ent.Field { return []ent.Field{ - field.String("name"), + field.String("name").Unique(), + field.String("slug").Unique(), field.String("description").Default("(No description)"), field.String("colour").Default("#8577ce"), field.Int("sort").Default(-1), field.Bool("admin").Default(false), + field.JSON("metadata", map[string]any{}). + Optional(). + Comment("Arbitrary metadata used by clients to store domain specific information."), } } diff --git a/internal/openapi/generated.go b/internal/openapi/generated.go index 9a573b970..19be378f8 100644 --- a/internal/openapi/generated.go +++ b/internal/openapi/generated.go @@ -338,13 +338,19 @@ type Category struct { // Id A unique identifier for this resource. Id Identifier `json:"id"` + // Meta Arbitrary metadata for the resource. + Meta *Metadata `json:"meta,omitempty"` + // Misc Arbitrary extra data stored with the resource. Misc *map[string]interface{} `json:"misc,omitempty"` // Name A category's user-facing name. Name CategoryName `json:"name"` PostCount int `json:"postCount"` - Sort int `json:"sort"` + + // Slug A category's URL-safe slug. + Slug *CategorySlug `json:"slug,omitempty"` + Sort int `json:"sort"` // UpdatedAt The time the resource was updated. UpdatedAt time.Time `json:"updatedAt"` @@ -361,9 +367,15 @@ type CategoryCommonProps struct { Colour *string `json:"colour,omitempty"` Description *string `json:"description,omitempty"` + // Meta Arbitrary metadata for the resource. + Meta *Metadata `json:"meta,omitempty"` + // Name A category's user-facing name. Name CategoryName `json:"name"` - Sort int `json:"sort"` + + // Slug A category's URL-safe slug. + Slug *CategorySlug `json:"slug,omitempty"` + Sort int `json:"sort"` } // CategoryIdentifierList defines model for CategoryIdentifierList. @@ -375,8 +387,14 @@ type CategoryInitialProps struct { Colour string `json:"colour"` Description string `json:"description"` + // Meta Arbitrary metadata for the resource. + Meta *Metadata `json:"meta,omitempty"` + // Name A category's user-facing name. Name CategoryName `json:"name"` + + // Slug A category's URL-safe slug. + Slug *CategorySlug `json:"slug,omitempty"` } // CategoryList defines model for CategoryList. @@ -384,6 +402,22 @@ type CategoryList struct { Categories []Category `json:"categories"` } +// CategoryMutableProps defines model for CategoryMutableProps. +type CategoryMutableProps struct { + Admin *bool `json:"admin,omitempty"` + Colour *string `json:"colour,omitempty"` + Description *string `json:"description,omitempty"` + + // Meta Arbitrary metadata for the resource. + Meta *Metadata `json:"meta,omitempty"` + + // Name A category's user-facing name. + Name *CategoryName `json:"name,omitempty"` + + // Slug A category's URL-safe slug. + Slug *CategorySlug `json:"slug,omitempty"` +} + // CategoryName A category's user-facing name. type CategoryName = string @@ -405,17 +439,26 @@ type CategoryReference struct { // Id A unique identifier for this resource. Id Identifier `json:"id"` + // Meta Arbitrary metadata for the resource. + Meta *Metadata `json:"meta,omitempty"` + // Misc Arbitrary extra data stored with the resource. Misc *map[string]interface{} `json:"misc,omitempty"` // Name A category's user-facing name. Name CategoryName `json:"name"` - Sort int `json:"sort"` + + // Slug A category's URL-safe slug. + Slug *CategorySlug `json:"slug,omitempty"` + Sort int `json:"sort"` // UpdatedAt The time the resource was updated. UpdatedAt time.Time `json:"updatedAt"` } +// CategorySlug A category's URL-safe slug. +type CategorySlug = string + // Collection defines model for Collection. type Collection struct { // CreatedAt The time the resource was created. @@ -1101,6 +1144,9 @@ type AccountHandleParam = AccountHandle // AssetPath defines model for AssetPath. type AssetPath = string +// CategoryIDParam A unique identifier for this resource. +type CategoryIDParam = Identifier + // CollectionIDParam A unique identifier for this resource. type CollectionIDParam = Identifier @@ -1155,6 +1201,9 @@ type CategoryCreateOK = Category // CategoryListOK defines model for CategoryListOK. type CategoryListOK = CategoryList +// CategoryUpdateOK defines model for CategoryUpdateOK. +type CategoryUpdateOK = Category + // CollectionAddPostOK A collection is a group of threads owned by a user. It allows users to // curate their own lists of content from the site. Collections can only // contain root level posts (threads) with titles and slugs to link to. @@ -1242,6 +1291,9 @@ type AuthPassword = AuthPair // CategoryCreate defines model for CategoryCreate. type CategoryCreate = CategoryInitialProps +// CategoryUpdate defines model for CategoryUpdate. +type CategoryUpdate = CategoryMutableProps + // CategoryUpdateOrder defines model for CategoryUpdateOrder. type CategoryUpdateOrder = CategoryIdentifierList @@ -1359,6 +1411,9 @@ type CategoryUpdateOrderJSONRequestBody = CategoryIdentifierList // CategoryCreateJSONRequestBody defines body for CategoryCreate for application/json ContentType. type CategoryCreateJSONRequestBody = CategoryInitialProps +// CategoryUpdateJSONRequestBody defines body for CategoryUpdate for application/json ContentType. +type CategoryUpdateJSONRequestBody = CategoryMutableProps + // CollectionCreateJSONRequestBody defines body for CollectionCreate for application/json ContentType. type CollectionCreateJSONRequestBody = CollectionInitialProps @@ -1544,6 +1599,11 @@ type ClientInterface interface { CategoryCreate(ctx context.Context, body CategoryCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // CategoryUpdate request with any body + CategoryUpdateWithBody(ctx context.Context, categoryId CategoryIDParam, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CategoryUpdate(ctx context.Context, categoryId CategoryIDParam, body CategoryUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // CollectionList request CollectionList(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -2030,6 +2090,30 @@ func (c *Client) CategoryCreate(ctx context.Context, body CategoryCreateJSONRequ return c.Client.Do(req) } +func (c *Client) CategoryUpdateWithBody(ctx context.Context, categoryId CategoryIDParam, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCategoryUpdateRequestWithBody(c.Server, categoryId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CategoryUpdate(ctx context.Context, categoryId CategoryIDParam, body CategoryUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCategoryUpdateRequest(c.Server, categoryId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) CollectionList(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewCollectionListRequest(c.Server) if err != nil { @@ -3194,6 +3278,53 @@ func NewCategoryCreateRequestWithBody(server string, contentType string, body io return req, nil } +// NewCategoryUpdateRequest calls the generic CategoryUpdate builder with application/json body +func NewCategoryUpdateRequest(server string, categoryId CategoryIDParam, body CategoryUpdateJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCategoryUpdateRequestWithBody(server, categoryId, "application/json", bodyReader) +} + +// NewCategoryUpdateRequestWithBody generates requests for CategoryUpdate with any type of body +func NewCategoryUpdateRequestWithBody(server string, categoryId CategoryIDParam, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "category_id", runtime.ParamLocationPath, categoryId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/categories/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PATCH", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewCollectionListRequest generates requests for CollectionList func NewCollectionListRequest(server string) (*http.Request, error) { var err error @@ -4206,6 +4337,11 @@ type ClientWithResponsesInterface interface { CategoryCreateWithResponse(ctx context.Context, body CategoryCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*CategoryCreateResponse, error) + // CategoryUpdate request with any body + CategoryUpdateWithBodyWithResponse(ctx context.Context, categoryId CategoryIDParam, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CategoryUpdateResponse, error) + + CategoryUpdateWithResponse(ctx context.Context, categoryId CategoryIDParam, body CategoryUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*CategoryUpdateResponse, error) + // CollectionList request CollectionListWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*CollectionListResponse, error) @@ -4809,6 +4945,29 @@ func (r CategoryCreateResponse) StatusCode() int { return 0 } +type CategoryUpdateResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Category + JSONDefault *APIError +} + +// Status returns HTTPResponse.Status +func (r CategoryUpdateResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CategoryUpdateResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type CollectionListResponse struct { Body []byte HTTPResponse *http.Response @@ -5585,6 +5744,23 @@ func (c *ClientWithResponses) CategoryCreateWithResponse(ctx context.Context, bo return ParseCategoryCreateResponse(rsp) } +// CategoryUpdateWithBodyWithResponse request with arbitrary body returning *CategoryUpdateResponse +func (c *ClientWithResponses) CategoryUpdateWithBodyWithResponse(ctx context.Context, categoryId CategoryIDParam, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CategoryUpdateResponse, error) { + rsp, err := c.CategoryUpdateWithBody(ctx, categoryId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCategoryUpdateResponse(rsp) +} + +func (c *ClientWithResponses) CategoryUpdateWithResponse(ctx context.Context, categoryId CategoryIDParam, body CategoryUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*CategoryUpdateResponse, error) { + rsp, err := c.CategoryUpdate(ctx, categoryId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCategoryUpdateResponse(rsp) +} + // CollectionListWithResponse request returning *CollectionListResponse func (c *ClientWithResponses) CollectionListWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*CollectionListResponse, error) { rsp, err := c.CollectionList(ctx, reqEditors...) @@ -6546,6 +6722,39 @@ func ParseCategoryCreateResponse(rsp *http.Response) (*CategoryCreateResponse, e return response, nil } +// ParseCategoryUpdateResponse parses an HTTP response from a CategoryUpdateWithResponse call +func ParseCategoryUpdateResponse(rsp *http.Response) (*CategoryUpdateResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CategoryUpdateResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Category + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && true: + var dest APIError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSONDefault = &dest + + } + + return response, nil +} + // ParseCollectionListResponse parses an HTTP response from a CollectionListWithResponse call func ParseCollectionListResponse(rsp *http.Response) (*CollectionListResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -7270,6 +7479,9 @@ type ServerInterface interface { // (POST /v1/categories) CategoryCreate(ctx echo.Context) error + // (PATCH /v1/categories/{category_id}) + CategoryUpdate(ctx echo.Context, categoryId CategoryIDParam) error + // (GET /v1/collections) CollectionList(ctx echo.Context) error @@ -7650,6 +7862,24 @@ func (w *ServerInterfaceWrapper) CategoryCreate(ctx echo.Context) error { return err } +// CategoryUpdate converts echo context to params. +func (w *ServerInterfaceWrapper) CategoryUpdate(ctx echo.Context) error { + var err error + // ------------- Path parameter "category_id" ------------- + var categoryId CategoryIDParam + + err = runtime.BindStyledParameterWithLocation("simple", false, "category_id", runtime.ParamLocationPath, ctx.Param("category_id"), &categoryId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter category_id: %s", err)) + } + + ctx.Set(BrowserScopes, []string{""}) + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.CategoryUpdate(ctx, categoryId) + return err +} + // CollectionList converts echo context to params. func (w *ServerInterfaceWrapper) CollectionList(ctx echo.Context) error { var err error @@ -8089,6 +8319,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/v1/categories", wrapper.CategoryList) router.PATCH(baseURL+"/v1/categories", wrapper.CategoryUpdateOrder) router.POST(baseURL+"/v1/categories", wrapper.CategoryCreate) + router.PATCH(baseURL+"/v1/categories/:category_id", wrapper.CategoryUpdate) router.GET(baseURL+"/v1/collections", wrapper.CollectionList) router.POST(baseURL+"/v1/collections", wrapper.CollectionCreate) router.GET(baseURL+"/v1/collections/:collection_id", wrapper.CollectionGet) @@ -8156,6 +8387,8 @@ type CategoryCreateOKJSONResponse Category type CategoryListOKJSONResponse CategoryList +type CategoryUpdateOKJSONResponse Category + type CollectionAddPostOKJSONResponse Collection type CollectionCreateOKJSONResponse Collection @@ -9126,6 +9359,50 @@ func (response CategoryCreatedefaultJSONResponse) VisitCategoryCreateResponse(w return json.NewEncoder(w).Encode(response.Body) } +type CategoryUpdateRequestObject struct { + CategoryId CategoryIDParam `json:"category_id"` + Body *CategoryUpdateJSONRequestBody +} + +type CategoryUpdateResponseObject interface { + VisitCategoryUpdateResponse(w http.ResponseWriter) error +} + +type CategoryUpdate200JSONResponse struct{ CategoryUpdateOKJSONResponse } + +func (response CategoryUpdate200JSONResponse) VisitCategoryUpdateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type CategoryUpdate400Response = BadRequestResponse + +func (response CategoryUpdate400Response) VisitCategoryUpdateResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type CategoryUpdate401Response = UnauthorisedResponse + +func (response CategoryUpdate401Response) VisitCategoryUpdateResponse(w http.ResponseWriter) error { + w.WriteHeader(401) + return nil +} + +type CategoryUpdatedefaultJSONResponse struct { + Body APIError + StatusCode int +} + +func (response CategoryUpdatedefaultJSONResponse) VisitCategoryUpdateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(response.StatusCode) + + return json.NewEncoder(w).Encode(response.Body) +} + type CollectionListRequestObject struct { } @@ -10040,6 +10317,9 @@ type StrictServerInterface interface { // (POST /v1/categories) CategoryCreate(ctx context.Context, request CategoryCreateRequestObject) (CategoryCreateResponseObject, error) + // (PATCH /v1/categories/{category_id}) + CategoryUpdate(ctx context.Context, request CategoryUpdateRequestObject) (CategoryUpdateResponseObject, error) + // (GET /v1/collections) CollectionList(ctx context.Context, request CollectionListRequestObject) (CollectionListResponseObject, error) @@ -10732,6 +11012,37 @@ func (sh *strictHandler) CategoryCreate(ctx echo.Context) error { return nil } +// CategoryUpdate operation middleware +func (sh *strictHandler) CategoryUpdate(ctx echo.Context, categoryId CategoryIDParam) error { + var request CategoryUpdateRequestObject + + request.CategoryId = categoryId + + var body CategoryUpdateJSONRequestBody + if err := ctx.Bind(&body); err != nil { + return err + } + request.Body = &body + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.CategoryUpdate(ctx.Request().Context(), request.(CategoryUpdateRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "CategoryUpdate") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(CategoryUpdateResponseObject); ok { + return validResponse.VisitCategoryUpdateResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + // CollectionList operation middleware func (sh *strictHandler) CollectionList(ctx echo.Context) error { var request CollectionListRequestObject @@ -11296,142 +11607,144 @@ func (sh *strictHandler) GetVersion(ctx echo.Context) error { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/web/src/api/openapi/categories.ts b/web/src/api/openapi/categories.ts index d61b70c30..075c8908b 100644 --- a/web/src/api/openapi/categories.ts +++ b/web/src/api/openapi/categories.ts @@ -14,6 +14,8 @@ import type { CategoryCreateBody, CategoryCreateOKResponse, CategoryListOKResponse, + CategoryUpdateBody, + CategoryUpdateOKResponse, CategoryUpdateOrderBody, InternalServerErrorResponse, } from "./schemas"; @@ -91,3 +93,18 @@ export const categoryUpdateOrder = ( data: categoryUpdateOrderBody, }); }; + +/** + * Create a category for organising posts. + */ +export const categoryUpdate = ( + categoryId: string, + categoryUpdateBody: CategoryUpdateBody, +) => { + return fetcher({ + url: `/v1/categories/${categoryId}`, + method: "patch", + headers: { "Content-Type": "application/json" }, + data: categoryUpdateBody, + }); +}; diff --git a/web/src/api/openapi/schemas/categoryCommonProps.ts b/web/src/api/openapi/schemas/categoryCommonProps.ts index 959f25832..6c15a2537 100644 --- a/web/src/api/openapi/schemas/categoryCommonProps.ts +++ b/web/src/api/openapi/schemas/categoryCommonProps.ts @@ -6,11 +6,15 @@ * OpenAPI spec version: 1 */ import type { CategoryName } from "./categoryName"; +import type { CategorySlug } from "./categorySlug"; +import type { Metadata } from "./metadata"; export interface CategoryCommonProps { name: CategoryName; + slug?: CategorySlug; description?: string; colour?: string; sort: number; admin?: boolean; + meta?: Metadata; } diff --git a/web/src/api/openapi/schemas/categoryInitialProps.ts b/web/src/api/openapi/schemas/categoryInitialProps.ts index 850e65b54..8fae51332 100644 --- a/web/src/api/openapi/schemas/categoryInitialProps.ts +++ b/web/src/api/openapi/schemas/categoryInitialProps.ts @@ -6,10 +6,14 @@ * OpenAPI spec version: 1 */ import type { CategoryName } from "./categoryName"; +import type { CategorySlug } from "./categorySlug"; +import type { Metadata } from "./metadata"; export interface CategoryInitialProps { name: CategoryName; + slug?: CategorySlug; description: string; colour: string; admin: boolean; + meta?: Metadata; } diff --git a/web/src/api/openapi/schemas/categoryMutableProps.ts b/web/src/api/openapi/schemas/categoryMutableProps.ts new file mode 100644 index 000000000..46f41be8d --- /dev/null +++ b/web/src/api/openapi/schemas/categoryMutableProps.ts @@ -0,0 +1,19 @@ +/** + * Generated by orval v6.17.0 🍺 + * Do not edit manually. + * storyden + * Storyden social API for building community driven platforms. + * OpenAPI spec version: 1 + */ +import type { CategoryName } from "./categoryName"; +import type { CategorySlug } from "./categorySlug"; +import type { Metadata } from "./metadata"; + +export interface CategoryMutableProps { + name?: CategoryName; + slug?: CategorySlug; + description?: string; + colour?: string; + admin?: boolean; + meta?: Metadata; +} diff --git a/web/src/api/openapi/schemas/categorySlug.ts b/web/src/api/openapi/schemas/categorySlug.ts new file mode 100644 index 000000000..0b3dc5b3e --- /dev/null +++ b/web/src/api/openapi/schemas/categorySlug.ts @@ -0,0 +1,12 @@ +/** + * Generated by orval v6.17.0 🍺 + * Do not edit manually. + * storyden + * Storyden social API for building community driven platforms. + * OpenAPI spec version: 1 + */ + +/** + * A category's URL-safe slug. + */ +export type CategorySlug = string; diff --git a/web/src/api/openapi/schemas/categoryUpdateBody.ts b/web/src/api/openapi/schemas/categoryUpdateBody.ts new file mode 100644 index 000000000..3dd710e3b --- /dev/null +++ b/web/src/api/openapi/schemas/categoryUpdateBody.ts @@ -0,0 +1,10 @@ +/** + * Generated by orval v6.17.0 🍺 + * Do not edit manually. + * storyden + * Storyden social API for building community driven platforms. + * OpenAPI spec version: 1 + */ +import type { CategoryMutableProps } from "./categoryMutableProps"; + +export type CategoryUpdateBody = CategoryMutableProps; diff --git a/web/src/api/openapi/schemas/categoryUpdateOKResponse.ts b/web/src/api/openapi/schemas/categoryUpdateOKResponse.ts new file mode 100644 index 000000000..e93f510eb --- /dev/null +++ b/web/src/api/openapi/schemas/categoryUpdateOKResponse.ts @@ -0,0 +1,13 @@ +/** + * Generated by orval v6.17.0 🍺 + * Do not edit manually. + * storyden + * Storyden social API for building community driven platforms. + * OpenAPI spec version: 1 + */ +import type { Category } from "./category"; + +/** + * OK + */ +export type CategoryUpdateOKResponse = Category; diff --git a/web/src/api/openapi/schemas/index.ts b/web/src/api/openapi/schemas/index.ts index e01f39d03..2891b7069 100644 --- a/web/src/api/openapi/schemas/index.ts +++ b/web/src/api/openapi/schemas/index.ts @@ -55,9 +55,13 @@ export * from "./categoryIdentifierList"; export * from "./categoryInitialProps"; export * from "./categoryList"; export * from "./categoryListOKResponse"; +export * from "./categoryMutableProps"; export * from "./categoryName"; export * from "./categoryNameList"; export * from "./categoryReference"; +export * from "./categorySlug"; +export * from "./categoryUpdateBody"; +export * from "./categoryUpdateOKResponse"; export * from "./categoryUpdateOrderBody"; export * from "./collection"; export * from "./collectionAddPostOKResponse";