Skip to main content
Glama
Southclaws

Storyden

by Southclaws
search.go3.14 kB
package node_search import ( "context" "entgo.io/ent/dialect/sql" "github.com/Southclaws/dt" "github.com/Southclaws/fault" "github.com/Southclaws/fault/fctx" "github.com/jmoiron/sqlx" "github.com/rs/xid" "github.com/Southclaws/storyden/app/resources/account" "github.com/Southclaws/storyden/app/resources/library" "github.com/Southclaws/storyden/app/resources/pagination" "github.com/Southclaws/storyden/app/resources/tag/tag_ref" "github.com/Southclaws/storyden/app/resources/visibility" "github.com/Southclaws/storyden/internal/ent" ent_account "github.com/Southclaws/storyden/internal/ent/account" "github.com/Southclaws/storyden/internal/ent/node" ent_tag "github.com/Southclaws/storyden/internal/ent/tag" ) type Search interface { Search(ctx context.Context, params pagination.Parameters, opts ...Option) (*pagination.Result[*library.Node], error) } type query struct { nameContains string contentContains string visibility []visibility.Visibility authors []account.AccountID tags []tag_ref.Name } type Option func(*query) func WithNameContains(s string) Option { return func(q *query) { q.nameContains = s } } func WithContentContains(s string) Option { return func(q *query) { q.contentContains = s } } func WithVisibility(v []visibility.Visibility) Option { return func(q *query) { q.visibility = v } } func WithAuthors(ids ...account.AccountID) Option { return func(q *query) { q.authors = ids } } func WithTags(names ...tag_ref.Name) Option { return func(q *query) { q.tags = names } } type service struct { db *ent.Client raw *sqlx.DB } func New(db *ent.Client, raw *sqlx.DB) Search { return &service{ db: db, raw: raw, } } func (s *service) Search(ctx context.Context, params pagination.Parameters, opts ...Option) (*pagination.Result[*library.Node], error) { q := &query{} for _, fn := range opts { fn(q) } baseQuery := s.db.Node.Query().Where( node.Or( node.NameContainsFold(q.nameContains), node.ContentContainsFold(q.contentContains), ), node.VisibilityEQ(node.VisibilityPublished), node.DeletedAtIsNil(), ) if len(q.authors) > 0 { authorIDs := dt.Map(q.authors, func(id account.AccountID) xid.ID { return xid.ID(id) }) baseQuery = baseQuery.Where(node.HasOwnerWith(ent_account.IDIn(authorIDs...))) } if len(q.tags) > 0 { for _, tag := range q.tags { baseQuery = baseQuery.Where(node.HasTagsWith(ent_tag.NameEQ(tag.String()))) } } total, err := baseQuery.Count(ctx) if err != nil { return nil, fault.Wrap(err, fctx.With(ctx)) } query := baseQuery. WithOwner(). WithNodes(func(cq *ent.NodeQuery) { cq.WithOwner() }). WithPrimaryImage(). Order(node.ByUpdatedAt(sql.OrderDesc()), node.ByCreatedAt(sql.OrderDesc())). Limit(params.Limit()). Offset(params.Offset()) r, err := query.All(ctx) if err != nil { return nil, fault.Wrap(err, fctx.With(ctx)) } nodes, err := dt.MapErr(r, library.MapNode(true, nil)) if err != nil { return nil, fault.Wrap(err, fctx.With(ctx)) } result := pagination.NewPageResult(params, total, nodes) return &result, nil }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Southclaws/storyden'

If you have feedback or need assistance with the MCP directory API, please join our Discord server