Documentation
¶
Overview ¶
Package workspace mounts additional gadak profiles under /w/<name>/ and lists them at GET /api/v1/workspaces. Shared by `gadak serve` and the desktop app.
Index ¶
- func CreateHandler() http.HandlerFunc
- func ListHandler() http.HandlerFunc
- func Prefix(profile, served string) string
- func ProfileEq(got, want string) bool
- func ProfileExists(name string) bool
- func RemoveHandler(reg *Registry) http.HandlerFunc
- type Entry
- type InvalidNameError
- type KindUnreadableError
- type ListEntry
- type NeedsDestroyOriginError
- type NeedsYesError
- type NotFoundError
- type Registry
- func (r *Registry) Close()
- func (r *Registry) EnsureOrigins()
- func (r *Registry) EnsureWatch(name string) bool
- func (r *Registry) EnsureWatches() []string
- func (r *Registry) Evict(name string)
- func (r *Registry) Get(name string) (*Entry, error)
- func (r *Registry) Handler(spa http.Handler, version string) http.HandlerFunc
- func (r *Registry) WatchAll(ctx context.Context, primary string, logf func(string)) []string
- type RemoveResult
- type RootRefusalError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CreateHandler ¶ added in v0.19.0
func CreateHandler() http.HandlerFunc
CreateHandler answers POST /api/v1/workspaces by seeding a local-origin workspace profile or registering a paired one (kind "paired" + offer). The local-origin seed is the shared one: config write, default issue type, mirror fill. A fill that fails is logged, not failed (SeedLocalOrigin contract — the workspace exists and writes work; the next sync fills). The paired path is createPaired's.
func ListHandler ¶
func ListHandler() http.HandlerFunc
ListHandler answers GET /api/v1/workspaces with the primary profile first (active:true) and every named profile after. Credentials never appear.
func Prefix ¶ added in v0.15.0
Prefix is the path segment that selects `profile` on a server whose primary profile is `served`: "" when they are the same mirror, "/w/<name>" when the profile has to be reached as a workspace mount.
Callers join it ahead of the rest of the path, so the empty string is the correct answer for the primary profile and not a missing value.
func ProfileEq ¶ added in v0.15.0
ProfileEq reports whether two profile names mean the same mirror. The primary profile answers to both "" and "default" — the config layer stores it empty, humans and URLs write it out — so a comparison that misses this sends `gadak views open` to /w/default on the very server it is talking to.
func ProfileExists ¶
ProfileExists reports whether name is a directory under profiles/ (disk is the source of truth for workspace mounts).
func RemoveHandler ¶ added in v0.19.0
func RemoveHandler(reg *Registry) http.HandlerFunc
RemoveHandler answers DELETE /api/v1/workspaces/{name}?yes=1&destroy_origin=1. Refusals map from Remove's typed errors; detail reuses the CLI refusal wording so both surfaces teach the same next move.
Types ¶
type Entry ¶
type Entry struct {
// Handler is the concrete server handler, not http.Handler: this entry
// owns its lifetime, and Close has to be able to stop the background sync
// before the mirror it writes to is closed (GDK-270).
Handler *server.Handler
DB *store.DB
Cfg *config.Config
// contains filtered or unexported fields
}
Entry is one opened workspace mirror (handler + DB + config).
type InvalidNameError ¶ added in v0.19.0
InvalidNameError wraps config.DirFor's refusal (separator, "..", ...). DirFor stays the single owner of name validation; this type only makes the refusal distinguishable from other failures for the HTTP mapper.
func (*InvalidNameError) Error ¶ added in v0.19.0
func (e *InvalidNameError) Error() string
func (*InvalidNameError) Unwrap ¶ added in v0.19.0
func (e *InvalidNameError) Unwrap() error
type KindUnreadableError ¶ added in v0.19.0
KindUnreadableError is a config.json that will not parse. An unreadable config is a refusal, not a guess: if this might be localOrigin, its persist is the only copy of that tracker and a plain --yes must not destroy it.
func (*KindUnreadableError) Error ¶ added in v0.19.0
func (e *KindUnreadableError) Error() string
func (*KindUnreadableError) Unwrap ¶ added in v0.19.0
func (e *KindUnreadableError) Unwrap() error
type ListEntry ¶
type ListEntry struct {
Name string `json:"name"`
Site string `json:"site,omitempty"`
Projects []string `json:"projects,omitempty"`
Active bool `json:"active,omitempty"`
Error string `json:"error,omitempty"`
}
ListEntry is one item in GET /api/v1/workspaces. Never carries Token or Email — only site URL and project keys for the picker.
type NeedsDestroyOriginError ¶ added in v0.19.0
NeedsDestroyOriginError: local-origin with an existing persist, but the caller did not opt into destroying the only copy of that tracker.
func (*NeedsDestroyOriginError) Error ¶ added in v0.19.0
func (e *NeedsDestroyOriginError) Error() string
type NeedsYesError ¶ added in v0.19.0
NeedsYesError: the caller asked about removal without committing to it. Local-origin picks the wording that says there is no origin data to protect (no persist exists); connected picks the one that says the origin keeps everything.
func (*NeedsYesError) Error ¶ added in v0.19.0
func (e *NeedsYesError) Error() string
type NotFoundError ¶ added in v0.19.0
NotFoundError is a name with no profile directory under profiles/.
func (*NotFoundError) Error ¶ added in v0.19.0
func (e *NotFoundError) Error() string
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry lazy-opens profile mirrors on first /w/<name>/ request and closes them when the process exits.
func (*Registry) Close ¶
func (r *Registry) Close()
Close closes every opened workspace DB. Safe to call once at shutdown. In-flight constructors are waited on (they see closed and close their own object) so this never closes a half-built entry.
func (*Registry) EnsureOrigins ¶ added in v0.18.0
func (r *Registry) EnsureOrigins()
EnsureOrigins retries ownership for every opened entry. The rescan loop calls this so a failed bind heals within watchRescanInterval.
func (*Registry) EnsureWatch ¶ added in v0.13.0
EnsureWatch starts this profile's Watch if WatchAll has armed the owner, the profile now has a credential, and no loop is already running. Idempotent. LoadFor and store.Open run with r.mu released.
func (*Registry) EnsureWatches ¶ added in v0.13.0
EnsureWatches is the single "credential appeared" scan: start a Watch for every non-primary profile that now has a credential and does not already have a loop. Returns the names that were started this call.
func (*Registry) Evict ¶ added in v0.19.0
Evict closes one opened workspace entry and forgets it, so a removal (DELETE /api/v1/workspaces/{name}) does not delete a profile directory out from under an open SQLite handle — the /w/<name>/ mount would keep serving a zombie mirror of files that no longer exist. No-op when the entry is not open. The next Get for the name reconstructs it lazily, so a refused removal costs one reopen, nothing else. Lock discipline matches Close: the map mutation is under mu, closeEntry (IO) runs after release.
func (*Registry) Handler ¶
Handler routes /w/<name>/… to the named profile's API, config, healthz, or SPA. Invalid names and unknown profiles answer 404. version is reported in healthz (same field as the primary /healthz).
func (*Registry) WatchAll ¶
WatchAll arms the credential-appearance owner and starts a loop for every profile that already has a credential, skipping primary (its caller already watches that one). Returns the profile names that got a loop. Subsequent credentials (onboarding connect, or a later EnsureWatches / rescan) start through the same owner and cannot double-start. Log receives status lines; never pass secrets into it — only profile names are logged from here.
type RemoveResult ¶ added in v0.19.0
type RemoveResult struct {
Removed string
Kind string
OriginDestroyed bool
// The success lines below need more than the three fields above:
// Dir is the removed directory, Persist the destroyed persist path
// (empty when none), Local-origin the pre-removal kind reading.
Dir string
Persist string
LocalOrigin bool
// Advisory materials.
PairedSelector string
ClearedStored bool
WasActive bool
}
RemoveResult is what a successful removal did. The CLI shell reassembles its output lines from these fields; the HTTP handler serialises them. The core itself prints nothing except the stored-default warning, which was stderr-bound before the extraction and stays that way (both surfaces want it on stderr, and a silent failure to clear a now-dangling default is worse than a duplicated line).
func Remove ¶ added in v0.19.0
func Remove(name string, yes, destroyOrigin bool, cmdHint string) (RemoveResult, error)
Remove deletes the named workspace profile. Refusals are typed so each surface (CLI text, HTTP JSON) can answer with its own shape without re-deriving the decision; every refusal's Error() is the CLI wording. cmdHint is the command spelling the "to proceed" lines name ("workspaces" or "profiles" for the CLI aliases, "workspaces" for HTTP).
func (RemoveResult) Advisories ¶ added in v0.19.0
func (res RemoveResult) Advisories() []string
Advisories returns the lines that are true for every successful removal, whatever the kind: the pairing hint for a workspace that paired with a home serve, the stored-default cleanup note, the was-active retarget hint, and the serve-staleness warning (there is no reliable detector for a running serve since the persist lock was removed, GDK-936). One owner of the wording — the CLI prints each line, the HTTP handler returns them as the JSON "advisories" array.
type RootRefusalError ¶ added in v0.19.0
RootRefusalError is the ""/"default" refusal: the unnamed workspace is the home directory itself, not a profile under it — removing "the default workspace" must not be rm -rf on the whole home by another door.
func (*RootRefusalError) Error ¶ added in v0.19.0
func (e *RootRefusalError) Error() string