Documentation
¶
Overview ¶
Package server provides the dev server with HTTP serving, file watching, and WebSocket live reload.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIError ¶
type APIError struct {
Code string `json:"code"`
Message string `json:"message"`
File string `json:"file,omitempty"`
}
APIError represents a structured error in the response.
type APIResponse ¶
type APIResponse struct {
Success bool `json:"success"`
Data any `json:"data,omitempty"`
Error *APIError `json:"error,omitempty"`
}
APIResponse is the standard JSON envelope.
type APIServer ¶
type APIServer struct {
// contains filtered or unexported fields
}
APIServer serves the IPC JSON API for the desktop app.
func NewAPIServer ¶
func NewAPIServer(pm *project.ProjectManager, hub *project.EventHub) *APIServer
NewAPIServer creates a new API server.
func (*APIServer) Start ¶
Start begins listening on the given port. If port is 0, an ephemeral port is assigned. Returns the actual port being served on.
type ChangeKind ¶
type ChangeKind string
ChangeKind classifies a file system change.
const ( ChangeContent ChangeKind = "content" ChangeTemplate ChangeKind = "template" ChangeCSS ChangeKind = "css" ChangeConfig ChangeKind = "config" ChangeStatic ChangeKind = "static" ChangePlugin ChangeKind = "plugin" )
type DevServer ¶
type DevServer struct {
// contains filtered or unexported fields
}
DevServer runs the development HTTP server with live reload.
func (*DevServer) Ready ¶
Ready reports the actual bound port: the port is sent once after the listener binds, then the channel is closed. If Start fails or the server is stopped before binding, the channel is closed without a value.
func (*DevServer) Start ¶
Start binds the listener, runs the initial build, starts the file watcher, and serves HTTP. It blocks until the server is stopped. The listener is bound up front so Ready() reports the actual port immediately; connections arriving before the initial build finishes queue in the accept backlog.
type FileChange ¶
type FileChange struct {
Path string
Paths []string // all changed file paths in the batch (populated for content changes)
Kind ChangeKind
DetectedAt time.Time // when fsnotify first reported this change
}
FileChange represents a detected filesystem change.
type Hub ¶
type Hub struct {
// contains filtered or unexported fields
}
Hub manages WebSocket client connections and broadcasts reload messages.
func (*Hub) Broadcast ¶
func (h *Hub) Broadcast(msg ReloadMessage) int
Broadcast sends a reload message to all connected WebSocket clients. Returns the number of clients that received the message.
func (*Hub) BumpBuildID ¶ added in v1.0.0
BumpBuildID records a new successful build and returns its ID. IDs are millisecond timestamps forced monotonic, so two builds completing within the same millisecond (or a clock step backwards) cannot collide.
func (*Hub) ClearPendingError ¶
func (h *Hub) ClearPendingError()
ClearPendingError removes the stored build error after a successful rebuild.
func (*Hub) ClientCount ¶
ClientCount returns the number of connected WebSocket clients.
func (*Hub) HandleWS ¶
func (h *Hub) HandleWS(w http.ResponseWriter, r *http.Request)
HandleWS upgrades an HTTP connection to WebSocket and registers the client.
func (*Hub) SetPendingError ¶
func (h *Hub) SetPendingError(msg *ReloadMessage)
SetPendingError stores a build error to replay to newly connecting clients.
type Options ¶
type Options struct {
ProjectDir string
OutputDir string
Host string
Port int
LiveReload bool
Version string
BasePath string // normalized: "/docs/" or "/"
BuilderFactory func() *build.SiteBuilder
ThemeDevDirs []string // external dirs to watch as ChangeTemplate (for --theme-dev)
Verbose bool // print per-phase rebuild timings and plugin log messages
}
Options configures the dev server.
type RebuildResult ¶
type RebuildResult struct {
Success bool
Duration time.Duration
PageCount int
Warnings []engine.ValidationWarning
PhaseTimings []engine.PhaseTiming
LogMessages []engine.BuildLogEntry
Error error
}
RebuildResult holds the outcome of a rebuild attempt.
type Rebuilder ¶
type Rebuilder struct {
// contains filtered or unexported fields
}
Rebuilder wraps SiteBuilder for dev-mode rebuilds. It persists the builder across content/public changes and only creates a new one when config or templates change.
Coalescing: if a rebuild is already running, incoming requests are merged into a single pending change via mergeChanges (kinds escalate, content paths union), so no change is lost while at most one follow-up rebuild runs. This prevents cascading queued rebuilds when editors emit rapid successive save events.
func NewRebuilder ¶
func NewRebuilder(factory func() *build.SiteBuilder, projectDir string) *Rebuilder
NewRebuilder creates a Rebuilder with the given factory function. The factory is called on the first build and whenever config/template changes require a fresh SiteBuilder.
func (*Rebuilder) Rebuild ¶
func (r *Rebuilder) Rebuild(change FileChange) (FileChange, *RebuildResult)
Rebuild runs a site build and returns the executed change with its result. Config or template changes create a fresh builder (full re-init). Content or public changes reuse the existing builder (template engine skips Load).
If a rebuild is already in progress, the change is merged into the pending slot and this call returns a nil result (the caller should skip logging/broadcasting). When the active rebuild finishes, it picks up the pending change automatically and runs it before returning; the returned change is the one the final result actually belongs to.
type ReloadMessage ¶
type ReloadMessage struct {
Type ReloadType `json:"type"`
Path string `json:"path,omitempty"`
Error string `json:"error,omitempty"`
File string `json:"file,omitempty"`
Line int `json:"line,omitempty"`
Col int `json:"col,omitempty"`
Frame string `json:"frame,omitempty"`
ChangedAt int64 `json:"changedAt,omitempty"` // Unix millis when the file change was first detected
BuildID int64 `json:"buildId,omitempty"` // monotonic ID of the successful build this message refers to
Warnings []WarningItem `json:"warnings,omitempty"`
}
ReloadMessage is sent to browsers over WebSocket.
func ToReloadMessage ¶
func ToReloadMessage(change FileChange, result *RebuildResult, projectDir string) ReloadMessage
ToReloadMessage converts a file change and rebuild result into a ReloadMessage suitable for broadcasting to connected browsers.
type ReloadType ¶
type ReloadType string
ReloadType classifies what kind of reload to perform.
const ( ReloadFull ReloadType = "reload" ReloadCSS ReloadType = "css" ReloadError ReloadType = "error" ReloadWarning ReloadType = "warning" // ReloadSync announces the server's latest successful build ID to a client // that just connected. The client compares it against the build ID embedded // in its page and reloads only if the page predates the build, so stale // tabs (reconnects, server restarts, missed broadcasts) catch up exactly // once and fresh tabs never reload spuriously. ReloadSync ReloadType = "sync" )
type WarningItem ¶ added in v1.0.0
type WarningItem struct {
File string `json:"file"`
Line int `json:"line"`
Message string `json:"message"`
}
WarningItem is a single structured warning for the browser overlay.
type Watcher ¶
type Watcher struct {
// contains filtered or unexported fields
}
Watcher monitors project directories for changes and triggers a callback.
func NewWatcher ¶
func NewWatcher(projectDir, outputDir string, debounce time.Duration, onChange func([]FileChange)) *Watcher
NewWatcher creates a file watcher for the given project directory. outputDir is the build output directory (absolute or relative); changes under it are ignored so a build's own writes don't trigger a rebuild loop.
func (*Watcher) AddExternalDir ¶
func (w *Watcher) AddExternalDir(dir string, kind ChangeKind)
AddExternalDir registers a directory outside the project tree to watch. All changes under it are classified with the given kind. Must be called before Start().