services

package
v1.0.0-beta Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package services provides business logic layer for GitScrum CLI

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnauthorized    = errors.New("unauthorized")
	ErrPaymentRequired = errors.New("payment_required")
	ErrForbidden       = errors.New("forbidden")
	ErrNotFound        = errors.New("not_found")
	ErrConflict        = errors.New("conflict")
	ErrValidation      = errors.New("validation")
	ErrRateLimited     = errors.New("rate_limited")
	ErrServerError     = errors.New("server_error")
)

Sentinel errors for type checking

Functions

func IsConflict

func IsConflict(err error) bool

IsConflict checks if the error indicates a resource conflict (409)

func IsNotFound

func IsNotFound(err error) bool

IsNotFound checks if the error indicates resource not found (404)

func IsPaymentRequired

func IsPaymentRequired(err error) bool

IsPaymentRequired checks if the error indicates PRO subscription is needed (402)

func IsRateLimited

func IsRateLimited(err error) bool

IsRateLimited checks if the error indicates rate limiting (429)

func IsServerError

func IsServerError(err error) bool

IsServerError checks if the error is a server-side error (500+)

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized checks if the error indicates authentication is needed (401)

Types

type APIError

type APIError struct {
	StatusCode int                 `json:"-"`
	Type       error               `json:"-"`
	Message    string              `json:"message"`
	Errors     map[string][]string `json:"errors,omitempty"`
	Feature    string              `json:"feature,omitempty"`
	UpgradeURL string              `json:"upgrade_url,omitempty"`
}

APIError represents an error from the API with sanitized message

func (*APIError) Error

func (e *APIError) Error() string

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

type ActiveTimer

type ActiveTimer struct {
	UUID    string `json:"uuid"`
	Start   string `json:"start"`
	Comment string `json:"comment"`
	Task    Task   `json:"issue"`
}

ActiveTimer represents a running time entry

type AnalyticsData

type AnalyticsData struct {
	TasksCreated   int               `json:"tasks_created"`
	TasksCompleted int               `json:"tasks_completed"`
	TimeSpent      float64           `json:"time_spent"`
	Velocity       float64           `json:"velocity"`
	ByStatus       map[string]int    `json:"by_status"`
	ByMember       []MemberAnalytics `json:"by_member"`
}

AnalyticsData represents analytics metrics

type AnalyticsService

type AnalyticsService interface {
	// ProjectAnalytics returns analytics for a project
	ProjectAnalytics(project string, period string) (*AnalyticsData, error)

	// TeamAnalytics returns team-wide analytics
	TeamAnalytics(period string) (*AnalyticsData, error)
}

AnalyticsService handles analytics operations

type AuthService

type AuthService interface {
	// WhoAmI returns the current authenticated user
	WhoAmI() (*AuthUser, error)

	// ValidateToken checks if current token is valid
	ValidateToken() (bool, error)
}

AuthService handles authentication operations

type AuthUser

type AuthUser struct {
	User
	Workspaces []Workspace `json:"workspaces"`
}

AuthUser represents the authenticated user

type Branch

type Branch struct {
	UUID      string `json:"uuid"`
	Name      string `json:"name"`
	URL       string `json:"url"`
	CreatedAt string `json:"created_at"`
}

Branch represents a linked git branch

type CRMContact

type CRMContact struct {
	UUID    string `json:"uuid"`
	Name    string `json:"name"`
	Email   string `json:"email"`
	Company string `json:"company"`
	Phone   string `json:"phone"`
	Status  string `json:"status"`
	Source  string `json:"source"`
	Notes   string `json:"notes"`
}

CRMContact represents a CRM contact

type CRMDeal

type CRMDeal struct {
	UUID        string     `json:"uuid"`
	Title       string     `json:"title"`
	Value       float64    `json:"value"`
	Stage       string     `json:"stage"`
	Contact     CRMContact `json:"contact"`
	Probability int        `json:"probability"`
}

CRMDeal represents a CRM deal

type CRMService

type CRMService interface {
	// ListContacts returns all contacts
	ListContacts() ([]CRMContact, error)

	// ListDeals returns all deals
	ListDeals() ([]CRMDeal, error)
}

CRMService handles CRM operations

type ChatChannel

type ChatChannel struct {
	UUID        string `json:"uuid"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Type        string `json:"type"` // project, direct, team
}

ChatChannel represents a chat channel

type ChatMessage

type ChatMessage struct {
	UUID      string    `json:"uuid"`
	Content   string    `json:"content"`
	Author    User      `json:"author"`
	CreatedAt time.Time `json:"created_at"`
}

ChatMessage represents a chat message

type ChatService

type ChatService interface {
	// ListChannels returns available channels
	ListChannels() ([]ChatChannel, error)

	// ListMessages returns messages from a channel
	ListMessages(channelID string, limit int) ([]ChatMessage, error)

	// SendMessage sends a message to a channel
	SendMessage(channelID, content string) (*ChatMessage, error)
}

ChatService handles chat operations

type Client

type Client struct {
	UUID    string `json:"uuid"`
	Name    string `json:"name"`
	Email   string `json:"email"`
	Company string `json:"company"`
	Phone   string `json:"phone"`
	Status  string `json:"status"` // active, inactive
}

Client represents a client/customer

type ClientsService

type ClientsService interface {
	// List returns all clients
	List() ([]Client, error)

	// Get returns a client by ID
	Get(uuid string) (*Client, error)

	// Create creates a new client
	Create(name, email, company string) (*Client, error)
}

ClientsService handles client operations

type Contributor

type Contributor struct {
	User         User    `json:"user"`
	TasksDone    int     `json:"tasks_done"`
	TrackedHours float64 `json:"tracked_hours"`
}

Contributor represents a contributor's activity

type CreateProjectInput

type CreateProjectInput struct {
	Name        string
	Description string
	Workspace   string
}

CreateProjectInput for creating a new project

type CreateSprintInput

type CreateSprintInput struct {
	Title     string
	StartDate time.Time
	EndDate   time.Time
	Goal      string
	Project   string
}

CreateSprintInput for creating a new sprint

type CreateTaskInput

type CreateTaskInput struct {
	Title       string
	Description string
	Project     string
	Assignee    string
	Type        string
	Priority    string
	Parent      string
}

CreateTaskInput for creating a new task

type DayDigest

type DayDigest struct {
	Date         string `json:"date"`
	DoneTasks    int    `json:"done_count"`
	ActiveTasks  int    `json:"active_count"`
	BlockedTasks int    `json:"blocked_count"`
}

DayDigest represents a single day's metrics

type DayTime

type DayTime struct {
	Date  string  `json:"date"`
	Hours float64 `json:"hours"`
}

DayTime represents time spent on a day

type HTTPClient

type HTTPClient interface {
	Get(path string) (*http.Response, error)
	Post(path string, body interface{}) (*http.Response, error)
	Put(path string, body interface{}) (*http.Response, error)
	Delete(path string) (*http.Response, error)
}

HTTPClient interface for mocking

type Invoice

type Invoice struct {
	UUID      string    `json:"uuid"`
	Number    string    `json:"number"`
	Client    Client    `json:"client"`
	Amount    float64   `json:"amount"`
	Status    string    `json:"status"` // draft, sent, paid, overdue
	DueDate   time.Time `json:"due_date"`
	PaidAt    time.Time `json:"paid_at"`
	CreatedAt time.Time `json:"created_at"`
}

Invoice represents an invoice

type InvoicesService

type InvoicesService interface {
	// List returns all invoices
	List(status string) ([]Invoice, error)

	// Get returns an invoice by ID
	Get(uuid string) (*Invoice, error)

	// MarkAsPaid marks invoice as paid
	MarkAsPaid(uuid string) (*Invoice, error)
}

InvoicesService handles invoice operations

type Label

type Label struct {
	UUID  string `json:"uuid"`
	Title string `json:"title"`
	Color string `json:"color"`
}

Label represents a task label

type ListResponse

type ListResponse[T any] struct {
	Data       []T        `json:"data"`
	Pagination Pagination `json:"meta"`
}

ListResponse wraps paginated list responses

type MemberAnalytics

type MemberAnalytics struct {
	User           User    `json:"user"`
	TasksCompleted int     `json:"tasks_completed"`
	TimeSpent      float64 `json:"time_spent"`
}

MemberAnalytics represents per-user analytics

type MockCall

type MockCall struct {
	Method string
	Path   string
	Body   interface{}
}

MockCall tracks a method call

type MockClient

type MockClient struct {
	// Responses to return for each method
	GetResponses    map[string]*MockResponse
	PostResponses   map[string]*MockResponse
	PutResponses    map[string]*MockResponse
	DeleteResponses map[string]*MockResponse

	// Default response if path not found
	DefaultResponse *MockResponse

	// Track calls for assertions
	Calls []MockCall
}

MockClient for testing

func NewMockClient

func NewMockClient() *MockClient

NewMockClient creates a new mock client

func (*MockClient) AssertCalled

func (m *MockClient) AssertCalled(method, path string) bool

AssertCalled checks if a path was called with the given method

func (*MockClient) CallCount

func (m *MockClient) CallCount(method, path string) int

CallCount returns the number of calls to a path

func (*MockClient) Delete

func (m *MockClient) Delete(path string) (*http.Response, error)

func (*MockClient) Get

func (m *MockClient) Get(path string) (*http.Response, error)

func (*MockClient) OnDelete

func (m *MockClient) OnDelete(path string, statusCode int, body interface{}) *MockClient

OnDelete sets the response for a DELETE request

func (*MockClient) OnGet

func (m *MockClient) OnGet(path string, statusCode int, body interface{}) *MockClient

OnGet sets the response for a GET request

func (*MockClient) OnGetError

func (m *MockClient) OnGetError(path string, err error) *MockClient

OnGetError sets an error for a GET request

func (*MockClient) OnPost

func (m *MockClient) OnPost(path string, statusCode int, body interface{}) *MockClient

OnPost sets the response for a POST request

func (*MockClient) OnProRequired

func (m *MockClient) OnProRequired(path string) *MockClient

OnProRequired sets a 409 PRO required response

func (*MockClient) OnPut

func (m *MockClient) OnPut(path string, statusCode int, body interface{}) *MockClient

OnPut sets the response for a PUT request

func (*MockClient) OnUnauthorized

func (m *MockClient) OnUnauthorized(path string) *MockClient

OnUnauthorized sets a 401 response

func (*MockClient) Post

func (m *MockClient) Post(path string, body interface{}) (*http.Response, error)

func (*MockClient) Put

func (m *MockClient) Put(path string, body interface{}) (*http.Response, error)

type MockResponse

type MockResponse struct {
	StatusCode int
	Body       interface{}
	Error      error
}

MockResponse represents a mocked HTTP response

type Notification

type Notification struct {
	UUID      string    `json:"uuid"`
	Type      string    `json:"type"`
	Title     string    `json:"title"`
	Body      string    `json:"body"`
	Read      bool      `json:"read"`
	CreatedAt time.Time `json:"created_at"`
}

Notification represents a notification

type NotificationsService

type NotificationsService interface {
	// List returns recent notifications
	List(unreadOnly bool) ([]Notification, error)

	// MarkAsRead marks a notification as read
	MarkAsRead(uuid string) error

	// MarkAllAsRead marks all notifications as read
	MarkAllAsRead() error
}

NotificationsService handles notification operations

type Pagination

type Pagination struct {
	Total       int `json:"total"`
	PerPage     int `json:"per_page"`
	CurrentPage int `json:"current_page"`
	LastPage    int `json:"last_page"`
}

Pagination for list responses

type Point

type Point struct {
	Date   string  `json:"date"`
	Ideal  float64 `json:"ideal"`
	Actual float64 `json:"actual"`
}

Point for burndown charts

type Productivity

type Productivity struct {
	Score      float64 `json:"score"`
	TotalHours float64 `json:"total_hours"`
	TasksDone  int     `json:"tasks_done"`
	AvgPerDay  float64 `json:"avg_per_day"`
}

Productivity represents productivity metrics

type Project

type Project struct {
	UUID        string `json:"uuid"`
	Slug        string `json:"slug"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Color       string `json:"color"`
}

Project represents a project

type ProjectDetails

type ProjectDetails struct {
	Project
	TasksCount     int     `json:"tasks_count"`
	CompletedCount int     `json:"completed_count"`
	MembersCount   int     `json:"members_count"`
	Progress       float64 `json:"progress"`
	CurrentSprint  *Sprint `json:"current_sprint"`
}

ProjectDetails represents detailed project info

type ProjectMember

type ProjectMember struct {
	User
	Role string `json:"role"`
}

ProjectMember represents a project team member

type ProjectTime

type ProjectTime struct {
	Project Project `json:"project"`
	Hours   float64 `json:"hours"`
}

ProjectTime represents time spent on a project

type ProjectsService

type ProjectsService interface {
	// List returns all projects
	List() ([]Project, error)

	// Get returns a project by slug
	Get(slug string) (*ProjectDetails, error)

	// Create creates a new project
	Create(input CreateProjectInput) (*Project, error)

	// ListMembers returns project team members
	ListMembers(slug string) ([]ProjectMember, error)

	// ListWorkflows returns project workflow stages
	ListWorkflows(slug string) ([]Status, error)
}

ProjectsService handles project operations

type Proposal

type Proposal struct {
	UUID      string    `json:"uuid"`
	Title     string    `json:"title"`
	Client    Client    `json:"client"`
	Amount    float64   `json:"amount"`
	Status    string    `json:"status"` // draft, sent, accepted, rejected
	ExpiresAt time.Time `json:"expires_at"`
	CreatedAt time.Time `json:"created_at"`
}

Proposal represents a proposal/quote

type ProposalsService

type ProposalsService interface {
	// List returns all proposals
	List(status string) ([]Proposal, error)

	// Get returns a proposal by ID
	Get(uuid string) (*Proposal, error)

	// Send sends a proposal to the client
	Send(uuid string) (*Proposal, error)
}

ProposalsService handles proposal operations

type PullRequest

type PullRequest struct {
	UUID   string `json:"uuid"`
	Title  string `json:"title"`
	Number int    `json:"number"`
	State  string `json:"state"`
	URL    string `json:"url"`
}

PullRequest represents a linked pull request

type Services

type Services struct {

	// Domain services
	Tasks         TasksService
	Timer         TimerService
	Projects      ProjectsService
	Sprints       SprintsService
	Auth          AuthService
	Analytics     AnalyticsService
	Chat          ChatService
	Clients       ClientsService
	CRM           CRMService
	Invoices      InvoicesService
	Notifications NotificationsService
	Proposals     ProposalsService
	Standup       StandupService
	Wiki          WikiService
	Workspaces    WorkspacesService
	// contains filtered or unexported fields
}

Services container provides access to all domain services

func New

func New(client *api.Client) *Services

New creates all services with the given API client

func (*Services) Client

func (s *Services) Client() *api.Client

Client returns the underlying API client (for custom requests)

type SingleResponse

type SingleResponse[T any] struct {
	Data T `json:"data"`
}

SingleResponse wraps single item responses

type Sprint

type Sprint struct {
	UUID      string    `json:"uuid"`
	Title     string    `json:"title"`
	StartDate time.Time `json:"start_date"`
	EndDate   time.Time `json:"end_date"`
	Status    string    `json:"status"` // planned, active, completed
	Goal      string    `json:"goal"`
	Progress  float64   `json:"progress"`
}

Sprint represents a sprint

type SprintStats

type SprintStats struct {
	TotalTasks     int     `json:"total_tasks"`
	CompletedTasks int     `json:"completed_tasks"`
	TotalPoints    int     `json:"total_points"`
	BurndownData   []Point `json:"burndown"`
}

SprintStats represents sprint statistics

type SprintsService

type SprintsService interface {
	// List returns all sprints for a project
	List(project string) ([]Sprint, error)

	// GetActive returns the active sprint for a project
	GetActive(project string) (*Sprint, error)

	// Get returns a sprint by ID
	Get(uuid string) (*Sprint, error)

	// Create creates a new sprint
	Create(input CreateSprintInput) (*Sprint, error)

	// Start activates a sprint
	Start(uuid string) (*Sprint, error)

	// Complete ends a sprint
	Complete(uuid string) (*Sprint, error)

	// Stats returns sprint statistics
	Stats(uuid string) (*SprintStats, error)

	// ListTasks returns tasks in a sprint
	ListTasks(uuid string) ([]Task, error)
}

SprintsService handles sprint operations

type StandupService

type StandupService interface {
	// Summary returns aggregated standup stats for workspace
	Summary(workspaceSlug string) (*TeamStandupSummary, error)

	// CompletedYesterday returns tasks completed yesterday
	CompletedYesterday(workspaceSlug string) ([]StandupTask, error)

	// Blockers returns current blocking tasks
	Blockers(workspaceSlug string) ([]StandupTask, error)

	// TeamStatus returns team members' status
	TeamStatus(workspaceSlug string) ([]TeamMemberStatus, error)

	// WeeklyDigest returns weekly metrics
	WeeklyDigest(workspaceSlug string) (*WeeklyDigest, error)

	// Contributors returns contributors for period
	Contributors(workspaceSlug, period string) ([]Contributor, error)
}

StandupService handles team standup operations

type StandupTask

type StandupTask struct {
	UUID      string `json:"uuid"`
	Code      string `json:"code"`
	Title     string `json:"title"`
	Status    string `json:"workflow_name"`
	Assignees []User `json:"users"`
}

StandupTask represents a task in standup context

type Status

type Status struct {
	UUID  string `json:"uuid"`
	Title string `json:"title"`
	Color string `json:"color"`
	Slug  string `json:"slug"`
}

Status represents a workflow status

type Task

type Task struct {
	UUID        string    `json:"uuid"`
	Code        string    `json:"code"`
	Title       string    `json:"title"`
	Description string    `json:"description"`
	Type        string    `json:"type"`
	Priority    int       `json:"priority"`
	Effort      int       `json:"effort"`
	DueDate     string    `json:"due_date"`
	StartDate   string    `json:"start_date"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`

	// Relationships
	Status   Status  `json:"status"`
	Assignee User    `json:"assignee"`
	Author   User    `json:"author"`
	Project  Project `json:"project"`
	Labels   []Label `json:"labels"`

	// Computed
	TimeSpent float64 `json:"time_spent"`
	Progress  int     `json:"progress"`
}

Task represents a task/issue in the system

type TasksListOptions

type TasksListOptions struct {
	Project  string
	Assignee string
	Status   string
	Filter   string // my, today, overdue
	Limit    int
	Page     int
}

TasksListOptions for filtering task lists

type TasksService

type TasksService interface {
	// List returns tasks matching the given options
	List(opts TasksListOptions) ([]Task, error)

	// ListToday returns tasks due today for the current user
	ListToday() ([]Task, error)

	// Get returns a task by code (e.g., "GS-123")
	Get(code string) (*Task, error)

	// Create creates a new task
	Create(input CreateTaskInput) (*Task, error)

	// Update updates an existing task
	Update(code string, input UpdateTaskInput) (*Task, error)

	// Complete marks a task as complete
	Complete(code string) error

	// Assign assigns a user to a task
	Assign(code, username string) error

	// Move moves a task to another project
	Move(code, toProject string) (*Task, error)

	// Duplicate creates a copy of a task
	Duplicate(code, toProject string, withSubtasks bool) (*Task, error)

	// ListSubtasks returns subtasks for a task
	ListSubtasks(code string) ([]Task, error)
}

TasksService handles task operations

type TeamMemberStatus

type TeamMemberStatus struct {
	User         User    `json:"user"`
	ActiveTasks  int     `json:"active_tasks"`
	DoneTasks    int     `json:"done_tasks"`
	BlockedTasks int     `json:"blocked_tasks"`
	TrackedHours float64 `json:"tracked_hours"`
	IsOnline     bool    `json:"is_online"`
}

TeamMemberStatus represents a team member's standup status

type TeamStandupSummary

type TeamStandupSummary struct {
	DoneTasks    int     `json:"done_tasks"`
	ActiveTasks  int     `json:"active_tasks"`
	BlockedTasks int     `json:"blocked_tasks"`
	TrackedHours float64 `json:"tracked_hours"`
}

TeamStandupSummary represents the standup summary stats

type TimeEntry

type TimeEntry struct {
	UUID      string    `json:"uuid"`
	Start     time.Time `json:"start"`
	End       time.Time `json:"end"`
	Duration  float64   `json:"duration"`
	Comment   string    `json:"comment"`
	Billable  bool      `json:"billable"`
	CreatedAt time.Time `json:"created_at"`
}

TimeEntry represents a time tracking entry

type TimerReport

type TimerReport struct {
	TotalHours    float64       `json:"total_hours"`
	BillableHours float64       `json:"billable_hours"`
	ByProject     []ProjectTime `json:"by_project"`
	ByDay         []DayTime     `json:"by_day"`
}

TimerReport represents aggregated time data

type TimerService

type TimerService interface {
	// Status returns the current active timer, if any
	Status() (*ActiveTimer, error)

	// Start begins a new timer for a task
	Start(taskCode, comment string) (*ActiveTimer, error)

	// Stop ends the current timer
	Stop() (*TimeEntry, error)

	// Log adds a manual time entry
	Log(taskCode string, duration time.Duration, comment string) (*TimeEntry, error)

	// Report returns time tracking report
	Report(week, team bool) (*TimerReport, error)

	// Productivity returns productivity metrics
	Productivity(period string) (*Productivity, error)
}

TimerService handles time tracking operations

type UpdateTaskInput

type UpdateTaskInput struct {
	Title       string
	Description string
	Status      string
	Assignee    string
	Priority    string
}

UpdateTaskInput for updating a task

type User

type User struct {
	UUID     string `json:"uuid"`
	Name     string `json:"name"`
	Username string `json:"username"`
	Email    string `json:"email"`
	Avatar   string `json:"avatar"`
}

User represents a user in the system

type WeeklyDigest

type WeeklyDigest struct {
	Days []DayDigest `json:"days"`
}

WeeklyDigest represents weekly standup metrics

type WikiPage

type WikiPage struct {
	UUID      string    `json:"uuid"`
	Title     string    `json:"title"`
	Slug      string    `json:"slug"`
	Content   string    `json:"content"`
	Author    User      `json:"author"`
	UpdatedAt time.Time `json:"updated_at"`
	CreatedAt time.Time `json:"created_at"`
}

WikiPage represents a wiki page

type WikiService

type WikiService interface {
	// List returns all wiki pages for a project
	List(project string) ([]WikiPage, error)

	// Get returns a wiki page by slug
	Get(project, slug string) (*WikiPage, error)

	// Create creates a new wiki page
	Create(project, title, content string) (*WikiPage, error)

	// Update updates a wiki page
	Update(project, slug, title, content string) (*WikiPage, error)
}

WikiService handles wiki operations

type Workspace

type Workspace struct {
	UUID string `json:"uuid"`
	Slug string `json:"slug"`
	Name string `json:"name"`
}

Workspace represents a workspace

type WorkspaceDetails

type WorkspaceDetails struct {
	Workspace
	ProjectsCount int    `json:"projects_count"`
	MembersCount  int    `json:"members_count"`
	Plan          string `json:"plan"`
}

WorkspaceDetails represents detailed workspace info

type WorkspaceMember

type WorkspaceMember struct {
	User
	Role     string `json:"role"` // owner, admin, member
	JoinedAt string `json:"joined_at"`
}

WorkspaceMember represents a workspace member

type WorkspacesService

type WorkspacesService interface {
	// List returns all workspaces
	List() ([]Workspace, error)

	// Get returns a workspace by slug
	Get(slug string) (*WorkspaceDetails, error)

	// ListMembers returns workspace members
	ListMembers(slug string) ([]WorkspaceMember, error)

	// ListProjects returns projects in a workspace
	ListProjects(slug string) ([]Project, error)
}

WorkspacesService handles workspace operations

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL