types

package
v0.0.0-...-e769803 Latest Latest
Warning

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

Go to latest
Published: Jul 2, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrEntryNotFound = errors.New("cache entry not found")

ErrEntryNotFound is returned when a cache entry is not found.

Functions

This section is empty.

Types

type Cache

type Cache[T any] interface {
	// Get retrieves a value from the cache by key.
	// Returns ErrEntryNotFound if the key does not exist.
	Get(key string) (T, error)

	// Peek retrieves a value from the cache by key without affecting its position or access time.
	// Returns ErrEntryNotFound if the key does not exist.
	Peek(key string) (T, error)

	// Set stores a value in the cache with the specified TTL.
	// A zero TTL means the entry will not expire.
	Set(key string, value T, ttl time.Duration) error

	// Delete removes a key from the cache.
	// Returns ErrEntryNotFound if the key does not exist.
	Delete(key string) error

	// Exists checks if a key exists in the cache.
	// Returns true if the key exists, false otherwise.
	Exists(key string) bool

	// Len returns the number of entries currently stored in the cache.
	Len() int

	// Clear removes all entries from the cache.
	Clear()

	// WithContext returns a cache handle that uses ctx for tracing or cancellation propagation.
	//
	// Implementations may return a new handle or mutate and return the receiver.
	// Callers must not assume the returned handle is independent unless a concrete
	// provider documents that stronger guarantee.
	WithContext(ctx context.Context) Cache[T]
}

Cache provides a typed key/value cache abstraction with TTL and context propagation.

Type Parameters:

  • T: Cached value type

Error Handling:

  • Get/Peek return ErrEntryNotFound when key doesn't exist
  • Set/Delete return backend errors when storage operations fail

type Coder

type Coder interface {
	Code() int
	Status() int
	Msg() string
}

Coder describes an API envelope code, HTTP status, and client-safe message.

type ControllerConfig

type ControllerConfig[M Model] struct {
	// DB overrides the database handle used by the route. Only *gorm.DB is supported.
	DB any
	// TableName overrides the model table name used by the route.
	TableName string
	// ParamName names the route parameter that carries the resource ID.
	ParamName string
}

ControllerConfig customizes how router.Register builds an internal handler for a route. It is the public configuration surface for controller behavior; the concrete controller handlers and their runtime state remain framework-owned.

type Database

type Database[M Model] interface {
	// Create inserts one or more records, setting framework IDs and timestamps unless WithDryRun is enabled.
	Create(objs ...M) error
	// Delete removes one or more records using WithPurge, the model Purge setting, or soft delete by default.
	Delete(objs ...M) error
	// Update saves one or more full model values and updates timestamps unless WithDryRun is enabled.
	Update(objs ...M) error
	// UpdateByID updates a single field of a record by its ID.
	UpdateByID(id string, key string, value any) error
	// List retrieves multiple records matching the query conditions.
	List(dest *[]M) error
	// Get retrieves a single record by its ID.
	// The destination must be a non-nil pointer matching M. When M is *T,
	// both &value and new(T) are valid destinations; a nil *T returns ErrNilDest.
	// Get returns database.ErrRecordNotFound when no matching record exists.
	Get(dest M, id string) error
	// First retrieves the first record matching the current query conditions.
	First(dest M) error
	// Last retrieves the last record matching the current query conditions.
	Last(dest M) error
	// Take retrieves the first record in no specified order.
	Take(dest M) error
	// Count returns the total number of records matching the query conditions.
	Count(*int64) error
	// Cleanup permanently deletes all soft-deleted records; WithDryRun only builds the cleanup SQL.
	Cleanup() error
	// Health checks database connectivity and is not disabled by WithDryRun.
	Health() error
	// Transaction executes fn in a transaction for this model and passes a transaction-bound Database.
	Transaction(fn func(txDB Database[M]) error) error
	// TransactionFunc executes fn in a transaction for multi-model work; each Database used inside fn must call WithTx(tx).
	// WithTx also seeds the returned operation chain's context, so model hooks that receive that context and call
	// database.Database[*OtherModel](ctx) keep using the same transaction.
	TransactionFunc(fn func(tx any) error) error

	DatabaseOption[M]
}

Database defines the model-scoped database operation contract. It provides CRUD operations, query builders, transactions, cleanup, health checks, and optional cache/dry-run behavior for a single Model type.

Type Parameters:

  • M: Model type that implements Model interface

The interface embeds DatabaseOption[M] to provide chainable query building. A chain is expected to end with one terminal operation, such as Create, List, Get, Count, Cleanup, Health, Transaction, or TransactionFunc.

Implementations share an underlying GORM session. Call database.Database[M](ctx) again for each independent operation chain. Keeping the returned value in a variable and running another independent operation on it (for example, List then Get or Update) is incorrect usage; see database.Database.

type DatabaseOption

type DatabaseOption[M Model] interface {
	// WithDB uses a custom *gorm.DB; callers must migrate custom schemas explicitly.
	WithDB(any) Database[M]
	// WithTx binds operations to a *gorm.DB transaction, primarily inside TransactionFunc.
	// It also stores the transaction in the operation context so model hooks can pass ctx to Database[*OtherModel](ctx)
	// without manually threading the raw transaction through hook signatures.
	WithTx(tx any) Database[M]
	// WithTable sets a custom table name; the table must already exist.
	WithTable(name string) Database[M]
	// WithDebug enables debug mode to show detailed SQL queries.
	WithDebug() Database[M]
	// WithQuery adds query conditions from model fields or raw SQL configuration.
	WithQuery(query M, config ...QueryConfig) Database[M]
	// WithCursor enables cursor-based pagination for List operations.
	WithCursor(string, bool, ...string) Database[M]
	// WithTimeRange applies a time range filter to the query.
	WithTimeRange(columnName string, startTime time.Time, endTime time.Time) Database[M]
	// WithSelect specifies fields for SELECT and Update column selection where supported.
	WithSelect(columns ...string) Database[M]
	// WithIndex specifies database index hints for query optimization (MySQL only).
	WithIndex(indexName string, hint ...consts.IndexHintMode) Database[M]
	// WithRollback configures a callback that runs when Transaction or TransactionFunc rolls back.
	WithRollback(rollbackFunc func()) Database[M]
	// WithLock adds row-level locking to SELECT queries (must be used within a transaction).
	WithLock(mode ...consts.LockMode) Database[M]
	// WithBatchSize sets the batch size for Create, Update, and Delete.
	WithBatchSize(size int) Database[M]
	// WithPagination applies pagination parameters (page, size) to the query.
	WithPagination(page, size int) Database[M]
	// WithLimit restricts the number of returned records for read operations.
	WithLimit(limit int) Database[M]
	// WithOffset skips records before returning read operation results.
	WithOffset(offset int) Database[M]
	// WithExclude excludes records matching specified conditions.
	WithExclude(map[string][]any) Database[M]
	// WithOrder adds ORDER BY clause to sort query results.
	WithOrder(order string) Database[M]
	// WithExpand enables eager loading of specified associations.
	WithExpand(expand []string, order ...string) Database[M]
	// WithPurge controls whether Delete permanently removes records instead of soft deleting them.
	WithPurge(...bool) Database[M]
	// WithCache enables cache reads/writes for supported read operations and cache invalidation for writes.
	WithCache(...bool) Database[M]
	// WithOmit excludes specified fields from INSERT, UPDATE, and SELECT operations.
	WithOmit(...string) Database[M]
	// WithBuildSQL builds SQL for the next terminal operation and appends Query, Args, and RenderedSQL to the collector.
	WithBuildSQL(statements *[]SQLStatement) Database[M]
	// WithDryRun builds SQL without database I/O, framework hooks, cache mutation, or object field filling.
	WithDryRun() Database[M]
	// WithoutHook disables model hooks for the operation.
	WithoutHook() Database[M]
}

DatabaseOption provides chainable options for a single Database operation chain. Options apply to the next terminal operation and are reset afterward. Start a new chain with database.Database[M](ctx) for each independent operation.

type DistributedCache

type DistributedCache[T any] interface {
	Cache[T]

	// SetWithSync stores a value in both local and distributed cache with synchronization.
	SetWithSync(key string, value T, localTTL time.Duration, remoteTTL time.Duration) error

	// GetWithSync retrieves a value from local cache first, then from distributed cache if not found.
	GetWithSync(key string, localTTL time.Duration) (T, error)

	// DeleteWithSync removes a value from both local and distributed cache with synchronization.
	DeleteWithSync(key string) error
}

DistributedCache extends Cache with explicit local-plus-remote synchronization helpers.

Type Parameters:

  • T: Cached value type

type ESDocumenter

type ESDocumenter interface {
	// Document returns a map representing an Elasticsearch document.
	// The returned map should contain all fields to be indexed, where:
	//   - keys are field names (string type)
	//   - values are field values (any type)
	//
	// Implementation notes:
	//   1. The returned map should only contain JSON-serializable values.
	//   2. Field names should match those defined in the Elasticsearch mapping.
	//   3. Complex types (like nested objects or arrays) should be correctly
	//      represented in the returned map.
	//
	// Example:
	//   return map[string]any{
	//       "id":    "1234",
	//       "title": "Sample Document",
	//       "tags":  []string{"tag1", "tag2"},
	//   }
	Document() map[string]any

	// GetID returns a string that uniquely identifies the document.
	// This ID is typically used as the Elasticsearch document ID.
	//
	// Implementation notes:
	//   1. The ID should be unique within the index.
	//   2. If no custom ID is needed, consider returning an empty string
	//      to let Elasticsearch auto-generate an ID.
	//   3. The ID should be a string, even if it's originally a numeric value.
	//
	// Example:
	//   return "user_12345"
	GetID() string
}

ESDocumenter represents a document that can be indexed into Elasticsearch. Types implementing this interface should be able to convert themselves into a document format suitable for Elasticsearch indexing.

type Event

type Event = sse.Event

Event is an alias for sse.Event. This allows users to use types.Event instead of importing internal/sse directly.

type Initializer

type Initializer interface {
	Init() error
}

Initializer defines a bootstrap component that performs one-time setup. Implementations should return an error when required configuration, connections, or runtime resources cannot be initialized.

type Logger

type Logger interface {
	With(fields ...string) Logger

	WithObject(name string, obj zapcore.ObjectMarshaler) Logger
	WithArray(name string, arr zapcore.ArrayMarshaler) Logger

	WithContext(context.Context, consts.Phase) Logger

	StandardLogger
	StructuredLogger
	ZapLogger
}

Logger combines plain, sugared structured, and typed zap logging methods. With attaches string key/value fields. WithObject, WithArray, and the context helpers return derived loggers with additional structured fields.

type Model

type Model interface {
	GetTableName() string // GetTableName returns the table name.
	GetID() string
	SetID(id ...string) // SetID method will automatically set the id if id is empty.
	ClearID()           // ClearID always set the id to empty.
	GetCreatedBy() string
	GetUpdatedBy() string
	GetCreatedAt() time.Time
	GetUpdatedAt() time.Time
	SetCreatedBy(string)
	SetUpdatedBy(string)
	SetCreatedAt(time.Time)
	SetUpdatedAt(time.Time)
	Expands() []string // Expands returns association paths that should be preloaded by default.
	Excludes() map[string][]any
	Purge() bool                                  // Purge indicates whether to permanently delete records (hard delete). Default is false (soft delete).
	MarshalLogObject(zapcore.ObjectEncoder) error // MarshalLogObject implements zap.ObjectMarshaler.

	CreateBefore(context.Context) error
	CreateAfter(context.Context) error
	DeleteBefore(context.Context) error
	DeleteAfter(context.Context) error
	UpdateBefore(context.Context) error
	UpdateAfter(context.Context) error
	ListBefore(context.Context) error
	ListAfter(context.Context) error
	GetBefore(context.Context) error
	GetAfter(context.Context) error
}

Model defines the framework contract for database-backed and action models. Typical database resources embed model.Base. Action-only models may use model.Empty or model.Any when they do not represent persistent rows.

Type Requirements:

  • Must be a pointer to struct (e.g., *User)
  • Database resources should expose an ID primary key through GetID/SetID/ClearID
  • Hooks should be idempotent enough to run as part of framework CRUD phases

type Module

type Module[M Model, REQ Request, RSP Response] interface {
	// Service returns the service instance that handles business logic for this module.
	Service() Service[M, REQ, RSP]

	// Route returns the base API path for this module's endpoints.
	Route() string

	// Pub determines whether the API endpoints are public or require authentication.
	Pub() bool

	// Param returns the URL parameter name used for resource identification.
	Param() string
}

Module describes a registered API module: route metadata, auth exposure, resource parameter name, and the service implementation used by controllers.

Type Parameters:

  • M: Model type that implements Model interface
  • REQ: Request type for API operations
  • RSP: Response type for API operations

Features:

  • Automatic route registration
  • Service layer integration
  • Configurable authentication

type QueryConfig

type QueryConfig struct {
	FuzzyMatch   bool   // Enable fuzzy matching (LIKE/REGEXP). Default: false
	AllowEmpty   bool   // Allow empty query conditions. Default: false
	UseOr        bool   // Use OR logic to combine query conditions. Default: false (uses AND)
	RawQuery     string // Raw SQL query string for custom WHERE conditions
	RawQueryArgs []any  // Arguments for the raw SQL query parameters
}

QueryConfig configures the behavior of WithQuery method.

Fields:

  • FuzzyMatch: Enable fuzzy matching (LIKE/REGEXP queries). Default: false (exact match with IN clause)

  • Single value: Uses LIKE pattern (WHERE name LIKE '%value%')

  • Multiple values (comma-separated): Uses REGEXP pattern (WHERE name REGEXP '.*value1.*|.*value2.*')

  • Empty strings in comma-separated values are automatically skipped

  • REGEXP special characters are automatically escaped

  • Note: REGEXP may not be available in all databases (e.g., SQLite requires extension)

  • AllowEmpty: Allow empty query conditions to match all records. Default: false (blocked for safety)

  • When false: Empty queries are blocked (adds WHERE 1 = 0)

  • When true: Empty queries match all records (full table scan)

  • Empty query cases: nil, empty struct, all fields are zero values, all field values are empty strings

  • Critical: Use with caution, especially for Delete operations

  • UseOr: Use OR logic to combine query conditions. Default: false (uses AND logic)

  • When false: Multiple fields use AND logic (WHERE name IN ('John') AND age IN (18))

  • When true: Multiple fields use OR logic (WHERE name IN ('John') OR age IN (18))

  • First condition always uses WHERE, subsequent conditions use OR

  • Works with both exact match and fuzzy match

  • RawQuery: Raw SQL query string for custom WHERE conditions. When provided, model fields are ignored

  • Works even when query is nil

  • Supports parameterized queries with RawQueryArgs

  • Example: "age > ? AND status = ?"

  • RawQueryArgs: Arguments for the raw SQL query, used with RawQuery for parameterized queries

  • Can be nil or empty slice if RawQuery has no placeholders

  • Example: []any{18, "active"}

CRITICAL SAFETY FEATURE: Empty query conditions (all fields are zero values) are blocked by default to prevent catastrophic data loss scenarios, especially when the result is used for Delete operations.

Empty Query Examples:

  • WithQuery(&User{}) → all fields are zero values
  • WithQuery(&User{Name: "", Email: ""}) → all field values are empty strings
  • WithQuery(&KV{Key: ""}) → happens when removed slice is empty

Usage Examples:

// Exact match (default)
WithQuery(&User{Name: "John"})
WithQuery(&User{Name: "John"}, QueryConfig{})

// Exact match with multiple values (comma-separated)
WithQuery(&User{Name: "John,Jack"})  // WHERE name IN ('John', 'Jack')
WithQuery(&User{ID: "id1,id2,id3"})  // WHERE id IN ('id1', 'id2', 'id3')

// Fuzzy match - single value (LIKE)
WithQuery(&User{Name: "John"}, QueryConfig{FuzzyMatch: true})  // WHERE name LIKE '%John%'

// Fuzzy match - multiple values (REGEXP)
WithQuery(&User{Name: "John,Jack"}, QueryConfig{FuzzyMatch: true})  // WHERE name REGEXP '.*John.*|.*Jack.*'

// Allow empty query (ListFactory with pagination)
WithQuery(&User{}, QueryConfig{AllowEmpty: true})  // Returns all records

// Fuzzy match + Allow empty
WithQuery(&User{}, QueryConfig{FuzzyMatch: true, AllowEmpty: true})

// Use OR logic to combine conditions
WithQuery(&User{Name: "John", Email: "john@example.com"}, QueryConfig{UseOr: true})
// WHERE name IN ('John') OR email IN ('john@example.com')

// OR logic with fuzzy match
WithQuery(&User{Name: "John", Email: "example"}, QueryConfig{UseOr: true, FuzzyMatch: true})
// WHERE name LIKE '%John%' OR email LIKE '%example%'

	// Raw SQL query (can be combined with model fields using AND logic)
WithQuery(&User{}, QueryConfig{RawQuery: "age > ? AND status = ?", RawQueryArgs: []any{18, "active"}})
WithQuery(nil, QueryConfig{RawQuery: "created_at BETWEEN ? AND ?", RawQueryArgs: []any{startDate, endDate}})

// Raw SQL with complex conditions
WithQuery(&User{}, QueryConfig{RawQuery: "created_at BETWEEN ? AND ? OR priority IN (?)", RawQueryArgs: []any{startDate, endDate, priorities}})
// Raw SQL combined with model fields
WithQuery(&User{Name: "John"}, QueryConfig{RawQuery: "age > ?", RawQueryArgs: []any{18}})  // WHERE age > ? AND name IN ('John')

// Combined options
WithQuery(&User{Name: "John"}, QueryConfig{
    FuzzyMatch: true,
    UseOr:      true,
    AllowEmpty: false,
})

type RBAC

type RBAC interface {
	// Authorize reports whether subject may perform action on object inside tenant.
	// Implementations should treat tenant as the authorization domain, subject as
	// the authenticated identity, object as the protected route or resource, and
	// action as the operation being checked, such as an HTTP method.
	Authorize(tenant string, subject string, object string, action string) (bool, error)

	// AddRole ensures role is available inside tenant.
	// Casbin-backed implementations may create roles implicitly when policies or
	// grouping rules are added, so this method can be a lifecycle hook with no
	// persistent side effect.
	AddRole(tenant string, role string) error

	// RemoveRole removes role from tenant, including its permission policies and
	// subject assignments. Callers should use this when deleting a role record so
	// authorization state does not retain stale grants.
	RemoveRole(tenant string, role string) error

	// GrantPermission grants role access to action on object inside tenant.
	// This represents one exact allow policy for a tenant-scoped role.
	GrantPermission(tenant string, role string, object string, action string) error

	// RevokePermission removes one exact role permission inside tenant.
	// Use RevokeRolePermissions when replacing or deleting the full permission set
	// for a role.
	RevokePermission(tenant string, role string, object string, action string) error

	// RevokeRolePermissions removes every permission policy granted to role inside
	// tenant without removing the role's subject assignments.
	RevokeRolePermissions(tenant string, role string) error

	// AssignRole assigns subject to role inside tenant.
	// This creates tenant membership for subject and makes the role's
	// tenant-scoped permissions available to that subject.
	AssignRole(tenant string, subject string, role string) error

	// UnassignRole removes subject's assignment to role inside tenant.
	// Other roles held by the same subject in the same tenant are left unchanged.
	UnassignRole(tenant string, subject string, role string) error

	// SubjectInTenant reports whether subject has at least one role assignment in
	// tenant. It checks membership, not whether any specific route is authorized.
	SubjectInTenant(tenant string, subject string) (bool, error)

	// SubjectsInTenant returns subjects with at least one role assignment in
	// tenant. It checks membership, not whether any specific route is authorized.
	SubjectsInTenant(tenant string) ([]string, error)

	// AssignSystemRole assigns subject to a system-level role outside any tenant.
	// System roles are intended for cross-tenant framework privileges and should
	// not be used for ordinary tenant-local authorization.
	AssignSystemRole(subject string, role string) error

	// UnassignSystemRole removes subject's assignment to a system-level role.
	UnassignSystemRole(subject string, role string) error

	// HasSystemRole reports whether subject holds a system-level role.
	// This check is separate from Authorize because system roles are not scoped to
	// tenant route policies.
	HasSystemRole(subject string, role string) (bool, error)
}

RBAC provides tenant-scoped role, permission, and subject assignment operations. When RBAC is disabled or not initialized, the framework may provide a safe no-op implementation whose methods succeed without side effects.

RBAC Model:

  • Tenant: Authorization domain for roles, permissions, and assignments
  • Subject: Users or entities that need access
  • Role: Named collection of permissions
  • Object: Protected resources or endpoints
  • Action: Operations on resources

type Request

type Request any

type Response

type Response any

type SQLStatement

type SQLStatement struct {
	// Query is the parameterized SQL with placeholders.
	Query string
	// Args contains the values bound to Query.
	Args []any
	// RenderedSQL is dialect-rendered SQL for logging, inspection, and manual debugging.
	RenderedSQL string
}

SQLStatement contains a generated SQL statement in executable and rendered forms.

type SSEBuilder

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

SSEBuilder provides a fluent interface for building and sending SSE events. It supports chaining methods to configure and send SSE events or streams.

func (*SSEBuilder) Done

func (b *SSEBuilder) Done() error

Done sends a [DONE] marker to indicate the end of an SSE stream. This is commonly used in AI chat completions and similar streaming APIs.

Note: This method should be called AFTER Stream() returns, if your protocol requires a [DONE] marker. Standard SSE streams do not require this marker and will naturally end when the connection closes.

Example:

ctx.SSE().Stream(func(w io.Writer) bool {
    // Send data...
    return true
})
// Send [DONE] marker to indicate stream completion
_ = ctx.SSE().Done()

Returns:

  • error: Any error that occurred during encoding

func (*SSEBuilder) Stream

func (b *SSEBuilder) Stream(fn func(io.Writer) bool)

Stream starts a Server-Sent Events stream. The provided function will be called repeatedly until it returns false. The stream will automatically stop if:

  • The function returns false
  • The request context is canceled (timeout, client disconnect, etc.)
  • An error occurs while writing to the client

Note: This method does NOT automatically send a [DONE] marker when the stream ends. If your protocol requires a [DONE] marker (e.g., AI chat completions), you must manually call Done() after Stream() returns.

Example:

ctx.SSE().Stream(func(w io.Writer) bool {
    _ = ctx.Encode(w, types.Event{Data: "chunk"})
    return true // Continue streaming
})
// Send [DONE] marker if required by your protocol
_ = ctx.SSE().Done()

func (*SSEBuilder) WithInterval

func (b *SSEBuilder) WithInterval(duration time.Duration) *SSEBuilder

WithInterval sets the time interval between events in a stream. This must be called before Stream() when using interval-based streaming.

Example:

ctx.SSE().WithInterval(1*time.Second).Stream(func(w io.Writer) bool {
    _ = ctx.Encode(w, types.Event{Data: "chunk"})
    return true
})

type Service

type Service[M Model, REQ Request, RSP Response] interface {
	Create(*ServiceContext, REQ) (RSP, error)
	Delete(*ServiceContext, REQ) (RSP, error)
	Update(*ServiceContext, REQ) (RSP, error)
	Patch(*ServiceContext, REQ) (RSP, error)
	List(*ServiceContext, REQ) (RSP, error)
	Get(*ServiceContext, REQ) (RSP, error)

	CreateMany(*ServiceContext, REQ) (RSP, error)
	DeleteMany(*ServiceContext, REQ) (RSP, error)
	UpdateMany(*ServiceContext, REQ) (RSP, error)
	PatchMany(*ServiceContext, REQ) (RSP, error)

	CreateBefore(*ServiceContext, M) error
	CreateAfter(*ServiceContext, M) error
	DeleteBefore(*ServiceContext, M) error
	DeleteAfter(*ServiceContext, M) error
	UpdateBefore(*ServiceContext, M) error
	UpdateAfter(*ServiceContext, M) error
	PatchBefore(*ServiceContext, M) error
	PatchAfter(*ServiceContext, M) error
	ListBefore(*ServiceContext, *[]M) error
	ListAfter(*ServiceContext, *[]M) error
	GetBefore(*ServiceContext, M) error
	GetAfter(*ServiceContext, M) error

	CreateManyBefore(*ServiceContext, ...M) error
	CreateManyAfter(*ServiceContext, ...M) error
	DeleteManyBefore(*ServiceContext, ...M) error
	DeleteManyAfter(*ServiceContext, ...M) error
	UpdateManyBefore(*ServiceContext, ...M) error
	UpdateManyAfter(*ServiceContext, ...M) error
	PatchManyBefore(*ServiceContext, ...M) error
	PatchManyAfter(*ServiceContext, ...M) error

	Import(*ServiceContext, io.Reader) ([]M, error)
	Export(*ServiceContext, ...M) ([]byte, error)

	Filter(*ServiceContext, M) M
	FilterRaw(*ServiceContext) string

	Logger
}

Service defines the controller-facing business operation contract for a model. Generated controllers call these methods for CRUD, batch CRUD, lifecycle hooks, import/export, filtering, and logging.

Type Parameters:

  • M: Model type that implements Model interface
  • REQ: Request type for the current action or resource operation
  • RSP: Response type for the current action or resource operation

Custom actions should use action-specific REQ/RSP types instead of reusing types from other endpoints, even when the fields are identical.

type ServiceContext

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

func NewServiceContext

func NewServiceContext(c *gin.Context, ctx context.Context, phase consts.Phase) *ServiceContext

NewServiceContext creates ServiceContext from gin.Context. Including request details, headers, phase, and user information.

You can pass a custom context.Context to propagate span tracing. If ctx is nil, the request context is used when available.

func (*ServiceContext) ClientIP

func (sc *ServiceContext) ClientIP() string

func (*ServiceContext) Cookie

func (sc *ServiceContext) Cookie(name string) (string, error)

func (*ServiceContext) Data

func (sc *ServiceContext) Data(code int, contentType string, data []byte)

func (*ServiceContext) Deadline

func (sc *ServiceContext) Deadline() (time.Time, bool)

func (*ServiceContext) Done

func (sc *ServiceContext) Done() <-chan struct{}

func (*ServiceContext) Encode

func (sc *ServiceContext) Encode(w io.Writer, event Event) error

Encode writes an SSE event to the given writer. This is a convenience method that wraps sse.Encode.

The event is formatted according to the SSE specification:

  • Fields are written in recommended order: id, event, retry, data
  • Each field is written as "field: value\n"
  • Multiple data fields are concatenated (for multi-line data)
  • Events are separated by a blank line (\n\n)

If Data is a complex type (map, struct, slice), it will be JSON-encoded. If Data is a primitive type, it will be converted to string. If Data is nil, no data field will be written.

Example:

err := ctx.Encode(w, types.Event{
	Event: "message",
	Data:  "Hello",
})

Parameters:

  • w: Writer to write the event to
  • event: SSE event to encode

Returns:

  • error: Any error that occurred during encoding

func (*ServiceContext) Err

func (sc *ServiceContext) Err() error

func (*ServiceContext) FormFile

func (sc *ServiceContext) FormFile(name string) (*multipart.FileHeader, error)

func (*ServiceContext) Host

func (sc *ServiceContext) Host() string

func (*ServiceContext) IsHTTPS

func (sc *ServiceContext) IsHTTPS() bool

func (*ServiceContext) Method

func (sc *ServiceContext) Method() string

func (*ServiceContext) Param

func (sc *ServiceContext) Param(key string) string

func (*ServiceContext) Params

func (sc *ServiceContext) Params() map[string]string

func (*ServiceContext) Path

func (sc *ServiceContext) Path() string

func (*ServiceContext) Phase

func (sc *ServiceContext) Phase() consts.Phase

func (*ServiceContext) PostForm

func (sc *ServiceContext) PostForm(key string) string

func (*ServiceContext) Query

func (sc *ServiceContext) Query() url.Values

func (*ServiceContext) RequiresAuth

func (sc *ServiceContext) RequiresAuth() bool

RequiresAuth returns whether the current API requires authentication.

func (*ServiceContext) Route

func (sc *ServiceContext) Route() string

func (*ServiceContext) SSE

func (sc *ServiceContext) SSE() *SSEBuilder

SSE returns a new SSE builder for chaining SSE operations. This provides a fluent interface for sending SSE events and streams.

Example usage:

// Start a stream
ctx.SSE().Stream(func(w io.Writer) bool {
    _ = ctx.Encode(w, types.Event{Data: "chunk"})
    return true
})

// Stream with interval
ctx.SSE().WithInterval(1*time.Second).Stream(func(w io.Writer) bool {
    _ = ctx.Encode(w, types.Event{Data: "chunk"})
    return true
})

// Send [DONE] marker
_ = ctx.SSE().Done()
Example (CompleteFlow)

ExampleServiceContext_SSE_completeFlow demonstrates a complete SSE flow using the chainable API. This pattern is commonly used in AI chat completions and similar streaming APIs.

package main

import (
	"io"

	"github.com/hydroan/gst/types"
)

func main() {
	var sc *types.ServiceContext

	// Stream data chunks using the chainable API
	sc.SSE().Stream(func(w io.Writer) bool {
		// Send chat completion chunks
		_ = sc.Encode(w, types.Event{
			Data: map[string]any{
				"content": "Hello",
			},
		})
		// Continue streaming...
		return true
	})

	// Send [DONE] marker to indicate stream completion
	// This is required by protocols like OpenAI's chat completion API
	_ = sc.SSE().Done()
}
Example (Done)

ExampleServiceContext_SSE_done demonstrates using the chainable API to send a [DONE] marker.

package main

import (
	"github.com/hydroan/gst/types"
)

func main() {
	var sc *types.ServiceContext

	// Send [DONE] marker using the chainable API
	_ = sc.SSE().Done()
}
Example (Stream)

ExampleServiceContext_SSE_stream demonstrates using the chainable API for streaming.

package main

import (
	"io"
	"time"

	"github.com/hydroan/gst/types"
)

func main() {
	var sc *types.ServiceContext

	// Stream events using the chainable API
	sc.SSE().Stream(func(w io.Writer) bool {
		_ = sc.Encode(w, types.Event{
			Event: "message",
			Data:  time.Now().String(),
		})
		return true
	})
}
Example (StreamWithInterval)

ExampleServiceContext_SSE_streamWithInterval demonstrates using the chainable API for interval-based streaming.

package main

import (
	"fmt"
	"io"
	"time"

	"github.com/hydroan/gst/types"
)

func main() {
	var sc *types.ServiceContext

	// Stream with interval using the chainable API
	counter := 0
	sc.SSE().WithInterval(1 * time.Second).Stream(func(w io.Writer) bool {
		counter++

		// Send event
		_ = sc.Encode(w, types.Event{
			ID:    fmt.Sprintf("event-%d", counter),
			Event: "message",
			Data: map[string]any{
				"number":  counter,
				"message": fmt.Sprintf("Event %d of 3", counter),
			},
		})

		// Return true to continue (will wait 1 second), false to stop
		// This will send 3 events: at 0s, 1s, 2s, then stop
		return counter < 3
	})

	// Send [DONE] marker if required by your protocol
	_ = sc.SSE().Done()
}

func (*ServiceContext) SessionID

func (sc *ServiceContext) SessionID() string

func (*ServiceContext) SetCookie

func (sc *ServiceContext) SetCookie(cookie *http.Cookie)

func (*ServiceContext) TenantID

func (sc *ServiceContext) TenantID() string

func (*ServiceContext) TraceID

func (sc *ServiceContext) TraceID() string

func (*ServiceContext) UserAgent

func (sc *ServiceContext) UserAgent() string

func (*ServiceContext) UserID

func (sc *ServiceContext) UserID() string

func (*ServiceContext) Username

func (sc *ServiceContext) Username() string

func (*ServiceContext) Value

func (sc *ServiceContext) Value(key any) any

type StandardLogger

type StandardLogger interface {
	Debug(args ...any)
	Info(args ...any)
	Warn(args ...any)
	Error(args ...any)
	Fatal(args ...any)

	Debugf(format string, args ...any)
	Infof(format string, args ...any)
	Warnf(format string, args ...any)
	Errorf(format string, args ...any)
	Fatalf(format string, args ...any)
}

StandardLogger provides plain and printf-style leveled logging methods. Fatal and Fatalf follow the underlying logger's fatal behavior and should terminate the process after writing the log entry.

type StructuredLogger

type StructuredLogger interface {
	Debugw(msg string, keysAndValues ...any)
	Infow(msg string, keysAndValues ...any)
	Warnw(msg string, keysAndValues ...any)
	Errorw(msg string, keysAndValues ...any)
	Fatalw(msg string, keysAndValues ...any)
}

StructuredLogger provides sugared structured logging with alternating key/value fields. Methods with suffix "w" mean "with fields".

type ZapLogger

type ZapLogger interface {
	Debugz(msg string, fields ...zap.Field)
	Infoz(msg string, fields ...zap.Field)
	Warnz(msg string, fields ...zap.Field)
	Errorz(msg string, fields ...zap.Field)
	Fatalz(msg string, fields ...zap.Field)
}

ZapLogger provides structured logging with typed zap.Field values. Methods with suffix "z" are the low-allocation typed-field variants.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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