Documentation
¶
Overview ¶
Package preview serves design artifacts over HTTP so every surface — the WebUI iframe, a system browser opened from the TUI, a Zed resource link — looks at the same running document instead of a file:// copy.
The package deliberately knows nothing about the design model: it is handed a directory and an entry document and hands back a URL. That keeps it free of any dependency on internal/design, so internal/design can import it to mint URLs while internal/api mounts the very same handler on the main listener.
Two deployments share one implementation:
- mounted: internal/api registers Server.ServeHTTP under Prefix on the API listener, so the preview lives on the Pando origin and is reachable remotely through the existing external-access toggle.
- loopback: processes without an API server (plain TUI, ACP, CLI) call Server.StartLoopback, which binds 127.0.0.1:0 and serves the same routes.
Every artifact is addressed through an unguessable per-artifact token in the path. The token is the capability: it is bound to the session that created it and dies with the grant, so a stale URL in someone's browser history stops resolving instead of exposing whatever now sits in that directory.
Index ¶
- Constants
- Variables
- type Grant
- type Options
- type Server
- func (s *Server) Addr() string
- func (s *Server) Bump(artifactID string)
- func (s *Server) Close()
- func (s *Server) Grants() []Grant
- func (s *Server) Publish(artifactID, sessionID, absDir, entry string) (Grant, error)
- func (s *Server) Revoke(artifactID string)
- func (s *Server) RevokeSession(sessionID string)
- func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (s *Server) StartLoopback() error
- func (s *Server) URL(artifactID string, opts URLOptions) (string, error)
- type URLOptions
Constants ¶
const BridgePath = Prefix + "_bridge.js"
BridgePath serves the selection bridge. It sits outside the token space on purpose: it is a static asset with no artifact content in it, and keeping it token-free means one cached copy serves every artifact.
const DefaultTTL = 12 * time.Hour
DefaultTTL is how long a grant stays resolvable without being refreshed. Presenting an artifact refreshes it, so an artifact under active iteration never expires while the user is looking at it.
const Prefix = "/preview/"
Prefix is the single route prefix the server owns. Everything below it is artifact content; nothing above it is ever touched.
Variables ¶
var ErrForbidden = errors.New("preview: refused")
ErrForbidden is returned by an access guard that refuses to serve. The API server uses it to keep previews off a network-facing listener that has no authentication in front of it.
Functions ¶
This section is empty.
Types ¶
type Grant ¶
type Grant struct {
Token string `json:"token"`
ArtifactID string `json:"artifact_id"`
SessionID string `json:"session_id,omitempty"`
// Dir is the absolute artifact directory. Nothing outside it is served.
Dir string `json:"-"`
// Entry is the directory-relative default document.
Entry string `json:"entry"`
ExpiresAt time.Time `json:"expires_at"`
// contains filtered or unexported fields
}
Grant is one artifact published for viewing.
type Options ¶
type Options struct {
// BaseURL resolves the origin to build absolute URLs with. It is a function
// because the API server's bind address changes at runtime when the
// external-access toggle is flipped. When it is nil or returns an empty
// string the server falls back to its own loopback listener, and to a
// relative URL when it has none.
BaseURL func() string
// Access is consulted on every request and before every publish. A non-nil
// error refuses the operation. It exists so the API server can enforce
// "never on a non-loopback bind without basic auth".
Access func() error
// TTL overrides DefaultTTL.
TTL time.Duration
// FrameAncestors overrides the CSP frame-ancestors list. It defaults to
// 'self', which is right whenever the preview and the UI framing it share
// an origin — the mounted deployment. A shell that runs the UI on its own
// origin (the Wails desktop app) has to widen it, and doing that here keeps
// the decision in the caller that knows its own origin.
FrameAncestors string
// Inject is JavaScript spliced into a ?bridge=1 document ahead of the
// bridge itself. internal/design supplies the renderer's own element
// walker here, so the data-pando-id a user clicks in the browser is the
// same id the stored node index holds. Keeping it an option is what lets
// this package stay ignorant of the design model.
Inject []byte
}
Options configures a server.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the grant registry and the HTTP handler over it.
func (*Server) Bump ¶
Bump increments the live-reload revision of a published artifact. It is a no-op when the artifact has no active grant on this server.
func (*Server) Close ¶
func (s *Server) Close()
Close stops the loopback listener and drops every grant.
func (*Server) Grants ¶
Grants lists the live grants, newest expiry first is not guaranteed; the order is unspecified. It exists for diagnostics and tests.
func (*Server) Publish ¶
Publish registers (or refreshes) a grant for an artifact directory and returns it. The token is stable for the lifetime of the grant so reloading a preview keeps the same URL, which is what lets an iframe survive a re-render.
func (*Server) RevokeSession ¶
RevokeSession drops every grant a session published. Sessions end; their preview URLs must stop resolving with them.
func (*Server) ServeHTTP ¶
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP serves artifact files under Prefix.
func (*Server) StartLoopback ¶
StartLoopback binds 127.0.0.1:0 and serves the preview routes there. It is the fallback for processes with no API server; calling it twice is a no-op.
type URLOptions ¶
type URLOptions struct {
// Slide adds a #slide-N fragment (decks).
Slide int
// Bridge asks for the selection bridge to be injected. Only the Pando UI
// sets it; a URL opened in a plain browser stays untouched markup.
Bridge bool
// Doc overrides the entry document with another directory-relative file.
Doc string
}
URLOptions tunes the address Publish hands out.