devserver

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Mar 16, 2026 License: AGPL-3.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

View Source
const (
	PortRangeStart = 15173
	PortRangeEnd   = 15273
)
View Source
const (
	// EventDevServerStatus is emitted whenever any field in DevServerState changes.
	// Payload: DevServerState
	EventDevServerStatus = "plugin/devserver/status"

	// EventDevServerLog is emitted for batched log lines from Vite or Go build.
	// Payload: []LogEntry (each entry contains pluginID)
	EventDevServerLog = "plugin/devserver/log"

	// EventDevServerError is emitted for structured build errors.
	// Payload: (pluginID string, errors []BuildError)
	EventDevServerError = "plugin/devserver/error"
)
View Source
const (
	// DedupInterval is the debounce window for file change events.
	DedupInterval = 500 * time.Millisecond
)
View Source
const DefaultLogBufferSize = 5000

Variables

This section is empty.

Functions

This section is empty.

Types

type BuildError

type BuildError struct {
	File    string `json:"file"`
	Line    int    `json:"line"`
	Column  int    `json:"column"`
	Message string `json:"message"`
}

BuildError is a structured build error parsed from Go compiler output.

type BuildOpts

type BuildOpts struct {
	GoPath   string
	PnpmPath string
	NodePath string
}

BuildOpts holds resolved paths to build tools.

type DevInfoFile

type DevInfoFile struct {
	PID             int    `json:"pid"`
	Protocol        string `json:"protocol"`
	ProtocolVersion int    `json:"protocolVersion"`
	Addr            string `json:"addr"`
	VitePort        int    `json:"vitePort,omitempty"`
	PluginID        string `json:"pluginId,omitempty"`
	Version         string `json:"version,omitempty"`
	StartedAt       string `json:"startedAt,omitempty"`
}

DevInfoFile is the JSON structure of the .devinfo file written by externally-run plugins.

type DevProcessStatus

type DevProcessStatus string

DevProcessStatus describes the current status of either the Vite process or the Go watcher.

const (
	DevProcessStatusIdle     DevProcessStatus = "idle"
	DevProcessStatusStarting DevProcessStatus = "starting"
	DevProcessStatusBuilding DevProcessStatus = "building"
	DevProcessStatusRunning  DevProcessStatus = "running"
	DevProcessStatusReady    DevProcessStatus = "ready"
	DevProcessStatusError    DevProcessStatus = "error"
	DevProcessStatusStopped  DevProcessStatus = "stopped"
)

type DevServerInstance

type DevServerInstance struct {
	// contains filtered or unexported fields
}

DevServerInstance manages the dev server lifecycle for a single plugin. It coordinates the Vite process and Go file watcher.

func NewDevServerInstance

func NewDevServerInstance(
	parentCtx context.Context,
	logger logging.Logger,
	pluginID string,
	devPath string,
	vitePort int,
	buildOpts BuildOpts,
	reloader PluginReloader,
	onStatus emitStatusFunc,
	onLogs emitLogsFunc,
	onErrors emitErrorsFunc,
) *DevServerInstance

NewDevServerInstance creates a new instance. Call Start() to begin.

func (*DevServerInstance) GetLogs

func (inst *DevServerInstance) GetLogs(count int) []LogEntry

GetLogs returns log entries from the ring buffer.

func (*DevServerInstance) Start

func (inst *DevServerInstance) Start() error

Start spawns the Vite dev server and Go watcher in background goroutines.

func (*DevServerInstance) State

func (inst *DevServerInstance) State() DevServerState

State returns a snapshot of the current state, safe for JSON serialization.

func (*DevServerInstance) Stop

func (inst *DevServerInstance) Stop()

Stop gracefully stops both the Vite process and Go watcher. Sub-processes are stopped BEFORE the context is cancelled so that their Stop methods can still look up and signal the process group.

func (*DevServerInstance) TriggerRebuild added in v0.2.0

func (inst *DevServerInstance) TriggerRebuild()

TriggerRebuild triggers an explicit Go rebuild + transfer + reload cycle.

func (*DevServerInstance) VitePGID

func (inst *DevServerInstance) VitePGID() int

VitePGID returns the process group ID of the Vite child process, or 0.

type DevServerManager

type DevServerManager struct {
	// contains filtered or unexported fields
}

DevServerManager manages dev server instances for plugins in development mode. It is exposed as a Wails binding. All public methods are callable from the frontend.

func NewDevServerManager

func NewDevServerManager(
	logger logging.Logger,
	pluginRef PluginRef,
	pluginReloader PluginReloader,
	settingsProvider pkgsettings.Provider,
) *DevServerManager

NewDevServerManager creates a new DevServerManager. Call Initialize() with the Wails context before using any other methods.

func (*DevServerManager) GetDevServerLogs

func (m *DevServerManager) GetDevServerLogs(pluginID string, count int) []LogEntry

GetDevServerLogs returns the most recent log entries for a plugin's dev server.

func (*DevServerManager) GetDevServerState

func (m *DevServerManager) GetDevServerState(pluginID string) DevServerState

GetDevServerState returns the current state of the dev server for a single plugin.

func (*DevServerManager) GetExternalPluginInfo

func (m *DevServerManager) GetExternalPluginInfo(pluginID string) *DevInfoFile

GetExternalPluginInfo returns the DevInfo for an externally-managed plugin, or nil.

func (*DevServerManager) Initialize

func (m *DevServerManager) Initialize(ctx context.Context)

Initialize is called during Wails startup (OnStartup callback). It stores the Wails context needed for runtime.EventsEmit, and starts the external plugin watcher.

func (*DevServerManager) IsManaged

func (m *DevServerManager) IsManaged(pluginID string) bool

IsManaged returns true if the plugin's dev server is currently managed by this manager, either via IDE-managed mode or external mode.

func (*DevServerManager) ListDevServerStates

func (m *DevServerManager) ListDevServerStates() []DevServerState

ListDevServerStates returns the state of all running dev server instances, including externally-managed plugins.

func (*DevServerManager) RebuildPlugin added in v0.2.0

func (m *DevServerManager) RebuildPlugin(pluginID string) error

RebuildPlugin triggers a Go rebuild, transfers the binary, and reloads the plugin without restarting the Vite dev server.

func (*DevServerManager) RestartDevServer

func (m *DevServerManager) RestartDevServer(pluginID string) (DevServerState, error)

RestartDevServer stops and then starts the dev server for the given plugin.

func (*DevServerManager) Shutdown

func (m *DevServerManager) Shutdown()

Shutdown stops all running dev server instances and the external watcher. Called from Wails OnShutdown.

func (*DevServerManager) StartDevServer

func (m *DevServerManager) StartDevServer(pluginID string) (DevServerState, error)

StartDevServer starts a managed dev server for the given plugin. This spawns a Vite dev server process and a Go file watcher. The plugin must already be loaded in dev mode (DevMode=true, DevPath set).

Returns the initial DevServerState.

func (*DevServerManager) StartDevServerForPath

func (m *DevServerManager) StartDevServerForPath(pluginID, devPath string) (DevServerState, error)

StartDevServerForPath starts a managed dev server for a plugin using the provided devPath directly, without requiring the plugin to be loaded first. This is used during InstallInDevMode and Initialize where the plugin hasn't been loaded yet but we need the dev server (and its initial Go build) to run before LoadPlugin.

func (*DevServerManager) StopDevServer

func (m *DevServerManager) StopDevServer(pluginID string) error

StopDevServer stops the managed dev server for the given plugin.

type DevServerMode

type DevServerMode string

DevServerMode describes how the dev server for a plugin is managed.

const (
	// DevServerModeIdle means no dev server is running for this plugin.
	DevServerModeIdle DevServerMode = "idle"

	// DevServerModeManaged means the IDE spawned and manages the Vite + Go watcher processes.
	DevServerModeManaged DevServerMode = "managed"

	// DevServerModeExternal means the developer runs processes externally;
	// the IDE connects via .devinfo file.
	DevServerModeExternal DevServerMode = "external"
)

type DevServerState

type DevServerState struct {
	PluginID          string           `json:"pluginID"`
	Mode              DevServerMode    `json:"mode"`
	DevPath           string           `json:"devPath"`
	VitePort          int              `json:"vitePort"`
	ViteURL           string           `json:"viteURL"`
	ViteStatus        DevProcessStatus `json:"viteStatus"`
	GoStatus          DevProcessStatus `json:"goStatus"`
	LastBuildDuration time.Duration    `json:"lastBuildDuration"`
	LastBuildTime     string           `json:"lastBuildTime"`
	LastError         string           `json:"lastError"`
	GRPCConnected     bool             `json:"grpcConnected"`
}

DevServerState is the JSON-serializable state of a single plugin's dev server. This is sent to the frontend via Wails events and returned from query methods.

type ExternalConnection

type ExternalConnection struct {
	DevInfo     *DevInfoFile
	Connected   bool
	LastChecked time.Time
	// contains filtered or unexported fields
}

ExternalConnection tracks a connection to an externally-managed plugin.

type ExternalWatcher

type ExternalWatcher struct {
	// contains filtered or unexported fields
}

ExternalWatcher watches for .devinfo files in ~/.omniview/plugins/ and manages connections to externally-run plugin processes.

func NewExternalWatcher

func NewExternalWatcher(
	logger logging.Logger,
	onConnect func(pluginID string, info *DevInfoFile),
	onDisconnect func(pluginID string),
) (*ExternalWatcher, error)

NewExternalWatcher creates a new watcher for .devinfo files.

func (*ExternalWatcher) GetExternalInfo

func (ew *ExternalWatcher) GetExternalInfo(pluginID string) *DevInfoFile

GetExternalInfo returns the DevInfo for an externally-managed plugin, or nil.

func (*ExternalWatcher) IsExternallyManaged

func (ew *ExternalWatcher) IsExternallyManaged(pluginID string) bool

IsExternallyManaged returns true if the plugin has an active external connection.

func (*ExternalWatcher) Start

func (ew *ExternalWatcher) Start(ctx context.Context) error

Start begins watching for .devinfo files. Must be called after the Wails context is available.

func (*ExternalWatcher) Stop

func (ew *ExternalWatcher) Stop()

Stop shuts down the external watcher and disconnects all external plugins. It blocks until the run() goroutine has fully exited.

type LogEntry

type LogEntry struct {
	Timestamp string `json:"timestamp"`
	Source    string `json:"source"` // "vite" | "go-build" | "go-watch" | "manager"
	Level     string `json:"level"`  // "info" | "warn" | "error" | "debug"
	Message   string `json:"message"`
	PluginID  string `json:"pluginID"`
}

LogEntry is a single log line from either the Vite process or the Go build.

type LogRingBuffer

type LogRingBuffer struct {
	// contains filtered or unexported fields
}

LogRingBuffer is a fixed-size circular buffer for log entries. It is NOT thread-safe on its own; callers must hold the instance mutex.

func NewLogRingBuffer

func NewLogRingBuffer(capacity int) *LogRingBuffer

NewLogRingBuffer creates a ring buffer with the given capacity.

func (*LogRingBuffer) Clear

func (rb *LogRingBuffer) Clear()

Clear resets the buffer.

func (*LogRingBuffer) Entries

func (rb *LogRingBuffer) Entries() []LogEntry

Entries returns all entries in chronological order (oldest first).

func (*LogRingBuffer) Last

func (rb *LogRingBuffer) Last(n int) []LogEntry

Last returns the most recent n entries in chronological order.

func (*LogRingBuffer) Push

func (rb *LogRingBuffer) Push(entry LogEntry)

Push adds an entry to the ring buffer, overwriting the oldest if full.

type PluginRef

type PluginRef interface {
	GetDevPluginInfo(pluginID string) (devMode bool, devPath string, err error)
}

PluginRef is the minimal interface for reading plugin info. This avoids importing the plugin package (which would cause circular deps).

type PluginReloader

type PluginReloader interface {
	ReloadPlugin(id string) error
}

PluginReloader is the interface for reloading plugins after Go rebuild.

type PortAllocator

type PortAllocator struct {
	// contains filtered or unexported fields
}

PortAllocator manages port allocation for Vite dev servers. It tracks which ports are currently in use and finds free ones.

func NewPortAllocator

func NewPortAllocator() *PortAllocator

NewPortAllocator creates a new PortAllocator.

func (*PortAllocator) Allocate

func (pa *PortAllocator) Allocate(pluginID string) (int, error)

Allocate finds a free port in the range [PortRangeStart, PortRangeEnd) and reserves it for the given pluginID. Returns the port number or an error if no port is available.

func (*PortAllocator) CleanupStaleProcesses

func (pa *PortAllocator) CleanupStaleProcesses(ctx context.Context, logger logging.Logger)

CleanupStaleProcesses kills zombie Vite dev server process groups left over from a previous unclean shutdown. It reads the PID file written by SavePIDs, kills each recorded process group, and removes the file.

func (*PortAllocator) GetPort

func (pa *PortAllocator) GetPort(pluginID string) int

GetPort returns the port assigned to a plugin, or 0 if none.

func (*PortAllocator) RecordPID

func (pa *PortAllocator) RecordPID(port, pgid int)

RecordPID associates a process group ID with an allocated port so it can be killed during stale process cleanup on next startup.

func (*PortAllocator) Release

func (pa *PortAllocator) Release(port int)

Release frees a previously allocated port.

func (*PortAllocator) ReleaseByPlugin

func (pa *PortAllocator) ReleaseByPlugin(pluginID string) int

ReleaseByPlugin frees the port allocated to the given plugin ID, if any. Returns the port that was released, or 0 if no port was allocated.

func (*PortAllocator) SavePIDs

func (pa *PortAllocator) SavePIDs()

SavePIDs persists the current port→PGID map to disk so stale processes can be cleaned up after an unclean shutdown.

Jump to

Keyboard shortcuts

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