Documentation
¶
Overview ¶
Package sdk is the Tabibu Extension SDK. Import it in your extension's main package and call Run with your Extension implementation.
The SDK handles:
- .env file loading on startup (dev convenience)
- stdio JSON-RPC (NDJSON) over inherited stdin/stdout
- Pine HTTP server on EXT_HTTP_PORT (default 9000)
- Static UI serving from ui/dist/ in production (EXT_DEV != "true")
- Domain service calls via sdk.Patients() and friends
- Graceful drain on shutdown message or SIGTERM → drain_done → exit 0
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func HTTPClient ¶
func HTTPClient() *client
HTTPClient returns a pre-authenticated *http.Client for making direct calls to the Tabibu server. Use this only when sdk.Patients() (or other service accessors) don't cover what you need.
func Run ¶
Run starts the extension. It blocks until the process is told to shut down.
- Loads .env (dev convenience; existing vars take precedence)
- Reads env vars: EXT_NAME, EXT_HTTP_PORT, EXT_DATA_DIR, EXT_DEV, EXT_SERVER_URL
- Opens the log file in EXT_DATA_DIR/logs/extension.log
- Initialises the stdio IPC conn (stdin/stdout are inherited from parent)
- Reads the API key from EXT_DATA_DIR/.api_key for sdk.HTTPClient()
- Calls ext.OnStart(ctx, server)
- In prod: serves ui/dist/ as a SPA if the directory exists
- Starts dispatching stdin messages (events, shutdown, config_update)
- SIGTERM fallback: triggers drain if runtime message never arrives
Types ¶
type Config ¶
Config is a read-only map of key-value pairs from the extension's config section in manifest.toml, overridden by admin in the Tabibu panel. Updated automatically when an OnConfigUpdate message arrives on stdin.
type Ctx ¶
type Ctx interface {
Status(code int) Ctx
JSON(v any) error
BindJSON(v any) error
Params(key string) string
Query(key string) string
Context() context.Context
Header(key string) string
}
Ctx is the request context passed to handler functions.
type Event ¶
type Event struct {
Name string `json:"name"`
Version string `json:"version"`
OccurredAt time.Time `json:"occurred_at"`
Payload json.RawMessage `json:"payload"`
ID string `json:"id"`
}
Event carries a single event dispatched to the extension.
type Extension ¶
type Extension interface {
// OnStart is called once after the SDK is ready. Register HTTP routes
// on the provided Server. Return a non-nil error to abort startup.
OnStart(ctx context.Context, server Server) error
// OnEvent is called for each event routed to this extension by the
// Extension Runtime (declared in manifest.toml contributes.events).
// Return a non-nil error to signal processing failure.
OnEvent(ctx context.Context, event Event) error
// OnShutdown is called when Tabibu sends a drain signal (shutdown message
// on stdin or SIGTERM). Finish in-flight work and return. The SDK then
// writes drain_done to stdout and exits 0. The process is force-killed
// after stop_grace_period seconds.
OnShutdown(ctx context.Context) error
// OnConfigUpdate is called when the extension's config is changed in the
// Tabibu admin panel. Values are pushed via the stdio config_update message.
// Use sdk.Config() to read the current config map at any time.
OnConfigUpdate(ctx context.Context, cfg Config) error
}
Extension is the interface every Tabibu extension must implement.
type HandlerFunc ¶
HandlerFunc is the signature for HTTP handlers registered via Server.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger writes structured JSON log entries to both logs/extension.log and stderr. The log file is opened with O_APPEND so existing content is preserved across restarts. In containerised deployments log shipping (e.g. Fluent Bit) reads from the file; rotation is handled by the container runtime or logrotate.
var Log *Logger
Log is the SDK's structured logger. Available after Run() has started.
type Patient ¶
type Patient struct {
ID string `json:"id"`
BloodGroup *string `json:"blood_group,omitempty"`
AllergyStatus string `json:"allergy_status"`
CreatedAt string `json:"created_at"`
Person PatientPerson `json:"person"`
}
Patient is a patient record as returned by the Extension Runtime. Fields mirror the server's patients.models.Patient JSON output.
type PatientPerson ¶
type PatientPerson struct {
ID string `json:"id"`
GivenName string `json:"given_name,omitempty"`
MiddleName string `json:"middle_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
Salutation string `json:"salutation,omitempty"`
Sex string `json:"sex"`
Birthdate *string `json:"birthdate,omitempty"`
BirthdateEstimated bool `json:"birthdate_estimated"`
PrimaryPhone *string `json:"primary_phone,omitempty"`
AltPhone *string `json:"alt_phone,omitempty"`
Email *string `json:"email,omitempty"`
PhotoURL *string `json:"photo_url,omitempty"`
}
PatientPerson holds the demographic and contact data for a patient. Fields mirror the server's persons.models.Person JSON output.
type PatientsService ¶
type PatientsService interface {
// List returns patients whose name or ID matches query. Pass an empty
// string to return all patients.
List(ctx context.Context, query string) ([]Patient, error)
// Get returns a single patient by UUID.
Get(ctx context.Context, id string) (Patient, error)
// Register creates a new patient record.
Register(ctx context.Context, req RegisterPatientRequest) (Patient, error)
}
PatientsService provides read and write access to the patients domain. Calls are routed through the stdio IPC channel to the Extension Runtime, which forwards them to the server's patients module.
func Patients ¶
func Patients() PatientsService
Patients returns the patients domain service backed by the IPC channel. Call from within handler functions or background goroutines after Run() starts.
type RegisterPatientRequest ¶
type RegisterPatientRequest struct {
GivenName string `json:"given_name"`
MiddleName string `json:"middle_name,omitempty"`
FamilyName string `json:"family_name"`
Salutation string `json:"salutation,omitempty"`
Sex string `json:"sex"`
Birthdate string `json:"birthdate,omitempty"`
BirthdateEstimated bool `json:"birthdate_estimated,omitempty"`
BloodGroup *string `json:"blood_group,omitempty"`
AllergyStatus string `json:"allergy_status,omitempty"`
Phone string `json:"primary_phone,omitempty"`
AltPhone string `json:"alt_phone,omitempty"`
Email string `json:"email,omitempty"`
}
RegisterPatientRequest is the payload for registering a new patient. Fields mirror the server's patients.models.RegisterRequest.
type Server ¶
type Server interface {
Get(path string, h HandlerFunc)
Post(path string, h HandlerFunc)
Put(path string, h HandlerFunc)
Delete(path string, h HandlerFunc)
}
Server is the subset of Pine's API exposed to OnStart.