Documentation
¶
Overview ¶
Package completion provides tab completion support for the basecamp CLI. It implements a file-based cache for projects, people, and accounts data that enables fast, offline-capable shell completions without requiring API calls.
Index ¶
- Constants
- func DefaultCacheDirFunc(cmd *cobra.Command) string
- type Cache
- type CacheDirFunc
- type CachedAccount
- type CachedPerson
- type CachedProfile
- type CachedProject
- type Completer
- func (c *Completer) AccountCompletion() cobra.CompletionFunc
- func (c *Completer) PeopleCompletion() cobra.CompletionFunc
- func (c *Completer) PeopleNameCompletion() cobra.CompletionFunc
- func (c *Completer) ProfileCompletion() cobra.CompletionFunc
- func (c *Completer) ProjectCompletion() cobra.CompletionFunc
- func (c *Completer) ProjectNameCompletion() cobra.CompletionFunc
- type RefreshResult
- type Refresher
- type Store
- func (s *Store) Accounts() []CachedAccount
- func (s *Store) Clear() error
- func (s *Store) Dir() string
- func (s *Store) IsStale(maxAge time.Duration) bool
- func (s *Store) Load() (*Cache, error)
- func (s *Store) Path() string
- func (s *Store) People() []CachedPerson
- func (s *Store) Profiles() []CachedProfile
- func (s *Store) Projects() []CachedProject
- func (s *Store) Save(cache *Cache) error
- func (s *Store) UpdateAccounts(accounts []CachedAccount) error
- func (s *Store) UpdatePeople(people []CachedPerson) error
- func (s *Store) UpdateProjects(projects []CachedProject) error
Constants ¶
const ( // CacheVersion is the current cache schema version. CacheVersion = 1 // DefaultMaxAge is the default cache staleness threshold (1 hour). DefaultMaxAge = time.Hour // CacheFileName is the default cache file name. CacheFileName = "completion.json" )
Variables ¶
This section is empty.
Functions ¶
func DefaultCacheDirFunc ¶
DefaultCacheDirFunc returns the cache directory by checking (in order): 1. --cache-dir flag on the root command 2. App config from context (set by PersistentPreRunE) 3. BASECAMP_CACHE_DIR environment variable 4. Default cache directory
This is the standard CacheDirFunc that all commands should use.
Limitation: During __complete, PersistentPreRunE doesn't run, so appctx is not set and config files are not loaded. This means cache_dir set in config files is NOT honored during completion—only --cache-dir flag and env vars work. This is intentional: loading config files adds latency that defeats fast completions. Users who set cache_dir in config should also set BASECAMP_CACHE_DIR.
Types ¶
type Cache ¶
type Cache struct {
Projects []CachedProject `json:"projects,omitempty"`
People []CachedPerson `json:"people,omitempty"`
Accounts []CachedAccount `json:"accounts,omitempty"`
ProjectsUpdatedAt time.Time `json:"projects_updated_at"`
PeopleUpdatedAt time.Time `json:"people_updated_at"`
AccountsUpdatedAt time.Time `json:"accounts_updated_at"`
UpdatedAt time.Time `json:"updated_at"` // Legacy, kept for backwards compat
Version int `json:"version"` // Schema version for future migrations
}
Cache stores completion data with metadata for staleness detection.
type CacheDirFunc ¶
CacheDirFunc returns the cache directory to use for completion. Takes the command to allow checking both context and flags at completion time.
type CachedAccount ¶
CachedAccount holds account data for tab completion.
type CachedPerson ¶
type CachedPerson struct {
ID int64 `json:"id"`
Name string `json:"name"`
EmailAddress string `json:"email_address,omitempty"`
}
CachedPerson holds person data for tab completion.
type CachedProfile ¶
CachedProfile holds profile data for tab completion. Unlike other cached items, profiles come from config files, not API calls.
type CachedProject ¶
type CachedProject struct {
ID int64 `json:"id"`
Name string `json:"name"`
Purpose string `json:"purpose,omitempty"` // "hq", "team", or empty
Bookmarked bool `json:"bookmarked,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
CachedProject holds project data for tab completion. Fields are chosen to support ranking (HQ, Bookmarked, Recent) and display.
type Completer ¶
type Completer struct {
// contains filtered or unexported fields
}
Completer provides tab completion functions for the basecamp CLI. It reads from a file-based cache and does NOT initialize the full App or SDK.
func NewCompleter ¶
func NewCompleter(getCacheDir CacheDirFunc) *Completer
NewCompleter creates a new Completer. The getCacheDir function is called at completion time to determine the cache directory. If nil, DefaultCacheDirFunc is used.
func (*Completer) AccountCompletion ¶
func (c *Completer) AccountCompletion() cobra.CompletionFunc
AccountCompletion returns a Cobra completion function for account arguments. Accounts are sorted alphabetically by name. The --account flag takes an ID.
func (*Completer) PeopleCompletion ¶
func (c *Completer) PeopleCompletion() cobra.CompletionFunc
PeopleCompletion returns a Cobra completion function for person arguments. People are sorted alphabetically by name, with "me" always first if it matches the filter.
func (*Completer) PeopleNameCompletion ¶
func (c *Completer) PeopleNameCompletion() cobra.CompletionFunc
PeopleNameCompletion returns a Cobra completion function for person name arguments. People are sorted alphabetically by name, with "me" always first if it matches the filter.
func (*Completer) ProfileCompletion ¶
func (c *Completer) ProfileCompletion() cobra.CompletionFunc
ProfileCompletion returns a Cobra completion function for profile arguments. Profiles come from the config file's profiles map. Since completion runs before PersistentPreRunE, we need to load the config directly here.
func (*Completer) ProjectCompletion ¶
func (c *Completer) ProjectCompletion() cobra.CompletionFunc
ProjectCompletion returns a Cobra completion function for project arguments. Projects are ranked: HQ > Bookmarked > Recent > Alphabetical.
func (*Completer) ProjectNameCompletion ¶
func (c *Completer) ProjectNameCompletion() cobra.CompletionFunc
ProjectNameCompletion returns a Cobra completion function for project name arguments. Unlike ProjectCompletion, this returns names instead of IDs for commands that accept names.
type RefreshResult ¶
RefreshResult contains the outcome of a refresh operation.
func (RefreshResult) Error ¶
func (r RefreshResult) Error() error
Error returns a combined error message if any operation failed.
func (RefreshResult) HasError ¶
func (r RefreshResult) HasError() bool
HasError returns true if any refresh operation failed.
type Refresher ¶
type Refresher struct {
// contains filtered or unexported fields
}
Refresher handles background cache refresh operations.
func NewRefresher ¶
func NewRefresher(store *Store, sdk *basecamp.AccountClient) *Refresher
NewRefresher creates a new cache refresher.
func (*Refresher) IsRefreshing ¶
IsRefreshing returns true if a background refresh is in progress.
func (*Refresher) RefreshAll ¶
func (r *Refresher) RefreshAll(ctx context.Context) RefreshResult
RefreshAll fetches fresh data from the API and updates the cache. This is a synchronous operation - use RefreshIfStale for async. On partial failure, preserves existing cached data for the failed portion. Returns RefreshResult with counts and any errors encountered.
func (*Refresher) RefreshIfStale ¶
RefreshIfStale triggers a background refresh if the cache is stale. Returns immediately - the refresh happens asynchronously. If a refresh is already in progress, this is a no-op.
func (*Refresher) RefreshPeople ¶
RefreshPeople fetches fresh people data and updates the cache.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store handles reading and writing the completion cache.
func NewStore ¶
NewStore creates a new cache store. If dir is empty, it uses the default location (~/.cache/basecamp/).
func (*Store) Accounts ¶
func (s *Store) Accounts() []CachedAccount
Accounts returns cached accounts, or nil if cache is empty/missing.
func (*Store) IsStale ¶
IsStale returns true if the cache is older than maxAge or incomplete. A cache is considered stale if: - It doesn't exist or can't be loaded - Either per-section timestamp is missing (legacy cache or incomplete) - The oldest section timestamp exceeds maxAge
func (*Store) Load ¶
Load reads the cache from disk. Returns an empty cache if the file doesn't exist or is invalid.
func (*Store) People ¶
func (s *Store) People() []CachedPerson
People returns cached people, or nil if cache is empty/missing.
func (*Store) Profiles ¶
func (s *Store) Profiles() []CachedProfile
Profiles returns configured profiles for tab completion. Since profiles are defined in config files (not API-fetched), this loads the config directly rather than from the completion cache.
func (*Store) Projects ¶
func (s *Store) Projects() []CachedProject
Projects returns cached projects, or nil if cache is empty/missing.
func (*Store) Save ¶
Save writes the cache to disk atomically. Sets ProjectsUpdatedAt, PeopleUpdatedAt, and UpdatedAt to now. AccountsUpdatedAt is NOT set here; use UpdateAccounts for that. Note: Works on a copy to avoid mutating the caller's cache instance.
func (*Store) UpdateAccounts ¶
func (s *Store) UpdateAccounts(accounts []CachedAccount) error
UpdateAccounts updates just the accounts in the cache. Only updates AccountsUpdatedAt, preserving other timestamps. Note: Accounts are user-level (not account-scoped like projects/people), so they're refreshed separately via `basecamp me`.
func (*Store) UpdatePeople ¶
func (s *Store) UpdatePeople(people []CachedPerson) error
UpdatePeople updates just the people in the cache. Only updates PeopleUpdatedAt, preserving ProjectsUpdatedAt.
func (*Store) UpdateProjects ¶
func (s *Store) UpdateProjects(projects []CachedProject) error
UpdateProjects updates just the projects in the cache. Only updates ProjectsUpdatedAt, preserving PeopleUpdatedAt.