generation

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package generation hosts the telescope-side OpenAPI generation loop.

The loop wraps cartographer's in-process extraction API, debounces source file change notifications, caches the last-good result per workspace root, and materialises the spec to disk only when the user's config permits.

Downstream consumers (LSP features, the telescope CLI, the VS Code extension) read from Loop.Current to obtain the authoritative in-memory spec bytes and its SourceMap.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Root is the workspace root directory the Loop extracts from.
	Root string
	// ConfigDir is an optional override for the .cartographer directory;
	// defaults to <Root>/.cartographer when empty.
	ConfigDir string
	// OutputPath, when non-empty, controls where DiskWriter persists the spec.
	OutputPath string
	// Lang overrides cartographer's language auto-detection.
	Lang string

	// DebounceWindow is the idle duration used by the debouncer. Defaults to
	// 500ms when zero.
	DebounceWindow time.Duration
	// SlowExtractionThreshold, when non-zero, causes the loop to drop to
	// save-only triggering after any single extraction exceeds this duration.
	SlowExtractionThreshold time.Duration

	// WriteMode / WriteSourceMap control DiskWriter behaviour.
	WriteMode      WriteMode
	WriteSourceMap bool

	// TriggerMode: "always" (debounce + save) or "save" (save-only).
	TriggerMode string
}

Config is the per-root configuration for a single Loop instance.

type DiskWriter

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

DiskWriter persists extraction results to disk according to a WriteMode policy. The Loop constructs one DiskWriter per workspace root.

func NewDiskWriter

func NewDiskWriter(outputPath string, writeSourceMap bool, mode WriteMode) *DiskWriter

NewDiskWriter constructs a DiskWriter. outputPath may be empty, in which case Write is a no-op regardless of mode.

func (*DiskWriter) Mode

func (w *DiskWriter) Mode() WriteMode

Mode returns the current WriteMode policy.

func (*DiskWriter) OnDiskHash

func (w *DiskWriter) OnDiskHash(result *Result) (string, bool, error)

OnDiskHash returns the sha256 hex digest of the current on-disk spec, if any. Loop uses this to detect manual-edit skew vs. the last extraction.

func (*DiskWriter) OutputPath

func (w *DiskWriter) OutputPath() string

OutputPath returns the configured output path, if any.

func (*DiskWriter) ShouldWrite

func (w *DiskWriter) ShouldWrite(trigger Trigger) bool

ShouldWrite returns true if the configured mode permits a write for the given trigger.

func (*DiskWriter) Write

func (w *DiskWriter) Write(result *Result, trigger Trigger) error

Write persists the spec (and optional sourcemap sidecar) to disk, if the current mode permits it for the given trigger.

type Event

type Event struct {
	Kind     EventKind
	Root     string
	Duration time.Duration
	Err      error
	Result   *Result
}

Event is emitted on every loop iteration and broadcast to all subscribers.

type EventKind

type EventKind string

EventKind identifies a Loop lifecycle event.

const (
	GenerationStarted   EventKind = "started"
	GenerationSucceeded EventKind = "succeeded"
	GenerationFailed    EventKind = "failed"
	GenerationSkipped   EventKind = "skipped"
)

type ExtractResult

type ExtractResult struct {
	SpecBytes   []byte
	SpecMap     map[string]interface{}
	SourceMap   *sourcemap.SourceMap
	OutputPath  string
	Operations  int
	Types       int
	GeneratedAt time.Time
	Duration    time.Duration
	// SpecSource records which cartographer path produced the spec:
	// "extracted" (source extraction), "canonical-openapi3"
	// (in-repo OpenAPI 3 file), "canonical-swagger2" (auto-converted
	// Swagger 2), or "non-rest-stub" (library/worker placeholder).
	SpecSource string
	// CanonicalSpecPath is the absolute path of the in-repo spec used
	// by the passthrough, or empty when source extraction ran.
	CanonicalSpecPath string
	// DetectedLanguage is what cartographer's on-disk heuristics would
	// have picked as the language. Used to surface mislabelled services
	// in downstream reports without forcing the pipeline to bail.
	DetectedLanguage string
	// LanguageMismatch is true when DetectedLanguage disagrees with the
	// resolved Lang (e.g. java-spring template on a go.mod repo).
	LanguageMismatch bool
	// HasConfig is true when .cartographer/cartographer.yaml was loaded.
	HasConfig bool
	// ConfigApplied is true when service-local shaping (path rewrites, metadata) ran.
	ConfigApplied bool
}

ExtractResult is the in-memory output of a single extraction.

type Extractor

type Extractor struct{}

Extractor is a thin adapter around cartographer/extraction.ExtractProject.

func NewExtractor

func NewExtractor() *Extractor

NewExtractor constructs a new Extractor.

func (*Extractor) Extract

func (e *Extractor) Extract(ctx context.Context, opts ExtractorOptions) (*ExtractResult, error)

Extract runs cartographer extraction and renders the result as YAML bytes, plus a SourceMap derived from the spec's structured x-source metadata.

ctx is accepted for future cancellation support; cartographer's current API is synchronous so ctx is used only to abort before the run and to bound any post-processing.

type ExtractorOptions

type ExtractorOptions struct {
	RootDir     string
	ConfigDir   string
	Lang        string
	Template    string
	Title       string
	Version     string
	Description string
	OutputPath  string
	// Kind marks non-REST services (worker, library, non-rest,
	// scheduler, connector, cli). When set, cartographer skips source
	// extraction and either uses an in-repo canonical spec or emits a
	// minimal stub.
	Kind string
	// PreferCanonicalSpec tells cartographer to auto-discover an
	// in-repo OpenAPI/Swagger spec (openapi.yaml, docs/swagger.yaml,
	// ...) and use it instead of running source extraction
	// when one is found. Falls back to source extraction otherwise.
	PreferCanonicalSpec bool
	// Extraction configures code-derived extraction behavior (error schema,
	// signature pagination types, co-located OpenAPI merge). When unset,
	// cartographer.yaml extraction block is used when present.
	Extraction extractionopts.Options
}

ExtractorOptions configures a single extraction run. Fields map onto cartographer's ProjectOptions plus a couple of telescope-side knobs.

type Loop

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

Loop is the per-workspace generation supervisor. It owns an Extractor, a debouncer, a DiskWriter, and a cache of the last-good Result.

func NewLoop

func NewLoop(cfg Config, logger *slog.Logger) *Loop

NewLoop constructs a new Loop for a single workspace root.

func (*Loop) Current

func (l *Loop) Current() (*Result, bool)

Current returns the most recent successful extraction, if any.

func (*Loop) DetectSkew

func (l *Loop) DetectSkew() (bool, error)

DetectSkew returns true when the on-disk spec differs from the last one the Loop wrote, signalling a manual edit.

func (*Loop) NotifyChange

func (l *Loop) NotifyChange(sourceURI string)

NotifyChange schedules a debounced regeneration in response to a didChange on a watched source file.

func (*Loop) NotifySave

func (l *Loop) NotifySave(sourceURI string)

NotifySave forces an immediate regeneration (bypassing the debounce window) and, if WriteMode permits, triggers an onSave disk write.

func (*Loop) RegenerateNow

func (l *Loop) RegenerateNow(ctx context.Context, trigger Trigger) (*Result, error)

RegenerateNow runs an extraction synchronously.

func (*Loop) Root

func (l *Loop) Root() string

Root returns the workspace root this Loop was constructed for.

func (*Loop) SkewHash

func (l *Loop) SkewHash() string

SkewHash returns the last recorded on-disk hash for skew detection.

func (*Loop) Start

func (l *Loop) Start(ctx context.Context) error

Start begins listening for change notifications. The returned error is only non-nil for configuration issues; transient extraction errors are surfaced via Events.

func (*Loop) Stop

func (l *Loop) Stop(drain time.Duration) error

Stop cancels the loop's root context and waits up to drain for any in-flight extraction. Safe to call multiple times.

func (*Loop) Subscribe

func (l *Loop) Subscribe(fn func(Event))

Subscribe registers a listener that is invoked for every lifecycle Event.

func (*Loop) WriteNow

func (l *Loop) WriteNow() error

WriteNow forces a disk write using the last good extraction, ignoring the configured WriteMode. Backs `Telescope: Write Spec to Disk Now`.

func (*Loop) Writer

func (l *Loop) Writer() *DiskWriter

Writer returns the loop's DiskWriter. Callers should not mutate it.

type Manager

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

Manager owns one Loop per workspace root. It is the handle LSP lifecycle wiring uses to add/remove roots on didChangeWorkspaceFolders and broadcast config changes to all live loops.

func NewManager

func NewManager(logger *slog.Logger) *Manager

NewManager constructs an empty Manager.

func (*Manager) Add

func (m *Manager) Add(ctx context.Context, cfg Config) (*Loop, error)

Add creates and starts a Loop for the given root, replacing any existing one. Previously-registered subscribers are re-attached so the event stream is uninterrupted across Stop+Start.

func (*Manager) Apply

func (m *Manager) Apply(ctx context.Context, cfg Config) (*Loop, bool, error)

Apply reconfigures the loop for the given root. Safe fields are hot-reloaded; unsafe fields (enabled toggle, Root change) require a Stop+Start, which the Manager performs transparently.

func (*Manager) Get

func (m *Manager) Get(root string) (*Loop, bool)

Get returns the Loop for a given workspace root, if any.

func (*Manager) NotifyChange

func (m *Manager) NotifyChange(root, sourceURI string)

NotifyChange forwards a source-file change to the Loop owning the workspace root that contains the URI.

func (*Manager) NotifySave

func (m *Manager) NotifySave(root, sourceURI string)

NotifySave forwards a didSave to the matching Loop.

func (*Manager) Remove

func (m *Manager) Remove(root string)

Remove stops and drops the Loop for a given workspace root.

func (*Manager) Roots

func (m *Manager) Roots() []string

Roots returns all known workspace roots.

func (*Manager) StopAll

func (m *Manager) StopAll(drain time.Duration)

StopAll tears down every Loop with a bounded drain.

func (*Manager) Subscribe

func (m *Manager) Subscribe(fn func(Event))

Subscribe attaches a single listener across every current and future Loop owned by this manager.

type Result

type Result struct {
	Root        string
	SpecBytes   []byte
	SpecMap     map[string]interface{}
	SourceMap   *sourcemap.SourceMap
	OutputPath  string
	GeneratedAt time.Time
	Duration    time.Duration
	Operations  int
	Types       int
}

Result is the last-good extraction result served to consumers via Loop.Current. It survives transient extraction failures so subsequent lint runs can keep working off the previous known-good spec.

type Trigger

type Trigger string

Trigger describes why the Loop asked the writer to persist.

const (
	TriggerAuto     Trigger = "auto"     // post-regenerate write, subject to mode
	TriggerOnSave   Trigger = "onSave"   // didSave-fired regenerate
	TriggerOnDemand Trigger = "onDemand" // explicit CLI/LSP command
)

type WriteMode

type WriteMode string

WriteMode controls when Loop materialises the in-memory spec to disk.

const (
	// WriteNever disables all disk writes regardless of output/writeSourceMap.
	WriteNever WriteMode = "never"
	// WriteOnDemand only writes when the user explicitly asks via CLI/command.
	WriteOnDemand WriteMode = "onDemand"
	// WriteOnSave writes after regenerations triggered by a didSave event.
	WriteOnSave WriteMode = "onSave"
	// WriteAlways writes after every successful regeneration.
	WriteAlways WriteMode = "always"
)

Jump to

Keyboard shortcuts

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