Documentation
¶
Index ¶
- Constants
- Variables
- func FormatSize(bytes int64) string
- func HashContent(data []byte) string
- func ResolveAPIURL(cfg Config) string
- func ResolveAuth() (string, error)
- func TotalSize(files []FileEntry) int64
- type APIClient
- func (c *APIClient) CreateAPIToken(name string, expiresIn *int64) (APITokenResponse, error)
- func (c *APIClient) CreateProject(ctx context.Context, name, distVersion, projectKey string) (CreateProjectResponse, error)
- func (c *APIClient) DeleteAPIToken(tokenID string) error
- func (c *APIClient) GetSession(ctx context.Context, projectID, distributionVersion string) (SessionResponse, error)
- func (c *APIClient) ListAPITokens() ([]APITokenListItem, error)
- func (c *APIClient) PollToken(deviceCode string) (TokenResponse, error)
- func (c *APIClient) RefreshToken(jwt string) (TokenResponse, error)
- func (c *APIClient) RequestDeviceCode() (DeviceCodeResponse, error)
- func (c *APIClient) SetHTTPClient(hc *http.Client)
- func (c *APIClient) Whoami() (WhoamiResponse, error)
- type APIError
- type APITokenListItem
- type APITokenResponse
- type BuildCmd
- type BuildDoneEvent
- type Config
- type CreateProjectResponse
- type DeviceCodeResponse
- type Document
- type FileEntry
- type FileWatcher
- type InitCmd
- type InstanceClient
- func (c *InstanceClient) Build(ctx context.Context, projectID, main, directory, distVersion, compiler string, ...) (BuildDoneEvent, error)
- func (c *InstanceClient) BuildWithArgs(ctx context.Context, projectID, main, directory, distVersion, compiler string, ...) (BuildDoneEvent, error)
- func (c *InstanceClient) DownloadPDF(ctx context.Context, projectID, buildID, outputPath string) error
- func (c *InstanceClient) SetHTTPClient(hc *http.Client)
- func (c *InstanceClient) Sync(ctx context.Context, projectID string, files []FileEntry) (SyncResult, error)
- func (c *InstanceClient) Upload(ctx context.Context, projectID, projectDir string, filePaths []string, ...) error
- func (c *InstanceClient) UploadRaw(ctx context.Context, projectID string, tarData []byte) error
- type LoginCmd
- type Options
- type ProgressBar
- type SessionResponse
- type Spinner
- type StatusCmd
- type SyncResult
- type TokenCmd
- type TokenCreateCmd
- type TokenDeleteCmd
- type TokenErrorResponse
- type TokenListCmd
- type TokenResponse
- type UI
- func (ui *UI) Confirm(msg string) (bool, error)
- func (ui *UI) DimInfo(msg string)
- func (ui *UI) Errorf(format string, args ...any)
- func (ui *UI) IsInteractive() bool
- func (ui *UI) IsTTY() bool
- func (ui *UI) Log(line string)
- func (ui *UI) Out() io.Writer
- func (ui *UI) Progress(label string, total int64) *ProgressBar
- func (ui *UI) Select(label string, options []string) (int, error)
- func (ui *UI) SelectDocuments(docs []Document) ([]Document, error)
- func (ui *UI) SelectOne(label string, options []string) (int, error)
- func (ui *UI) Spin(msg string) *Spinner
- func (ui *UI) Status(msg string)
- func (ui *UI) Success(msg string)
- func (ui *UI) TextInput(label string) (string, error)
- type WhoamiResponse
Constants ¶
const (
DefaultAPIURL = "https://api.texops.dev"
)
Variables ¶
var ( ErrAuthorizationPending = fmt.Errorf("authorization pending") ErrDeviceCodeExpired = fmt.Errorf("device code expired") ErrTokenConflict = fmt.Errorf("token name already exists") ErrTokenNotFound = fmt.Errorf("token not found") )
var AllowedCompilers = []string{"pdflatex", "xelatex", "lualatex", "latex", "platex", "uplatex"}
AllowedCompilers lists valid compiler values for .texops.yaml.
var CredentialsFilePath = credentialsFilePath
var KeyringGet = keyring.Get
var KeyringSet = keyring.Set
var NewInstanceClientFn = func(instanceURL, jwt string) *InstanceClient { return NewInstanceClient(instanceURL, jwt) }
var OpenBrowser = openBrowser
var PollInterval = 5 * time.Second
PollInterval controls how often PollToken is called. Exposed for testing.
var RunBuild = runBuild
var TexliveVersions = []string{"2025", "2024", "2023", "2022", "2021", "2020", "2019", "2018", "2017", "2016", "2015", "2014", "2013", "2012"}
TexliveVersions lists available TexLive distribution versions (newest first).
Functions ¶
func FormatSize ¶
func HashContent ¶
func ResolveAPIURL ¶
func ResolveAuth ¶
ResolveAuth returns a Bearer token for API authentication. It checks in order: TX_API_TOKEN env var, JWT from credentials file, JWT from keyring. Each source can override the ones below it. If a JWT is found but expired, it falls through to the next source.
Types ¶
type APIClient ¶
type APIClient struct {
// contains filtered or unexported fields
}
func NewAPIClient ¶
func (*APIClient) CreateAPIToken ¶
func (c *APIClient) CreateAPIToken(name string, expiresIn *int64) (APITokenResponse, error)
func (*APIClient) CreateProject ¶
func (*APIClient) DeleteAPIToken ¶
func (*APIClient) GetSession ¶
func (*APIClient) ListAPITokens ¶
func (c *APIClient) ListAPITokens() ([]APITokenListItem, error)
func (*APIClient) PollToken ¶
func (c *APIClient) PollToken(deviceCode string) (TokenResponse, error)
func (*APIClient) RefreshToken ¶
func (c *APIClient) RefreshToken(jwt string) (TokenResponse, error)
func (*APIClient) RequestDeviceCode ¶
func (c *APIClient) RequestDeviceCode() (DeviceCodeResponse, error)
func (*APIClient) SetHTTPClient ¶
func (*APIClient) Whoami ¶
func (c *APIClient) Whoami() (WhoamiResponse, error)
type APITokenListItem ¶
type APITokenListItem struct {
ID string `json:"id"`
Name string `json:"name"`
Prefix string `json:"prefix"`
ExpiresAt *string `json:"expires_at,omitempty"`
LastUsedAt *string `json:"last_used_at,omitempty"`
CreatedAt string `json:"created_at"`
}
APITokenListItem represents a token in a list response.
type APITokenResponse ¶
type APITokenResponse struct {
Token string `json:"token"`
ID string `json:"id"`
Name string `json:"name"`
Prefix string `json:"prefix"`
ExpiresAt *string `json:"expires_at,omitempty"`
CreatedAt string `json:"created_at"`
}
APITokenResponse is the response from creating an API token.
type BuildCmd ¶
type BuildDoneEvent ¶
type BuildDoneEvent struct {
Status string `json:"status"`
PdfURL string `json:"pdfUrl,omitempty"`
Message string `json:"message,omitempty"`
BuildID string `json:"build_id,omitempty"`
}
func ParseSSEStream ¶
func ParseSSEStream(reader io.Reader, onLog func(string)) (BuildDoneEvent, error)
type Config ¶
type Config struct {
ProjectKey string `yaml:"project_key,omitempty"`
Texlive string `yaml:"texlive"`
Compiler string `yaml:"compiler,omitempty"`
APIURL string `yaml:"api_url,omitempty"`
Documents []Document `yaml:"documents"`
}
func LoadConfig ¶
func ParseConfig ¶
type CreateProjectResponse ¶
type DeviceCodeResponse ¶
type Document ¶
type Document struct {
Name string `yaml:"name"`
Main string `yaml:"main"`
Directory string `yaml:"directory,omitempty"`
Output string `yaml:"output,omitempty"`
Texlive string `yaml:"texlive,omitempty"`
Compiler string `yaml:"compiler,omitempty"`
}
func DiscoverDocuments ¶
DiscoverDocuments recursively finds .tex files containing \documentclass in dir, respecting .gitignore and .txignore patterns. Returns a Document for each discovered file with name derived from the path stem.
type FileWatcher ¶ added in v0.4.3
type FileWatcher struct {
Events chan string
Errors chan error
// contains filtered or unexported fields
}
func NewFileWatcher ¶ added in v0.4.3
func NewFileWatcher(dir string, excludes []string) (*FileWatcher, error)
func (*FileWatcher) Close ¶ added in v0.4.3
func (w *FileWatcher) Close() error
func (*FileWatcher) Run ¶ added in v0.4.3
func (w *FileWatcher) Run(ctx context.Context)
type InitCmd ¶
type InitCmd struct {
Texlive string `long:"texlive" description:"TexLive distribution version"`
Compiler string `long:"compiler" description:"LaTeX compiler (pdflatex, xelatex, lualatex, latex, platex, uplatex)"`
Main string `long:"main" default:"main.tex" description:"Main TeX file (fallback when no .tex files discovered)"`
UI *UI `no-flag:"true"`
}
type InstanceClient ¶
type InstanceClient struct {
// contains filtered or unexported fields
}
func NewInstanceClient ¶
func NewInstanceClient(instanceURL, jwt string) *InstanceClient
func (*InstanceClient) Build ¶
func (c *InstanceClient) Build(ctx context.Context, projectID, main, directory, distVersion, compiler string, buildOptions map[string]string, onLog func(string)) (BuildDoneEvent, error)
func (*InstanceClient) BuildWithArgs ¶
func (c *InstanceClient) BuildWithArgs(ctx context.Context, projectID, main, directory, distVersion, compiler string, args []string, buildOptions map[string]string, onLog func(string)) (BuildDoneEvent, error)
func (*InstanceClient) DownloadPDF ¶
func (c *InstanceClient) DownloadPDF(ctx context.Context, projectID, buildID, outputPath string) error
func (*InstanceClient) SetHTTPClient ¶
func (c *InstanceClient) SetHTTPClient(hc *http.Client)
func (*InstanceClient) Sync ¶
func (c *InstanceClient) Sync(ctx context.Context, projectID string, files []FileEntry) (SyncResult, error)
type Options ¶
type Options struct {
Login LoginCmd `command:"login" description:"Log in to TexOps"`
Init InitCmd `command:"init" description:"Initialize a new TexOps project"`
Build BuildCmd `command:"build" description:"Build the LaTeX project"`
Status StatusCmd `command:"status" description:"Show authentication status"`
Token TokenCmd `command:"token" description:"Manage API tokens"`
}
type ProgressBar ¶
type ProgressBar struct {
// contains filtered or unexported fields
}
ProgressBar represents an in-progress upload with byte-level tracking.
func (*ProgressBar) Abort ¶
func (pb *ProgressBar) Abort()
Abort stops the progress bar without a success message. Use this when the operation has failed.
func (*ProgressBar) Done ¶
func (pb *ProgressBar) Done()
Done stops the progress bar and prints a completion line.
func (*ProgressBar) Reader ¶
func (pb *ProgressBar) Reader(r io.Reader) io.Reader
Reader wraps an io.Reader to feed progress updates to the progress bar.
func (*ProgressBar) Update ¶
func (pb *ProgressBar) Update(fraction float64)
Update sends a progress fraction (0.0-1.0) to the progress bar.
type SessionResponse ¶
type Spinner ¶
type Spinner struct {
// contains filtered or unexported fields
}
Spinner represents an in-progress async operation with animated feedback.
func (*Spinner) Cancel ¶ added in v0.4.3
func (s *Spinner) Cancel()
Cancel stops the spinner without printing anything.
type SyncResult ¶
type SyncResult struct {
Missing []string `json:"missing"`
}
type TokenCmd ¶
type TokenCmd struct {
Create TokenCreateCmd `command:"create" description:"Create a new API token"`
List TokenListCmd `command:"list" description:"List API tokens"`
Delete TokenDeleteCmd `command:"delete" description:"Delete an API token"`
}
type TokenCreateCmd ¶
type TokenCreateCmd struct {
Name string `long:"name" description:"Name for the token"`
ExpiresIn string `long:"expires-in" description:"Token expiry duration (e.g. 30d, 90d, 1y)"`
NoExpiry bool `long:"no-expiry" description:"Create token with no expiry"`
UI *UI `no-flag:"true"`
}
func (*TokenCreateCmd) Execute ¶
func (cmd *TokenCreateCmd) Execute(args []string) error
type TokenDeleteCmd ¶
type TokenDeleteCmd struct {
UI *UI `no-flag:"true"`
}
func (*TokenDeleteCmd) Execute ¶
func (cmd *TokenDeleteCmd) Execute(args []string) error
type TokenErrorResponse ¶
type TokenErrorResponse struct {
Error string `json:"error"`
}
type TokenListCmd ¶
type TokenListCmd struct {
UI *UI `no-flag:"true"`
}
func (*TokenListCmd) Execute ¶
func (cmd *TokenListCmd) Execute(args []string) error
type TokenResponse ¶
type UI ¶
type UI struct {
// contains filtered or unexported fields
}
func NewUIWithOptions ¶
NewUIWithOptions creates a UI with explicit TTY mode and input reader. Used in tests to simulate TTY/non-TTY behavior. Error output goes to out for easy test capture.
func NewUIWithTTYOptions ¶ added in v0.4.0
NewUIWithTTYOptions creates a UI with separate output-TTY and stdin-TTY flags. Use this when testing code that distinguishes IsTTY() from IsInteractive().
func (*UI) IsInteractive ¶ added in v0.4.0
func (*UI) Progress ¶
func (ui *UI) Progress(label string, total int64) *ProgressBar
Progress starts an animated progress bar with the given label and total bytes. In non-TTY mode, it prints periodic percentage milestones. Call Reader() to wrap an io.Reader for tracking, then Done() when finished.
func (*UI) Select ¶
Select displays an interactive selection list. In TTY mode, uses a simple numbered list with keyboard input. In non-TTY mode, returns an error.
func (*UI) SelectDocuments ¶
SelectDocuments shows an interactive checkbox list for selecting documents. All documents are pre-selected. Returns the selected documents. In non-TTY mode, returns all documents without interaction.
func (*UI) SelectOne ¶
SelectOne displays an interactive single-select list using Bubble Tea. Returns the index of the selected option, or an error if cancelled or non-TTY.