import { z } from "zod"; // Enums for GraphQL/API export const roleEnum = z.enum([ "user", "contributor", "reviewer", "editor", "admin", ]); export const workTypeEnum = z.enum([ "poem", "story", "novel", "play", "essay", "other", ]); export const contributionStatusEnum = z.enum([ "draft", "submitted", "under_review", "approved", "rejected", ]); // Core entity schemas for GraphQL/API export const userSchema = z.object({ id: z.string(), username: z.string(), email: z.string(), displayName: z.string().optional(), firstName: z.string().optional(), lastName: z.string().optional(), bio: z.string().optional(), avatar: z.string().optional(), role: roleEnum, verified: z.boolean().optional(), active: z.boolean().optional(), lastLoginAt: z.string().optional(), createdAt: z.string(), // ISO date string updatedAt: z.string().optional(), countryId: z.string().optional(), cityId: z.string().optional(), }); export const authorSchema = z.object({ id: z.string(), name: z.string(), slug: z.string(), birthYear: z.number().optional(), deathYear: z.number().optional(), country: z.string().optional(), biography: z.string().optional(), portrait: z.string().optional(), createdAt: z.string(), createdBy: z.string().optional(), updatedAt: z.string().optional(), countryId: z.string().optional(), cityId: z.string().optional(), copyrightId: z.string().optional(), }); export const workSchema = z.object({ id: z.string(), title: z.string(), slug: z.string(), authorId: z.string(), year: z.number().optional(), type: workTypeEnum, language: z.string(), content: z.string(), description: z.string().optional(), createdAt: z.string(), createdBy: z.string().optional(), updatedAt: z.string().optional(), tags: z.array(z.string()).optional(), // Array of tag IDs likes: z.number().optional(), views: z.number().optional(), author: authorSchema.optional(), // For denormalized author info readabilityScore: z.number().optional(), copyrightId: z.string().optional(), }); export const translationSchema = z.object({ id: z.string(), workId: z.string(), title: z.string(), language: z.string(), content: z.string(), translatorId: z.string(), year: z.number().optional(), notes: z.string().optional(), description: z.string().optional(), createdAt: z.string(), }); export const tagSchema = z.object({ id: z.string(), name: z.string(), type: z.string(), // genre, period, theme, etc. createdAt: z.string(), }); export const bookmarkSchema = z.object({ id: z.string(), userId: z.string(), workId: z.string(), note: z.string().optional(), createdAt: z.string(), }); export const commentSchema = z.object({ id: z.string(), userId: z.string(), workId: z.string().optional(), translationId: z.string().optional(), lineNumber: z.number().optional(), content: z.string(), parentId: z.string().optional(), entityType: z.string().optional(), // 'work', 'translation', 'blogPost', etc. entityId: z.string().optional(), createdAt: z.string(), }); export const likeSchema = z.object({ id: z.string(), userId: z.string(), entityType: z.string(), // 'work', 'translation', 'comment' entityId: z.string(), createdAt: z.string(), }); export const collectionSchema = z.object({ id: z.string(), name: z.string(), slug: z.string(), description: z.string().optional(), userId: z.string(), isPublic: z.boolean(), createdAt: z.string(), }); export const collectionItemSchema = z.object({ id: z.string(), collectionId: z.string(), workId: z.string(), order: z.number(), addedAt: z.string(), }); export const timelineEventSchema = z.object({ id: z.string(), authorId: z.string(), year: z.number(), title: z.string(), description: z.string().optional(), createdAt: z.string(), }); export const blogPostSchema = z.object({ id: z.string(), title: z.string(), slug: z.string(), content: z.string(), authorId: z.string(), excerpt: z.string().optional(), publishedAt: z.string().optional(), createdAt: z.string(), }); export const readingProgressSchema = z.object({ id: z.string(), userId: z.string(), workId: z.string(), translationId: z.string().optional(), progress: z.number().min(0).max(100), // percentage lastReadAt: z.string(), }); export const annotationSchema = z.object({ id: z.string(), workId: z.string(), translationId: z.string().optional(), lineNumber: z.number().optional(), content: z.string(), type: z.string(), // 'context', 'analysis', 'translation', etc. userId: z.string(), isOfficial: z.boolean(), createdAt: z.string(), }); export const analysisResultSchema = z.object({ id: z.string(), workId: z.string(), type: z.string(), // 'sentiment', 'linguistics', 'themes', 'poetic', etc. data: z.record(z.string(), z.unknown()), // flexible data structure createdAt: z.string(), }); // New schemas for GraphQL alignment export const countrySchema = z.object({ id: z.string(), name: z.string(), code: z.string(), language: z.string(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const citySchema = z.object({ id: z.string(), name: z.string(), countryId: z.string(), language: z.string(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const bookSchema = z.object({ id: z.string(), title: z.string(), slug: z.string(), language: z.string(), authorId: z.string(), copyrightId: z.string().optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const copyrightSchema = z.object({ id: z.string(), name: z.string(), language: z.string(), details: z.string().optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const contributionSchema = z.object({ id: z.string(), name: z.string(), status: contributionStatusEnum, userId: z.string(), workId: z.string().optional(), translationId: z.string().optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const userProfileSchema = z.object({ id: z.string(), userId: z.string(), phoneNumber: z.string().optional(), website: z.string().optional(), twitter: z.string().optional(), facebook: z.string().optional(), linkedIn: z.string().optional(), github: z.string().optional(), preferences: z.record(z.string(), z.unknown()).optional(), settings: z.record(z.string(), z.unknown()).optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const readabilityScoreSchema = z.object({ id: z.string(), workId: z.string(), score: z.number(), language: z.string(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const writingStyleSchema = z.object({ id: z.string(), workId: z.string(), name: z.string(), language: z.string(), characteristics: z.record(z.string(), z.unknown()).optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const emotionSchema = z.object({ id: z.string(), name: z.string(), workId: z.string().optional(), userId: z.string().optional(), collectionId: z.string().optional(), language: z.string(), intensity: z.number().optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const conceptSchema = z.object({ id: z.string(), name: z.string(), description: z.string().optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const topicClusterSchema = z.object({ id: z.string(), name: z.string(), description: z.string().optional(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const workStatsSchema = z.object({ id: z.string(), workId: z.string(), views: z.number(), likes: z.number(), bookmarks: z.number(), comments: z.number(), createdAt: z.string(), updatedAt: z.string().optional(), }); export const userStatsSchema = z.object({ id: z.string(), userId: z.string(), activity: z.number(), contributions: z.number(), likes: z.number(), comments: z.number(), createdAt: z.string(), updatedAt: z.string().optional(), }); // Input schemas for GraphQL mutations/API endpoints export const createUserSchema = userSchema.omit({ id: true, createdAt: true, role: true, // Role assigned by system }); export const createAuthorSchema = authorSchema.omit({ id: true, createdAt: true, }); export const createWorkSchema = workSchema.omit({ id: true, createdAt: true, author: true, // Not included in creation }); export const createTranslationSchema = translationSchema.omit({ id: true, createdAt: true, }); export const createTagSchema = tagSchema.omit({ id: true, createdAt: true, }); export const createBookmarkSchema = bookmarkSchema.omit({ id: true, createdAt: true, }); export const createCommentSchema = commentSchema.omit({ id: true, createdAt: true, }); export const createLikeSchema = likeSchema.omit({ id: true, createdAt: true, }); export const createCollectionSchema = collectionSchema.omit({ id: true, createdAt: true, }); export const createCollectionItemSchema = collectionItemSchema.omit({ id: true, addedAt: true, }); export const createTimelineEventSchema = timelineEventSchema.omit({ id: true, createdAt: true, }); export const createBlogPostSchema = blogPostSchema.omit({ id: true, createdAt: true, }); export const createReadingProgressSchema = readingProgressSchema.omit({ id: true, lastReadAt: true, }); export const createAnnotationSchema = annotationSchema.omit({ id: true, createdAt: true, }); export const createAnalysisResultSchema = analysisResultSchema.omit({ id: true, createdAt: true, }); // New create schemas for GraphQL alignment export const createCountrySchema = countrySchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createCitySchema = citySchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createBookSchema = bookSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createCopyrightSchema = copyrightSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createContributionSchema = contributionSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createUserProfileSchema = userProfileSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createReadabilityScoreSchema = readabilityScoreSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createWritingStyleSchema = writingStyleSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createEmotionSchema = emotionSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createConceptSchema = conceptSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createTopicClusterSchema = topicClusterSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createWorkStatsSchema = workStatsSchema.omit({ id: true, createdAt: true, updatedAt: true, }); export const createUserStatsSchema = userStatsSchema.omit({ id: true, createdAt: true, updatedAt: true, }); // Update schemas for partial updates export const updateUserSchema = createUserSchema.partial(); export const updateAuthorSchema = createAuthorSchema.partial(); export const updateWorkSchema = createWorkSchema.partial(); export const updateTranslationSchema = createTranslationSchema.partial(); export const updateTagSchema = createTagSchema.partial(); export const updateBookmarkSchema = createBookmarkSchema.partial(); export const updateCommentSchema = createCommentSchema.partial(); export const updateCollectionSchema = createCollectionSchema.partial(); export const updateTimelineEventSchema = createTimelineEventSchema.partial(); export const updateBlogPostSchema = createBlogPostSchema.partial(); export const updateReadingProgressSchema = createReadingProgressSchema.partial(); export const updateAnnotationSchema = createAnnotationSchema.partial(); // New update schemas for GraphQL alignment export const updateCountrySchema = createCountrySchema.partial(); export const updateCitySchema = createCitySchema.partial(); export const updateBookSchema = createBookSchema.partial(); export const updateCopyrightSchema = createCopyrightSchema.partial(); export const updateContributionSchema = createContributionSchema.partial(); export const updateUserProfileSchema = createUserProfileSchema.partial(); export const updateReadabilityScoreSchema = createReadabilityScoreSchema.partial(); export const updateWritingStyleSchema = createWritingStyleSchema.partial(); export const updateEmotionSchema = createEmotionSchema.partial(); export const updateConceptSchema = createConceptSchema.partial(); export const updateTopicClusterSchema = createTopicClusterSchema.partial(); export const updateWorkStatsSchema = createWorkStatsSchema.partial(); export const updateUserStatsSchema = createUserStatsSchema.partial(); // TypeScript types inferred from Zod schemas export type User = z.infer; export type Author = z.infer; export type Work = z.infer; export type Translation = z.infer; export type Tag = z.infer; export type Bookmark = z.infer; export type Comment = z.infer; export type Like = z.infer; export type Collection = z.infer; export type CollectionItem = z.infer; export type TimelineEvent = z.infer; export type BlogPost = z.infer; export type ReadingProgress = z.infer; export type Annotation = z.infer; export type AnalysisResult = z.infer; // New types for GraphQL alignment export type Country = z.infer; export type City = z.infer; export type Book = z.infer; export type Copyright = z.infer; export type Contribution = z.infer; export type UserProfile = z.infer; export type ReadabilityScore = z.infer; export type WritingStyle = z.infer; export type Emotion = z.infer; export type Concept = z.infer; export type TopicCluster = z.infer; export type WorkStats = z.infer; export type UserStats = z.infer; // Input types export type CreateUser = z.infer; export type CreateAuthor = z.infer; export type CreateWork = z.infer; export type CreateTranslation = z.infer; export type CreateTag = z.infer; export type CreateBookmark = z.infer; export type CreateComment = z.infer; export type CreateLike = z.infer; export type CreateCollection = z.infer; export type CreateCollectionItem = z.infer; export type CreateTimelineEvent = z.infer; export type CreateBlogPost = z.infer; export type CreateReadingProgress = z.infer; export type CreateAnnotation = z.infer; export type CreateAnalysisResult = z.infer; // New create types for GraphQL alignment export type CreateCountry = z.infer; export type CreateCity = z.infer; export type CreateBook = z.infer; export type CreateCopyright = z.infer; export type CreateContribution = z.infer; export type CreateUserProfile = z.infer; export type CreateReadabilityScore = z.infer< typeof createReadabilityScoreSchema >; export type CreateWritingStyle = z.infer; export type CreateEmotion = z.infer; export type CreateConcept = z.infer; export type CreateTopicCluster = z.infer; export type CreateWorkStats = z.infer; export type CreateUserStats = z.infer; // Update types export type UpdateUser = z.infer; export type UpdateAuthor = z.infer; export type UpdateWork = z.infer; export type UpdateTranslation = z.infer; export type UpdateTag = z.infer; export type UpdateBookmark = z.infer; export type UpdateComment = z.infer; export type UpdateCollection = z.infer; export type UpdateTimelineEvent = z.infer; export type UpdateBlogPost = z.infer; export type UpdateReadingProgress = z.infer; export type UpdateAnnotation = z.infer; // New update types for GraphQL alignment export type UpdateCountry = z.infer; export type UpdateCity = z.infer; export type UpdateBook = z.infer; export type UpdateCopyright = z.infer; export type UpdateContribution = z.infer; export type UpdateUserProfile = z.infer; export type UpdateReadabilityScore = z.infer< typeof updateReadabilityScoreSchema >; export type UpdateWritingStyle = z.infer; export type UpdateEmotion = z.infer; export type UpdateConcept = z.infer; export type UpdateTopicCluster = z.infer; export type UpdateWorkStats = z.infer; export type UpdateUserStats = z.infer; // API Response schemas export const apiResponseSchema = z.object({ success: z.boolean(), data: z.unknown().optional(), error: z.string().optional(), message: z.string().optional(), }); export const paginatedResponseSchema = z.object({ data: z.array(z.unknown()), pagination: z.object({ page: z.number(), limit: z.number(), total: z.number(), totalPages: z.number(), }), }); export type ApiResponse = z.infer; export type PaginatedResponse = z.infer;