tercul-backend/internal/adapters/graphql/model/models_gen.go
google-labs-jules[bot] caf07df08d feat(analytics): Enhance analytics capabilities
This commit introduces a comprehensive enhancement of the application's analytics features, addressing performance, data modeling, and feature set.

The key changes include:

- **Performance Improvement:** The analytics repository now uses a database "UPSERT" operation to increment counters, reducing two separate database calls (read and write) into a single, more efficient operation.

- **New Metrics:** The `WorkStats` and `TranslationStats` models have been enriched with new, calculated metrics:
  - `ReadingTime`: An estimation of the time required to read the work or translation.
  - `Complexity`: A score representing the linguistic complexity of the text.
  - `Sentiment`: A score indicating the emotional tone of the text.

- **Service Refactoring:** The analytics service has been refactored to support the new metrics. It now includes methods to calculate and update these scores, leveraging the existing linguistics package for text analysis.

- **GraphQL API Expansion:** The new analytics fields (`readingTime`, `complexity`, `sentiment`) have been exposed through the GraphQL API by updating the `WorkStats` and `TranslationStats` types in the schema.

- **Validation and Testing:**
  - GraphQL input validation has been centralized and improved by moving from ad-hoc checks to a consistent validation pattern in the GraphQL layer.
  - The test suite has been significantly improved with the addition of new tests for the analytics service and the data access layer, ensuring the correctness and robustness of the new features. This includes fixing several bugs that were discovered during the development process.
2025-09-07 19:26:51 +00:00

678 lines
22 KiB
Go

// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
package model
import (
"bytes"
"fmt"
"io"
"strconv"
)
type Address struct {
ID string `json:"id"`
Street string `json:"street"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
City *City `json:"city,omitempty"`
Country *Country `json:"country,omitempty"`
Authors []*Author `json:"authors,omitempty"`
Users []*User `json:"users,omitempty"`
}
type AuthPayload struct {
Token string `json:"token"`
User *User `json:"user"`
}
type Author struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
Biography *string `json:"biography,omitempty"`
BirthDate *string `json:"birthDate,omitempty"`
DeathDate *string `json:"deathDate,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
Books []*Book `json:"books,omitempty"`
Country *Country `json:"country,omitempty"`
City *City `json:"city,omitempty"`
Place *Place `json:"place,omitempty"`
Address *Address `json:"address,omitempty"`
CopyrightClaims []*CopyrightClaim `json:"copyrightClaims,omitempty"`
Copyright *Copyright `json:"copyright,omitempty"`
}
type AuthorInput struct {
Name string `json:"name"`
Language string `json:"language"`
Biography *string `json:"biography,omitempty"`
BirthDate *string `json:"birthDate,omitempty"`
DeathDate *string `json:"deathDate,omitempty"`
CountryID *string `json:"countryId,omitempty"`
CityID *string `json:"cityId,omitempty"`
PlaceID *string `json:"placeId,omitempty"`
AddressID *string `json:"addressId,omitempty"`
}
type Book struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
Stats *BookStats `json:"stats,omitempty"`
Copyright *Copyright `json:"copyright,omitempty"`
CopyrightClaims []*CopyrightClaim `json:"copyrightClaims,omitempty"`
}
type BookStats struct {
ID string `json:"id"`
Sales int32 `json:"sales"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Book *Book `json:"book"`
}
type Bookmark struct {
ID string `json:"id"`
Name *string `json:"name,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
User *User `json:"user"`
Work *Work `json:"work"`
}
type BookmarkInput struct {
Name *string `json:"name,omitempty"`
WorkID string `json:"workId"`
}
type Category struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
}
type City struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Country *Country `json:"country,omitempty"`
Authors []*Author `json:"authors,omitempty"`
Users []*User `json:"users,omitempty"`
}
type Collection struct {
ID string `json:"id"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
User *User `json:"user,omitempty"`
Stats *CollectionStats `json:"stats,omitempty"`
}
type CollectionInput struct {
Name string `json:"name"`
Description *string `json:"description,omitempty"`
WorkIds []string `json:"workIds,omitempty"`
}
type CollectionStats struct {
ID string `json:"id"`
Items int32 `json:"items"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Collection *Collection `json:"collection"`
}
type Comment struct {
ID string `json:"id"`
Text string `json:"text"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
User *User `json:"user"`
Work *Work `json:"work,omitempty"`
Translation *Translation `json:"translation,omitempty"`
LineNumber *int32 `json:"lineNumber,omitempty"`
ParentComment *Comment `json:"parentComment,omitempty"`
ChildComments []*Comment `json:"childComments,omitempty"`
Likes []*Like `json:"likes,omitempty"`
}
type CommentInput struct {
Text string `json:"text"`
WorkID *string `json:"workId,omitempty"`
TranslationID *string `json:"translationId,omitempty"`
LineNumber *int32 `json:"lineNumber,omitempty"`
ParentCommentID *string `json:"parentCommentId,omitempty"`
}
type Concept struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
Words []*Word `json:"words,omitempty"`
}
type Contribution struct {
ID string `json:"id"`
Name string `json:"name"`
Status ContributionStatus `json:"status"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
User *User `json:"user"`
Work *Work `json:"work,omitempty"`
Translation *Translation `json:"translation,omitempty"`
}
type ContributionInput struct {
Name string `json:"name"`
WorkID *string `json:"workId,omitempty"`
TranslationID *string `json:"translationId,omitempty"`
Status *ContributionStatus `json:"status,omitempty"`
}
type Copyright struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
WorkOwner *Author `json:"workOwner,omitempty"`
Works []*Work `json:"works,omitempty"`
Translations []*Translation `json:"translations,omitempty"`
Books []*Book `json:"books,omitempty"`
Sources []*Source `json:"sources,omitempty"`
}
type CopyrightClaim struct {
ID string `json:"id"`
Details string `json:"details"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Work *Work `json:"work,omitempty"`
Translation *Translation `json:"translation,omitempty"`
Book *Book `json:"book,omitempty"`
Source *Source `json:"source,omitempty"`
Author *Author `json:"author,omitempty"`
User *User `json:"user,omitempty"`
}
type Country struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Authors []*Author `json:"authors,omitempty"`
Users []*User `json:"users,omitempty"`
}
type Edge struct {
ID string `json:"id"`
SourceTable string `json:"sourceTable"`
SourceID string `json:"sourceId"`
TargetTable string `json:"targetTable"`
TargetID string `json:"targetId"`
Relation string `json:"relation"`
Language *string `json:"language,omitempty"`
Extra *string `json:"extra,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type Emotion struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
User *User `json:"user,omitempty"`
Work *Work `json:"work,omitempty"`
Collection *Collection `json:"collection,omitempty"`
}
type Like struct {
ID string `json:"id"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
User *User `json:"user"`
Work *Work `json:"work,omitempty"`
Translation *Translation `json:"translation,omitempty"`
Comment *Comment `json:"comment,omitempty"`
}
type LikeInput struct {
WorkID *string `json:"workId,omitempty"`
TranslationID *string `json:"translationId,omitempty"`
CommentID *string `json:"commentId,omitempty"`
}
type LinguisticLayer struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
}
type LoginInput struct {
Email string `json:"email"`
Password string `json:"password"`
}
type Mood struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
}
type Mutation struct {
}
type Place struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
City *City `json:"city,omitempty"`
Country *Country `json:"country,omitempty"`
Authors []*Author `json:"authors,omitempty"`
}
type PoeticAnalysis struct {
ID string `json:"id"`
Structure string `json:"structure"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Work *Work `json:"work"`
}
type Query struct {
}
type ReadabilityScore struct {
ID string `json:"id"`
Score float64 `json:"score"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Work *Work `json:"work,omitempty"`
}
type RegisterInput struct {
Username string `json:"username"`
Email string `json:"email"`
Password string `json:"password"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type SearchFilters struct {
Languages []string `json:"languages,omitempty"`
Categories []string `json:"categories,omitempty"`
Tags []string `json:"tags,omitempty"`
Authors []string `json:"authors,omitempty"`
DateFrom *string `json:"dateFrom,omitempty"`
DateTo *string `json:"dateTo,omitempty"`
}
type SearchResults struct {
Works []*Work `json:"works"`
Translations []*Translation `json:"translations"`
Authors []*Author `json:"authors"`
Total int32 `json:"total"`
}
type Source struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Copyright *Copyright `json:"copyright,omitempty"`
CopyrightClaims []*CopyrightClaim `json:"copyrightClaims,omitempty"`
Works []*Work `json:"works,omitempty"`
}
type Tag struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
}
type TextMetadata struct {
ID string `json:"id"`
Analysis string `json:"analysis"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Work *Work `json:"work"`
}
type TopicCluster struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Works []*Work `json:"works,omitempty"`
}
type Translation struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
Content *string `json:"content,omitempty"`
WorkID string `json:"workId"`
Work *Work `json:"work"`
Translator *User `json:"translator,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Stats *TranslationStats `json:"stats,omitempty"`
Copyright *Copyright `json:"copyright,omitempty"`
CopyrightClaims []*CopyrightClaim `json:"copyrightClaims,omitempty"`
Comments []*Comment `json:"comments,omitempty"`
Likes []*Like `json:"likes,omitempty"`
}
type TranslationInput struct {
Name string `json:"name"`
Language string `json:"language"`
Content *string `json:"content,omitempty"`
WorkID string `json:"workId"`
}
type TranslationStats struct {
ID string `json:"id"`
Views *int64 `json:"views,omitempty"`
Likes *int64 `json:"likes,omitempty"`
Comments *int64 `json:"comments,omitempty"`
Shares *int64 `json:"shares,omitempty"`
ReadingTime *int `json:"readingTime,omitempty"`
Sentiment *float64 `json:"sentiment,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Translation *Translation `json:"translation"`
}
type User struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
Bio *string `json:"bio,omitempty"`
AvatarURL *string `json:"avatarUrl,omitempty"`
Role UserRole `json:"role"`
LastLoginAt *string `json:"lastLoginAt,omitempty"`
Verified bool `json:"verified"`
Active bool `json:"active"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Translations []*Translation `json:"translations,omitempty"`
Comments []*Comment `json:"comments,omitempty"`
Likes []*Like `json:"likes,omitempty"`
Bookmarks []*Bookmark `json:"bookmarks,omitempty"`
Collections []*Collection `json:"collections,omitempty"`
Contributions []*Contribution `json:"contributions,omitempty"`
Country *Country `json:"country,omitempty"`
City *City `json:"city,omitempty"`
Address *Address `json:"address,omitempty"`
Stats *UserStats `json:"stats,omitempty"`
}
type UserInput struct {
Username *string `json:"username,omitempty"`
Email *string `json:"email,omitempty"`
Password *string `json:"password,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
Bio *string `json:"bio,omitempty"`
AvatarURL *string `json:"avatarUrl,omitempty"`
Role *UserRole `json:"role,omitempty"`
Verified *bool `json:"verified,omitempty"`
Active *bool `json:"active,omitempty"`
CountryID *string `json:"countryId,omitempty"`
CityID *string `json:"cityId,omitempty"`
AddressID *string `json:"addressId,omitempty"`
}
type UserProfile struct {
ID string `json:"id"`
UserID string `json:"userId"`
User *User `json:"user"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
Website *string `json:"website,omitempty"`
Twitter *string `json:"twitter,omitempty"`
Facebook *string `json:"facebook,omitempty"`
LinkedIn *string `json:"linkedIn,omitempty"`
Github *string `json:"github,omitempty"`
Preferences *string `json:"preferences,omitempty"`
Settings *string `json:"settings,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type UserStats struct {
ID string `json:"id"`
Activity int32 `json:"activity"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
User *User `json:"user"`
}
type Word struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Concept *Concept `json:"concept,omitempty"`
Works []*Work `json:"works,omitempty"`
}
type Work struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
Content *string `json:"content,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Translations []*Translation `json:"translations,omitempty"`
Authors []*Author `json:"authors,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
Categories []*Category `json:"categories,omitempty"`
ReadabilityScore *ReadabilityScore `json:"readabilityScore,omitempty"`
WritingStyle *WritingStyle `json:"writingStyle,omitempty"`
Emotions []*Emotion `json:"emotions,omitempty"`
TopicClusters []*TopicCluster `json:"topicClusters,omitempty"`
Moods []*Mood `json:"moods,omitempty"`
Concepts []*Concept `json:"concepts,omitempty"`
LinguisticLayers []*LinguisticLayer `json:"linguisticLayers,omitempty"`
Stats *WorkStats `json:"stats,omitempty"`
TextMetadata *TextMetadata `json:"textMetadata,omitempty"`
PoeticAnalysis *PoeticAnalysis `json:"poeticAnalysis,omitempty"`
Copyright *Copyright `json:"copyright,omitempty"`
CopyrightClaims []*CopyrightClaim `json:"copyrightClaims,omitempty"`
Collections []*Collection `json:"collections,omitempty"`
Comments []*Comment `json:"comments,omitempty"`
Likes []*Like `json:"likes,omitempty"`
Bookmarks []*Bookmark `json:"bookmarks,omitempty"`
}
type WorkInput struct {
Name string `json:"name"`
Language string `json:"language"`
Content *string `json:"content,omitempty"`
AuthorIds []string `json:"authorIds,omitempty"`
TagIds []string `json:"tagIds,omitempty"`
CategoryIds []string `json:"categoryIds,omitempty"`
}
type WorkStats struct {
ID string `json:"id"`
Views *int64 `json:"views,omitempty"`
Likes *int64 `json:"likes,omitempty"`
Comments *int64 `json:"comments,omitempty"`
Bookmarks *int64 `json:"bookmarks,omitempty"`
Shares *int64 `json:"shares,omitempty"`
TranslationCount *int64 `json:"translationCount,omitempty"`
ReadingTime *int `json:"readingTime,omitempty"`
Complexity *float64 `json:"complexity,omitempty"`
Sentiment *float64 `json:"sentiment,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Work *Work `json:"work"`
}
type WritingStyle struct {
ID string `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Work *Work `json:"work,omitempty"`
}
type ContributionStatus string
const (
ContributionStatusDraft ContributionStatus = "DRAFT"
ContributionStatusSubmitted ContributionStatus = "SUBMITTED"
ContributionStatusUnderReview ContributionStatus = "UNDER_REVIEW"
ContributionStatusApproved ContributionStatus = "APPROVED"
ContributionStatusRejected ContributionStatus = "REJECTED"
)
var AllContributionStatus = []ContributionStatus{
ContributionStatusDraft,
ContributionStatusSubmitted,
ContributionStatusUnderReview,
ContributionStatusApproved,
ContributionStatusRejected,
}
func (e ContributionStatus) IsValid() bool {
switch e {
case ContributionStatusDraft, ContributionStatusSubmitted, ContributionStatusUnderReview, ContributionStatusApproved, ContributionStatusRejected:
return true
}
return false
}
func (e ContributionStatus) String() string {
return string(e)
}
func (e *ContributionStatus) UnmarshalGQL(v any) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = ContributionStatus(str)
if !e.IsValid() {
return fmt.Errorf("%s is not a valid ContributionStatus", str)
}
return nil
}
func (e ContributionStatus) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
func (e *ContributionStatus) UnmarshalJSON(b []byte) error {
s, err := strconv.Unquote(string(b))
if err != nil {
return err
}
return e.UnmarshalGQL(s)
}
func (e ContributionStatus) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
e.MarshalGQL(&buf)
return buf.Bytes(), nil
}
type UserRole string
const (
UserRoleReader UserRole = "READER"
UserRoleContributor UserRole = "CONTRIBUTOR"
UserRoleReviewer UserRole = "REVIEWER"
UserRoleEditor UserRole = "EDITOR"
UserRoleAdmin UserRole = "ADMIN"
)
var AllUserRole = []UserRole{
UserRoleReader,
UserRoleContributor,
UserRoleReviewer,
UserRoleEditor,
UserRoleAdmin,
}
func (e UserRole) IsValid() bool {
switch e {
case UserRoleReader, UserRoleContributor, UserRoleReviewer, UserRoleEditor, UserRoleAdmin:
return true
}
return false
}
func (e UserRole) String() string {
return string(e)
}
func (e *UserRole) UnmarshalGQL(v any) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = UserRole(str)
if !e.IsValid() {
return fmt.Errorf("%s is not a valid UserRole", str)
}
return nil
}
func (e UserRole) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
func (e *UserRole) UnmarshalJSON(b []byte) error {
s, err := strconv.Unquote(string(b))
if err != nil {
return err
}
return e.UnmarshalGQL(s)
}
func (e UserRole) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
e.MarshalGQL(&buf)
return buf.Bytes(), nil
}