From eef5f217175058c6a42b931b057f2fbf7d05cffa Mon Sep 17 00:00:00 2001 From: nutcas3 Date: Fri, 17 Apr 2026 15:21:21 +0300 Subject: [PATCH] feat: Add GraphQL code generation scaffolding with comprehensive type definitions and resolver interfaces - Add custom GraphQL types and enums: SubscriberStatus, ProfileStatus, UsageType, SessionStatus, PaymentMethodType, InvoiceStatus, AlertType, AlertSeverity, SubscriberSort, UsagePeriod, TrendDirection - Define input types: SubscriberFilter, UsageEventFilter, CreateSubscriberInput, UpdateSubscriberInput, TopUpInput, UsageStatsInput, PaymentMethodInput, CreateAlertInput - Define output types: Page --- apps/api-server/internal/graphql/generated.go | 375 ++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 apps/api-server/internal/graphql/generated.go diff --git a/apps/api-server/internal/graphql/generated.go b/apps/api-server/internal/graphql/generated.go new file mode 100644 index 0000000..7d82700 --- /dev/null +++ b/apps/api-server/internal/graphql/generated.go @@ -0,0 +1,375 @@ +package graphql + +// This file will be generated by gqlgen +// Run: go run github.com/99designs/gqlgen generate + +import ( + "context" + "time" + + "github.com/99designs/gqlgen/graphql" + "github.com/nutcas3/telecom-platform/apps/api-server/internal/models" + "github.com/vektah/gqlparser/v2/ast" +) + +// GraphQL type definitions +type SubscriberStatus string +type ProfileStatus string +type UsageType string +type SessionStatus string +type PaymentMethodType string +type InvoiceStatus string +type AlertType string +type AlertSeverity string +type SubscriberSort string +type UsagePeriod string +type TrendDirection string + +const ( + SubscriberStatusActive SubscriberStatus = "ACTIVE" + SubscriberStatusInactive SubscriberStatus = "INACTIVE" + SubscriberStatusSuspended SubscriberStatus = "SUSPENDED" + SubscriberStatusTerminated SubscriberStatus = "TERMINATED" + SubscriberStatusProvisioning SubscriberStatus = "PROVISIONING" +) + +const ( + ProfileStatusActive ProfileStatus = "ACTIVE" + ProfileStatusInactive ProfileStatus = "INACTIVE" + ProfileStatusDownloading ProfileStatus = "DOWNLOADING" + ProfileStatusFailed ProfileStatus = "FAILED" +) + +const ( + UsageTypeData UsageType = "DATA" + UsageTypeVoice UsageType = "VOICE" + UsageTypeSMS UsageType = "SMS" +) + +const ( + SessionStatusActive SessionStatus = "ACTIVE" + SessionStatusCompleted SessionStatus = "COMPLETED" + SessionStatusTerminated SessionStatus = "TERMINATED" +) + +const ( + PaymentMethodTypeCreditCard PaymentMethodType = "CREDIT_CARD" + PaymentMethodTypeBankAccount PaymentMethodType = "BANK_ACCOUNT" +) + +const ( + InvoiceStatusDraft InvoiceStatus = "DRAFT" + InvoiceStatusPending InvoiceStatus = "PENDING" + InvoiceStatusPaid InvoiceStatus = "PAID" + InvoiceStatusOverdue InvoiceStatus = "OVERDUE" + InvoiceStatusCancelled InvoiceStatus = "CANCELLED" +) + +const ( + AlertTypeLowBalance AlertType = "LOW_BALANCE" + AlertTypeHighUsage AlertType = "HIGH_USAGE" + AlertTypePaymentFailed AlertType = "PAYMENT_FAILED" + AlertTypeSystemError AlertType = "SYSTEM_ERROR" +) + +const ( + AlertSeverityLow AlertSeverity = "LOW" + AlertSeverityMedium AlertSeverity = "MEDIUM" + AlertSeverityHigh AlertSeverity = "HIGH" + AlertSeverityCritical AlertSeverity = "CRITICAL" +) + +const ( + SubscriberSortCreatedAtAsc SubscriberSort = "CREATED_AT_ASC" + SubscriberSortCreatedAtDesc SubscriberSort = "CREATED_AT_DESC" + SubscriberSortUpdatedAtAsc SubscriberSort = "UPDATED_AT_ASC" + SubscriberSortUpdatedAtDesc SubscriberSort = "UPDATED_AT_DESC" + SubscriberSortFirstNameAsc SubscriberSort = "FIRST_NAME_ASC" + SubscriberSortFirstNameDesc SubscriberSort = "FIRST_NAME_DESC" + SubscriberSortLastNameAsc SubscriberSort = "LAST_NAME_ASC" + SubscriberSortLastNameDesc SubscriberSort = "LAST_NAME_DESC" + SubscriberSortEmailAsc SubscriberSort = "EMAIL_ASC" + SubscriberSortEmailDesc SubscriberSort = "EMAIL_DESC" + SubscriberSortBalanceAsc SubscriberSort = "BALANCE_ASC" + SubscriberSortBalanceDesc SubscriberSort = "BALANCE_DESC" + SubscriberSortDataUsedAsc SubscriberSort = "DATA_USED_ASC" + SubscriberSortDataUsedDesc SubscriberSort = "DATA_USED_DESC" +) + +const ( + UsagePeriodDaily UsagePeriod = "DAILY" + UsagePeriodWeekly UsagePeriod = "WEEKLY" + UsagePeriodMonthly UsagePeriod = "MONTHLY" + UsagePeriodYearly UsagePeriod = "YEARLY" +) + +const ( + TrendDirectionUp TrendDirection = "UP" + TrendDirectionDown TrendDirection = "DOWN" + TrendDirectionStable TrendDirection = "STABLE" +) + +// Input types +type SubscriberFilter struct { + Status *SubscriberStatus `json:"status"` + OrganizationID *string `json:"organizationId"` + PlanID *int `json:"planId"` + Search *string `json:"search"` + BalanceMin *float64 `json:"balanceMin"` + BalanceMax *float64 `json:"balanceMax"` + DataUsageMin *float64 `json:"dataUsageMin"` + DataUsageMax *float64 `json:"dataUsageMax"` +} + +type UsageEventFilter struct { + UsageType *UsageType `json:"usageType"` + TimestampGte *time.Time `json:"timestampGte"` + TimestampLte *time.Time `json:"timestampLte"` + CostMin *float64 `json:"costMin"` + CostMax *float64 `json:"costMax"` +} + +type CreateSubscriberInput struct { + MSISDN string `json:"msisdn"` + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + Email string `json:"email"` + OrganizationID *string `json:"organizationId"` + PlanID int `json:"planId"` + EUICCID *string `json:"euiccId"` +} + +type UpdateSubscriberInput struct { + FirstName *string `json:"firstName"` + LastName *string `json:"lastName"` + Email *string `json:"email"` + OrganizationID *string `json:"organizationId"` + PlanID *int `json:"planId"` +} + +type TopUpInput struct { + Amount float64 `json:"amount"` + PaymentMethodID *string `json:"paymentMethodId"` +} + +type UsageStatsInput struct { + IMSI string `json:"imsi"` + Period UsagePeriod `json:"period"` +} + +type PaymentMethodInput struct { + Type PaymentMethodType `json:"type"` + Token string `json:"token"` + IsDefault *bool `json:"isDefault"` +} + +type CreateAlertInput struct { + Type AlertType `json:"type"` + Severity AlertSeverity `json:"severity"` + Message string `json:"message"` + SubscriberID *int `json:"subscriberId"` +} + +// Output types +type PageInfo struct { + HasNextPage bool `json:"hasNextPage"` + HasPreviousPage bool `json:"hasPreviousPage"` + StartCursor *string `json:"startCursor"` + EndCursor *string `json:"endCursor"` +} + +type SubscriberEdge struct { + Node *models.Subscriber `json:"node"` + Cursor string `json:"cursor"` +} + +type SubscriberConnection struct { + Edges []*SubscriberEdge `json:"edges"` + PageInfo *PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +type UsageEventEdge struct { + Node *models.UsageEvent `json:"node"` + Cursor string `json:"cursor"` +} + +type UsageEventConnection struct { + Edges []*UsageEventEdge `json:"edges"` + PageInfo *PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +type InvoiceEdge struct { + Node *models.Invoice `json:"node"` + Cursor string `json:"cursor"` +} + +type InvoiceConnection struct { + Edges []*InvoiceEdge `json:"edges"` + PageInfo *PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +type AlertEdge struct { + Node *models.Alert `json:"node"` + Cursor string `json:"cursor"` +} + +type AlertConnection struct { + Edges []*AlertEdge `json:"edges"` + PageInfo *PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +type ChargingSessionEdge struct { + Node *ChargingSession `json:"node"` + Cursor string `json:"cursor"` +} + +type ChargingSessionConnection struct { + Edges []*ChargingSessionEdge `json:"edges"` + PageInfo *PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +type UsageTrend struct { + Direction TrendDirection `json:"direction"` + Percentage float64 `json:"percentage"` + PeriodOverPeriod float64 `json:"periodOverPeriod"` +} + +type UsageStats struct { + DataUsage float64 `json:"dataUsage"` + VoiceUsage float64 `json:"voiceUsage"` + SmsUsage float64 `json:"smsUsage"` + Cost float64 `json:"cost"` + Period string `json:"period"` + Trend *UsageTrend `json:"trend"` +} + +type CurrentSession struct { + SessionID string `json:"sessionId"` + StartTime time.Time `json:"startTime"` + DataUsed float64 `json:"dataUsed"` + VoiceUsed float64 `json:"voiceUsed"` + SmsUsed float64 `json:"smsUsed"` + Cost float64 `json:"cost"` +} + +type TodayUsage struct { + DataUsed float64 `json:"dataUsed"` + VoiceUsed float64 `json:"voiceUsed"` + SmsUsed float64 `json:"smsUsed"` + Cost float64 `json:"cost"` +} + +type RealTimeUsage struct { + CurrentSession *CurrentSession `json:"currentSession"` + TodayUsage *TodayUsage `json:"todayUsage"` +} + +type ESIMProvisionResult struct { + ProfileID string `json:"profileId"` + ActivationCode string `json:"activationCode"` + QRCode string `json:"qrCode"` +} + +type ChargingSession struct { + SessionID string `json:"sessionId"` + IMSI string `json:"imsi"` + StartTime time.Time `json:"startTime"` + EndTime *time.Time `json:"endTime"` + DataBytes float64 `json:"dataBytes"` + VoiceSeconds float64 `json:"voiceSeconds"` + SmsCount float64 `json:"smsCount"` + TotalCost float64 `json:"totalCost"` + Status SessionStatus `json:"status"` +} + +// GraphQL configuration +type Config struct { + Resolvers ResolverRoot +} + +type ResolverRoot interface { + Query() QueryResolver + Mutation() MutationResolver + Subscription() SubscriptionResolver +} + +type QueryResolver interface { + Subscriber(ctx context.Context, id string) (*models.Subscriber, error) + SubscriberByImsi(ctx context.Context, imsi string) (*models.Subscriber, error) + Subscribers(ctx context.Context, first *int, after *string, filter *SubscriberFilter, sort *SubscriberSort) (*SubscriberConnection, error) + SubscriberAccount(ctx context.Context, imsi string) (*models.SubscriberAccount, error) + UsageEvents(ctx context.Context, first *int, after *string, imsi *string, filter *UsageEventFilter) (*UsageEventConnection, error) + UsageStats(ctx context.Context, input UsageStatsInput) (*UsageStats, error) + RealTimeUsage(ctx context.Context, imsi string) (*RealTimeUsage, error) + Invoices(ctx context.Context, first *int, after *string, imsi *string, status *models.InvoiceStatus) (*InvoiceConnection, error) + Invoice(ctx context.Context, id string) (*models.Invoice, error) + RatingPlans(ctx context.Context) ([]*models.RatingPlan, error) + RatingPlan(ctx context.Context, planId string) (*models.RatingPlan, error) + ChargingSessions(ctx context.Context, first *int, after *string, imsi *string, status *SessionStatus) (*ChargingSessionConnection, error) + ChargingSession(ctx context.Context, sessionId string) (*ChargingSession, error) + Alerts(ctx context.Context, first *int, after *string, subscriberId *int, severity *models.AlertSeverity, resolved *bool) (*AlertConnection, error) + SystemStats(ctx context.Context) (*models.SystemStats, error) + HealthStatus(ctx context.Context) (*models.HealthStatus, error) + SearchSubscribers(ctx context.Context, query string, limit int) ([]*models.Subscriber, error) + SearchUsageEvents(ctx context.Context, query string, limit int) ([]*models.UsageEvent, error) +} + +type MutationResolver interface { + CreateSubscriber(ctx context.Context, input CreateSubscriberInput) (*models.Subscriber, error) + UpdateSubscriber(ctx context.Context, id string, input UpdateSubscriberInput) (*models.Subscriber, error) + DeleteSubscriber(ctx context.Context, id string) (bool, error) + TopUpBalance(ctx context.Context, imsi string, input TopUpInput) (*models.SubscriberAccount, error) + SuspendSubscriber(ctx context.Context, id string) (*models.Subscriber, error) + ActivateSubscriber(ctx context.Context, id string) (*models.Subscriber, error) + TerminateSubscriber(ctx context.Context, id string) (*models.Subscriber, error) + ProvisionESIM(ctx context.Context, imsi string) (*ESIMProvisionResult, error) + ActivateESIM(ctx context.Context, imsi string, profileId string) (bool, error) + DeactivateESIM(ctx context.Context, imsi string, profileId string) (bool, error) + AddPaymentMethod(ctx context.Context, subscriberId int, input PaymentMethodInput) (*models.PaymentMethod, error) + RemovePaymentMethod(ctx context.Context, paymentMethodId string) (bool, error) + SetDefaultPaymentMethod(ctx context.Context, paymentMethodId string) (*models.PaymentMethod, error) + ResolveAlert(ctx context.Context, alertId string) (*models.Alert, error) + CreateAlert(ctx context.Context, input CreateAlertInput) (*models.Alert, error) + TriggerSystemMaintenance(ctx context.Context) (bool, error) +} + +type SubscriptionResolver interface { + SubscriberUpdates(ctx context.Context, subscriberId string) (<-chan *models.Subscriber, error) + UsageUpdates(ctx context.Context, imsi string) (<-chan *models.UsageEvent, error) + AlertUpdates(ctx context.Context, severity models.AlertSeverity) (<-chan *models.Alert, error) + SystemStatsUpdates(ctx context.Context) (<-chan *models.SystemStats, error) +} + +func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { + return &executableSchema{ + resolvers: cfg.Resolvers, + } +} + +type executableSchema struct { + resolvers ResolverRoot +} + +func (e *executableSchema) Schema() *ast.Schema { + // This would be generated by gqlgen + return nil +} + +func (e *executableSchema) Complexity(ctx context.Context, typeName, fieldName string, childComplexity int, args map[string]any) (int, bool) { + // Default complexity calculation + return childComplexity, true +} + +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + // This would be generated by gqlgen + return nil +} + +func (e *executableSchema) Extensions() map[string]interface{} { + return map[string]interface{}{} +}