Documentation
¶
Index ¶
- type Config
- type Server
- type Store
- func (s *Store) Create(name string, doc entityDoc) (map[string]any, bool)
- func (s *Store) Delete(name, id string) bool
- func (s *Store) FindBy(name, field, value string) (string, bool)
- func (s *Store) Get(name, id string) (map[string]any, bool)
- func (s *Store) List(name string) []map[string]any
- func (s *Store) Update(name, id string, doc entityDoc, patch bool) (map[string]any, error)
- type TargetStatus
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Host is the interface to bind. It defaults to loopback (127.0.0.1): the emulator
// authenticates nothing, so it must not be reachable off the machine unless the
// user deliberately widens it (a container that maps the port needs 0.0.0.0).
Host string
// Port is the TCP port to listen on.
Port int
// Seed is a directory of JSON fixtures to preload, or "" for an empty tenant.
Seed string
// Verbose logs one line per request to Log.
Verbose bool
// Log is where request logs and startup notices go — stderr, so stdout stays the
// data contract even here.
Log io.Writer
// Components is where the emulator looks for its transport sub-components: the
// processes that deliver an event to a broker. A nil registry means none, which is
// an emulator that delivers webhooks and nothing else — a perfectly ordinary way to
// run it.
Components *component.Registry
// TransportEnv is the configuration to hand those components, by variable name.
// Only the names a component's manifest declares are actually set, so
// --pubsub-emulator-host reaches the Pub/Sub transport as the PUBSUB_EMULATOR_HOST
// it already reads, and reaches nothing else.
TransportEnv map[string]string
// WebhookAllowRemote lets webhook delivery call a callbackUrl outside the local
// network. It is off by default so a subscription fixture naming a real endpoint is
// skipped rather than fired made-up events at.
WebhookAllowRemote bool
// contains filtered or unexported fields
}
Config configures a Server.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a running emulator: a Fiber app answering the whole API surface from one in-memory store.
func New ¶
New builds a server: it registers every operation in the spec, wires the store, and preloads any seed data. It does not listen yet.
func (*Server) Eventing ¶ added in v0.6.0
func (s *Server) Eventing() []TargetStatus
Eventing reports each subscription target type, and what will happen to a subscription that names it.
The three the API defines are always reported, including the ones nothing delivers — a stored subscription that silently never fires is the failure this notice exists to prevent, and leaving the unavailable ones out is how it would happen. A third-party transport's own target type is reported too: it is the same silent failure, and a notice that only knew the three built-in types would hide exactly the broker the community protocol was added to reach.
func (*Server) Listen ¶
Listen binds the port and serves until ctx is cancelled, then shuts down gracefully and returns nil. It returns a non-nil error when the port could not be bound (e.g. already taken) or the server otherwise failed.
ready, if non-nil, is called the moment the port is bound — before Listen starts blocking to serve — so a caller can print a "point fft here" recipe only once it is actually true, instead of racing a bind failure with a recipe that looks like it worked.
ctx is the command's context, which the root cancels on SIGINT/SIGTERM — so Ctrl-C drains the server and exits 0.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the emulator's in-memory tenant: a set of collections, each a map of entities by id with a stable insertion order for pagination. One RWMutex guards the whole thing — a dev-time emulator has no need for finer locking, and one lock is one fewer thing to reason about.
func NewStore ¶
NewStore returns an empty store that knows each collection's response metadata (its items-key), inferred from the spec.
func (*Store) Create ¶
Create stores a new entity, assigning it an id (unless the body carries one) and version 1 (unless the body carries a version), and returns the stored document. This honors an incoming id/version so seed() can replay a fixture's captured values; the live HTTP create handler strips both from the body before calling this, matching the real API's server-assigned id/version semantics. The exported methods speak the concrete map[string]any rather than the internal entityDoc alias, which is the same type.
The second return is false when the collection is at [maxEntitiesPerCollection] and the entity was not stored.
func (*Store) FindBy ¶
FindBy returns the id of the first entity in the collection whose string field equals value, in insertion order. It backs URN path resolution: the API addresses a facility as urn:fft:facility:tenantFacilityId:<value>, and this is how the emulator turns that selector back into the entity the store keeps.
func (*Store) List ¶
List returns every entity in the collection, in insertion order. It clones on every call — the paginators then slice the result — which is O(n) per page and so O(n²) across a full walk. That is deliberate simplicity: a dev emulator holds tens of entities, not the millions where this would matter.
func (*Store) Update ¶
Update replaces (PUT) or merges (PATCH) an entity and bumps its version.
It enforces the body-carried optimistic lock: when the incoming document names a version and it does not match the stored one, the update is refused with a *conflictError so the client re-reads and retries. A missing version is taken as "whatever is current" rather than a conflict, so a PATCH need not echo it.
type TargetStatus ¶ added in v0.6.0
type TargetStatus struct {
// Target is the target type, e.g. GOOGLE_CLOUD_PUB_SUB.
Target string
// Status is one line, in the transport's own words where there is one. A
// transport that came from a component said this at the handshake, so the notice
// reports where a broker actually is without the emulator knowing anything about
// brokers.
Status string
// Live reports whether anything will be delivered to this target type at all.
Live bool
}
TargetStatus is what the startup notice says about one subscription target type: whether an event with that target will be delivered, and where.