import { authTables } from '@convex-dev/auth/server'; import { defineSchema, defineTable } from 'convex/server'; import { v } from 'convex/values'; const applicationTables = { /* * Below is the users table definition from authTables * You can add additional fields here. You can also remove * the users table here & create a 'profiles' table if you * prefer to keep auth data separate from application data. */ users: defineTable({ name: v.optional(v.string()), image: v.optional(v.string()), email: v.optional(v.string()), emailVerificationTime: v.optional(v.number()), phone: v.optional(v.string()), phoneVerificationTime: v.optional(v.number()), isAnonymous: v.optional(v.boolean()), /* Fields below here are custom & not defined in authTables */ isAdmin: v.optional(v.boolean()), role: v.optional(v.union(v.literal('owner'), v.literal('member'))), lastSeenAt: v.optional(v.number()), themePreference: v.optional( v.union(v.literal('light'), v.literal('dark'), v.literal('system')), ), }) .index('email', ['email']) .index('phone', ['phone']) /* Indexes below here are custom & not defined in authTables */ .index('name', ['name']), gitConnections: defineTable({ userId: v.id('users'), provider: v.union( v.literal('github'), v.literal('gitea'), v.literal('gitlab'), v.literal('other'), ), providerAccountId: v.optional(v.string()), displayName: v.string(), username: v.optional(v.string()), avatarUrl: v.optional(v.string()), installationId: v.optional(v.string()), scopes: v.optional(v.array(v.string())), status: v.union( v.literal('active'), v.literal('needs_reauth'), v.literal('revoked'), ), connectedAt: v.number(), updatedAt: v.number(), }) .index('by_user', ['userId']) .index('by_user_provider', ['userId', 'provider']) .index('by_status', ['status']), spoons: defineTable({ ownerId: v.id('users'), name: v.string(), description: v.optional(v.string()), provider: v.union( v.literal('github'), v.literal('gitea'), v.literal('gitlab'), v.literal('other'), ), upstreamOwner: v.string(), upstreamRepo: v.string(), upstreamDefaultBranch: v.string(), upstreamUrl: v.string(), forkOwner: v.optional(v.string()), forkRepo: v.optional(v.string()), forkDefaultBranch: v.optional(v.string()), forkUrl: v.optional(v.string()), visibility: v.union( v.literal('public'), v.literal('private'), v.literal('internal'), v.literal('unknown'), ), maintenanceMode: v.union( v.literal('watch'), v.literal('auto_pr'), v.literal('paused'), ), syncCadence: v.union( v.literal('daily'), v.literal('weekly'), v.literal('manual'), ), productionRefStrategy: v.union( v.literal('default_branch'), v.literal('latest_release'), v.literal('tag_pattern'), ), tagPattern: v.optional(v.string()), status: v.union( v.literal('draft'), v.literal('active'), v.literal('needs_connection'), v.literal('paused'), v.literal('archived'), ), lastCheckedAt: v.optional(v.number()), lastUpstreamCommit: v.optional(v.string()), lastForkCommit: v.optional(v.string()), createdAt: v.number(), updatedAt: v.number(), }) .index('by_owner', ['ownerId']) .index('by_owner_status', ['ownerId', 'status']) .index('by_owner_provider', ['ownerId', 'provider']) .index('by_upstream', ['provider', 'upstreamOwner', 'upstreamRepo']), syncRuns: defineTable({ spoonId: v.id('spoons'), ownerId: v.id('users'), kind: v.union( v.literal('scheduled_check'), v.literal('manual_check'), v.literal('upstream_update'), v.literal('merge_attempt'), v.literal('ai_review'), ), status: v.union( v.literal('queued'), v.literal('running'), v.literal('clean'), v.literal('conflict'), v.literal('needs_review'), v.literal('failed'), v.literal('merged'), ), upstreamFrom: v.optional(v.string()), upstreamTo: v.optional(v.string()), summary: v.optional(v.string()), aiAssessment: v.optional(v.string()), mergeRequestUrl: v.optional(v.string()), error: v.optional(v.string()), createdAt: v.number(), updatedAt: v.number(), }) .index('by_owner', ['ownerId']) .index('by_spoon', ['spoonId']) .index('by_owner_status', ['ownerId', 'status']) .index('by_created', ['createdAt']), agentRequests: defineTable({ spoonId: v.id('spoons'), ownerId: v.id('users'), prompt: v.string(), status: v.union( v.literal('draft'), v.literal('queued'), v.literal('running'), v.literal('changes_ready'), v.literal('merge_request_opened'), v.literal('failed'), v.literal('cancelled'), ), targetBranch: v.optional(v.string()), mergeRequestUrl: v.optional(v.string()), summary: v.optional(v.string()), error: v.optional(v.string()), createdAt: v.number(), updatedAt: v.number(), }) .index('by_owner', ['ownerId']) .index('by_spoon', ['spoonId']) .index('by_owner_status', ['ownerId', 'status']) .index('by_created', ['createdAt']), }; export default defineSchema({ ...authTables, ...applicationTables, });