tercul-backend/internal/adapters/graphql/schema.graphqls
google-labs-jules[bot] 1c4dcbcf99 Refactor: Introduce service layer for application logic
This change introduces a service layer to encapsulate the business logic
for each domain aggregate. This will make the code more modular,
testable, and easier to maintain.

The following services have been created:
- author
- bookmark
- category
- collection
- comment
- like
- tag
- translation
- user

The main Application struct has been updated to use these new services.
The integration test suite has also been updated to use the new
Application struct and services.

This is a work in progress. The next step is to fix the compilation
errors and then refactor the resolvers to use the new services.
2025-09-09 02:28:25 +00:00

714 lines
12 KiB
GraphQL

# GraphQL schema for Tercul literary platform
# Core types
type Work {
id: ID!
name: String!
language: String!
content: String
createdAt: String!
updatedAt: String!
translations: [Translation!]
authors: [Author!]
tags: [Tag!]
categories: [Category!]
readabilityScore: ReadabilityScore
writingStyle: WritingStyle
emotions: [Emotion!]
topicClusters: [TopicCluster!]
moods: [Mood!]
concepts: [Concept!]
linguisticLayers: [LinguisticLayer!]
stats: WorkStats
textMetadata: TextMetadata
poeticAnalysis: PoeticAnalysis
copyright: Copyright
copyrightClaims: [CopyrightClaim!]
collections: [Collection!]
comments: [Comment!]
likes: [Like!]
bookmarks: [Bookmark!]
}
type Translation {
id: ID!
name: String!
language: String!
content: String
workId: ID!
work: Work!
translator: User
createdAt: String!
updatedAt: String!
stats: TranslationStats
copyright: Copyright
copyrightClaims: [CopyrightClaim!]
comments: [Comment!]
likes: [Like!]
}
type Author {
id: ID!
name: String!
language: String!
biography: String
birthDate: String
deathDate: String
createdAt: String!
updatedAt: String!
works: [Work!]
books: [Book!]
country: Country
city: City
place: Place
address: Address
copyrightClaims: [CopyrightClaim!]
copyright: Copyright
}
type User {
id: ID!
username: String!
email: String!
firstName: String
lastName: String
displayName: String
bio: String
avatarUrl: String
role: UserRole!
lastLoginAt: String
verified: Boolean!
active: Boolean!
createdAt: String!
updatedAt: String!
# Relationships
translations: [Translation!]
comments: [Comment!]
likes: [Like!]
bookmarks: [Bookmark!]
collections: [Collection!]
contributions: [Contribution!]
# Location
country: Country
city: City
address: Address
# Stats
stats: UserStats
}
type UserProfile {
id: ID!
userId: ID!
user: User!
phoneNumber: String
website: String
twitter: String
facebook: String
linkedIn: String
github: String
preferences: JSON
settings: JSON
createdAt: String!
updatedAt: String!
}
enum UserRole {
READER
CONTRIBUTOR
REVIEWER
EDITOR
ADMIN
}
type Book {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
works: [Work!]
stats: BookStats
copyright: Copyright
copyrightClaims: [CopyrightClaim!]
}
type Collection {
id: ID!
name: String!
description: String
createdAt: String!
updatedAt: String!
works: [Work!]
user: User
stats: CollectionStats
}
type Tag {
id: ID!
name: String!
createdAt: String!
updatedAt: String!
works: [Work!]
}
type Category {
id: ID!
name: String!
createdAt: String!
updatedAt: String!
works: [Work!]
}
type Comment {
id: ID!
text: String!
createdAt: String!
updatedAt: String!
user: User!
work: Work
translation: Translation
lineNumber: Int
parentComment: Comment
childComments: [Comment!]
likes: [Like!]
}
type Like {
id: ID!
createdAt: String!
updatedAt: String!
user: User!
work: Work
translation: Translation
comment: Comment
}
type Bookmark {
id: ID!
name: String
createdAt: String!
updatedAt: String!
user: User!
work: Work!
}
type Contribution {
id: ID!
name: String!
status: ContributionStatus!
createdAt: String!
updatedAt: String!
user: User!
work: Work
translation: Translation
}
enum ContributionStatus {
DRAFT
SUBMITTED
UNDER_REVIEW
APPROVED
REJECTED
}
type ReadabilityScore {
id: ID!
score: Float!
language: String!
createdAt: String!
updatedAt: String!
work: Work
}
type WritingStyle {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
work: Work
}
type Emotion {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
user: User
work: Work
collection: Collection
}
type TopicCluster {
id: ID!
name: String!
createdAt: String!
updatedAt: String!
works: [Work!]
}
type Mood {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
works: [Work!]
}
type Concept {
id: ID!
name: String!
createdAt: String!
updatedAt: String!
works: [Work!]
words: [Word!]
}
type Word {
id: ID!
name: String!
createdAt: String!
updatedAt: String!
concept: Concept
works: [Work!]
}
type LinguisticLayer {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
works: [Work!]
}
type WorkStats {
id: ID!
views: Int
likes: Int
comments: Int
bookmarks: Int
shares: Int
translationCount: Int
readingTime: Int
complexity: Float
sentiment: Float
createdAt: String!
updatedAt: String!
work: Work!
}
type TranslationStats {
id: ID!
views: Int
likes: Int
comments: Int
shares: Int
readingTime: Int
sentiment: Float
createdAt: String!
updatedAt: String!
translation: Translation!
}
type UserStats {
id: ID!
activity: Int!
createdAt: String!
updatedAt: String!
user: User!
}
type BookStats {
id: ID!
sales: Int!
createdAt: String!
updatedAt: String!
book: Book!
}
type CollectionStats {
id: ID!
items: Int!
createdAt: String!
updatedAt: String!
collection: Collection!
}
type TextMetadata {
id: ID!
analysis: String!
language: String!
createdAt: String!
updatedAt: String!
work: Work!
}
type PoeticAnalysis {
id: ID!
structure: String!
language: String!
createdAt: String!
updatedAt: String!
work: Work!
}
type Copyright {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
workOwner: Author
works: [Work!]
translations: [Translation!]
books: [Book!]
sources: [Source!]
}
type CopyrightClaim {
id: ID!
details: String!
createdAt: String!
updatedAt: String!
work: Work
translation: Translation
book: Book
source: Source
author: Author
user: User
}
type Country {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
authors: [Author!]
users: [User!]
}
type City {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
country: Country
authors: [Author!]
users: [User!]
}
type Place {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
city: City
country: Country
authors: [Author!]
}
type Address {
id: ID!
street: String!
createdAt: String!
updatedAt: String!
city: City
country: Country
authors: [Author!]
users: [User!]
}
type Source {
id: ID!
name: String!
language: String!
createdAt: String!
updatedAt: String!
copyright: Copyright
copyrightClaims: [CopyrightClaim!]
works: [Work!]
}
type Edge {
id: ID!
sourceTable: String!
sourceId: ID!
targetTable: String!
targetId: ID!
relation: String!
language: String
extra: JSON
createdAt: String!
updatedAt: String!
}
scalar JSON
directive @binding(constraint: String!) on INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION
# Queries
type Query {
# Work queries
work(id: ID!): Work
works(
limit: Int
offset: Int
language: String
authorId: ID
categoryId: ID
tagId: ID
search: String
): [Work!]!
# Translation queries
translation(id: ID!): Translation
translations(
workId: ID!
language: String
limit: Int
offset: Int
): [Translation!]!
# Author queries
author(id: ID!): Author
authors(
limit: Int
offset: Int
search: String
countryId: ID
): [Author!]!
# User queries
user(id: ID!): User
userByEmail(email: String!): User
userByUsername(username: String!): User
users(
limit: Int
offset: Int
role: UserRole
): [User!]!
me: User
userProfile(userId: ID!): UserProfile
# Collection queries
collection(id: ID!): Collection
collections(
userId: ID
limit: Int
offset: Int
): [Collection!]!
# Tag queries
tag(id: ID!): Tag
tags(limit: Int, offset: Int): [Tag!]!
# Category queries
category(id: ID!): Category
categories(limit: Int, offset: Int): [Category!]!
# Comment queries
comment(id: ID!): Comment
comments(
workId: ID
translationId: ID
userId: ID
limit: Int
offset: Int
): [Comment!]!
# Search
search(
query: String!
limit: Int
offset: Int
filters: SearchFilters
): SearchResults!
trendingWorks(timePeriod: String, limit: Int): [Work!]!
}
input SearchFilters {
languages: [String!]
categories: [ID!]
tags: [ID!]
authors: [ID!]
dateFrom: String
dateTo: String
}
type SearchResults {
works: [Work!]!
translations: [Translation!]!
authors: [Author!]!
total: Int!
}
# Mutations
type Mutation {
# Authentication
register(input: RegisterInput!): AuthPayload!
login(input: LoginInput!): AuthPayload!
# Work mutations
createWork(input: WorkInput!): Work!
updateWork(id: ID!, input: WorkInput!): Work!
deleteWork(id: ID!): Boolean!
# Translation mutations
createTranslation(input: TranslationInput!): Translation!
updateTranslation(id: ID!, input: TranslationInput!): Translation!
deleteTranslation(id: ID!): Boolean!
# Author mutations
createAuthor(input: AuthorInput!): Author!
updateAuthor(id: ID!, input: AuthorInput!): Author!
deleteAuthor(id: ID!): Boolean!
# User mutations
updateUser(id: ID!, input: UserInput!): User!
deleteUser(id: ID!): Boolean!
# Collection mutations
createCollection(input: CollectionInput!): Collection!
updateCollection(id: ID!, input: CollectionInput!): Collection!
deleteCollection(id: ID!): Boolean!
addWorkToCollection(collectionId: ID!, workId: ID!): Collection!
removeWorkFromCollection(collectionId: ID!, workId: ID!): Collection!
# Comment mutations
createComment(input: CommentInput!): Comment!
updateComment(id: ID!, input: CommentInput!): Comment!
deleteComment(id: ID!): Boolean!
# Like mutations
createLike(input: LikeInput!): Like!
deleteLike(id: ID!): Boolean!
# Bookmark mutations
createBookmark(input: BookmarkInput!): Bookmark!
deleteBookmark(id: ID!): Boolean!
# Contribution mutations
createContribution(input: ContributionInput!): Contribution!
updateContribution(id: ID!, input: ContributionInput!): Contribution!
deleteContribution(id: ID!): Boolean!
reviewContribution(id: ID!, status: ContributionStatus!, feedback: String): Contribution!
# Additional authentication mutations
logout: Boolean!
refreshToken: AuthPayload!
forgotPassword(email: String!): Boolean!
resetPassword(token: String!, newPassword: String!): Boolean!
verifyEmail(token: String!): Boolean!
resendVerificationEmail(email: String!): Boolean!
# User profile mutations
updateProfile(input: UserInput!): User!
changePassword(currentPassword: String!, newPassword: String!): Boolean!
}
# Input types
input LoginInput {
email: String!
password: String!
}
input RegisterInput {
username: String!
email: String!
password: String!
firstName: String!
lastName: String!
}
type AuthPayload {
token: String!
user: User!
}
input WorkInput {
name: String!
language: String!
content: String
authorIds: [ID!]
tagIds: [ID!]
categoryIds: [ID!]
}
input TranslationInput {
name: String!
language: String!
content: String
workId: ID!
}
input AuthorInput {
name: String!
language: String!
biography: String
birthDate: String
deathDate: String
countryId: ID
cityId: ID
placeId: ID
addressId: ID
}
input UserInput {
username: String
email: String
password: String
firstName: String
lastName: String
displayName: String
bio: String
avatarUrl: String
role: UserRole
verified: Boolean
active: Boolean
countryId: ID
cityId: ID
addressId: ID
}
input CollectionInput {
name: String!
description: String
workIds: [ID!]
}
input CommentInput {
text: String!
workId: ID
translationId: ID
lineNumber: Int
parentCommentId: ID
}
input LikeInput {
workId: ID
translationId: ID
commentId: ID
}
input BookmarkInput {
name: String
workId: ID!
}
input ContributionInput {
name: String!
workId: ID
translationId: ID
status: ContributionStatus
}