datatable

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 47 Imported by: 0

Documentation

Overview

Package datatable binds typed report projections to declared client filters, authorization, deterministic pages and bounded CSV/XLSX exports.

Index

Constants

View Source
const (
	MaxRequestBytes = 64 << 10
	MaxColumns      = 128
	MaxFilters      = 128
	MaxFilterDepth  = 8
	MaxFilterValues = 100
	MaxScalarBytes  = 4096
	MaxSorts        = 8
	DefaultPageSize = 20
)

Variables

This section is empty.

Functions

func DirectionCodec

func DirectionCodec() codec.Codec[Direction]

DirectionCodec applies the generated membership rule at both SQL boundaries.

func ExportFormatCodec

func ExportFormatCodec() codec.Codec[ExportFormat]

ExportFormatCodec applies the generated membership rule at both SQL boundaries.

func ExportHandler

func ExportHandler[P, S, R, A any](table Table[S, R, A], manager *Manager, resolve func(context.Context, P) (A, Request, ExportOptions, error), deliver func(context.Context, P, *Artifact) error) (jobs.Handler[P], error)

ExportHandler adapts a table to an ordinary typed job definition. Resolve reconstructs CURRENT server authority from its persisted payload; it must not trust captured role/permission claims or turn a client model ID into authority. The handler always runs the table's Export authorization and row scope again. Reuse auth.Provider.Resolve for fresh eligibility, then apply current policy.

Deliver receives only a complete artifact, after its database snapshot closes and its generation slot is released. The handler owns and closes it even when delivery fails, panics or Goexits. Its context retains job values and the export's deadline, ends at manager shutdown, and rejects closing the same manager from inside delivery as a cycle. Jobs remain at-least-once: use jobs.Current's execution ID for an idempotent destination. Locale/timezone/actor references belong in P's existing job contract; this adapter creates neither another queue nor implicit email sends.

func ExportOptionsJSON

func ExportOptionsJSON() foundrycontract.JSON[ExportOptions]

ExportOptionsJSON describes the concrete ExportOptions JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs.

func FilterJSON

func FilterJSON() foundrycontract.JSON[Filter]

FilterJSON describes the concrete Filter JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs.

func Module

func Module(name foundation.ProviderID, key foundation.Key[*Manager], requires []foundation.ProviderID, construct func(foundation.Resolver) (*Manager, error)) foundation.Module

Module retains borrowed providers until query and export-generation callbacks actually exit. Completed artifacts use no borrowed provider: shutdown closes any still open instead of waiting for their owners, so the remaining wait is bounded by callbacks honoring cancellation. Export workers must declare this module as their dependency so their deliveries finish first.

func OperatorCodec

func OperatorCodec() codec.Codec[Operator]

OperatorCodec applies the generated membership rule at both SQL boundaries.

func PresentationJSON

func PresentationJSON() foundrycontract.JSON[Presentation]

PresentationJSON describes the concrete Presentation JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs.

func RequestJSON

func RequestJSON() foundrycontract.JSON[Request]

RequestJSON describes the concrete Request JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs.

func SortJSON

func SortJSON() foundrycontract.JSON[Sort]

SortJSON describes the concrete Sort JSON boundary. Reuse this immutable descriptor for decoding and client contract export. Fields are discovered from Go declarations; persistence models are not response DTOs.

Types

type Action

type Action string
const (
	QueryAction   Action = "query"
	ExportAction  Action = "export"
	InspectAction Action = "inspect"
)

type Artifact

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

Artifact owns one complete private file. Close is mandatory and idempotent; it closes and removes the file and releases its retention slot. Export generation capacity was already released when the file was completed, so a slow download or delivery never blocks other exports from generating. Failed removals remain owned by the manager and block new exports until cleanup succeeds; Close, the next export and manager shutdown retry removal. The path is not public. Manager shutdown closes artifacts that are still open. Reads, seeks and close are serialized; callers must not copy an Artifact.

func (*Artifact) Close

func (a *Artifact) Close() error

func (*Artifact) EntityTag

func (a *Artifact) EntityTag() foundryhttp.EntityTag

EntityTag is the strong HTTP validator of the exact artifact bytes. Each download regenerates the report, so If-Range/If-None-Match compare content: a range resume against a different run receives the complete new file.

func (*Artifact) MediaType

func (a *Artifact) MediaType() foundryhttp.MediaType

func (*Artifact) Modified

func (a *Artifact) Modified() time.Time

Modified is the UTC time the artifact was completed.

func (*Artifact) Name

func (a *Artifact) Name() string

func (*Artifact) Read

func (a *Artifact) Read(p []byte) (int, error)

func (*Artifact) Rows

func (a *Artifact) Rows() int

func (*Artifact) SHA256

func (a *Artifact) SHA256() string

func (*Artifact) Seek

func (a *Artifact) Seek(offset int64, whence int) (int64, error)

func (*Artifact) Size

func (a *Artifact) Size() int64

type Cell

type Cell[V any] struct {
	// contains filtered or unexported fields
}

Cell preserves the exact DTO field type through export formatting. Ordinary scalar cells reuse transport codecs; nullable cells render SQL NULL as empty. The table's JSON graph remains authoritative for public field metadata. XLSX writes scalar integer, float, decimal, boolean, date and date-time cells as typed spreadsheet values when the codec text is exactly representable; FormatWith output is always text.

func NullableCell

func NullableCell[V any](codec foundryhttp.QueryCodec[V]) Cell[value.Nullable[V]]

func ScalarCell

func ScalarCell[V any](codec foundryhttp.QueryCodec[V]) Cell[V]

func (Cell[V]) FormatWith

func (c Cell[V]) FormatWith(format func(context.Context, V, Presentation) (string, error)) Cell[V]

FormatWith explicitly customizes human presentation without replacing the field's JSON or filter contract. It must be concurrency-safe and bounded. Custom presentation is exported as text in every format.

type Column

type Column[S, R, V any] struct {
	// contains filtered or unexported fields
}

Column retains SQL scope S, response row R and exact field value V. Names and getters come from generated validation fields, not a duplicate string map.

func DefineColumn

func DefineColumn[S, R, V any](field validation.Field[R, V], label i18n.MessageKey) Column[S, R, V]

func (Column[S, R, V]) ExportAs

func (c Column[S, R, V]) ExportAs(cell Cell[V]) Column[S, R, V]

func (Column[S, R, V]) FilterBy

func (c Column[S, R, V]) FilterBy(source FilterSource[S, V]) Column[S, R, V]

func (Column[S, R, V]) Registration

func (c Column[S, R, V]) Registration() ColumnRegistration[S, R]

func (Column[S, R, V]) Searchable

func (c Column[S, R, V]) Searchable() Column[S, R, V]

func (Column[S, R, V]) SortBy

func (c Column[S, R, V]) SortBy(expression expr.Selected[S, V]) Column[S, R, V]

SortBy binds a selected value of the same scope and DTO field type. Example: column.SortBy(expr.Row(expr.Value(Users.Name)).Value()).

type ColumnInfo

type ColumnInfo struct {
	Name           string                  `json:"name"`
	Label          i18n.MessageKey         `json:"label"`
	Value          contract.ScalarProperty `json:"value"`
	Sortable       bool                    `json:"sortable"`
	Searchable     bool                    `json:"searchable"`
	SearchOperator Operator                `json:"search_operator,omitempty"`
	Exportable     bool                    `json:"exportable"`
	Filter         *FilterInfo             `json:"filter,omitempty"`
}

type ColumnRegistration

type ColumnRegistration[S, R any] struct {
	// contains filtered or unexported fields
}

ColumnRegistration erases V only after ownership-safe declaration. Columns from a different source scope or response row cannot be registered together.

type Config

type Config struct {
	// TimeZone is the default export presentation zone. Empty means UTC for a
	// direct manager, or inherits the application timezone during assembly.
	TimeZone     temporal.ZoneName
	Schema       string
	MaxActive    int
	Timeout      time.Duration
	MaxPageSize  int
	MaxOffset    int
	MaxRowBytes  int
	MaxPageBytes int
	// MaxExports bounds concurrent export generation (query, formatting and
	// file writing). A slot is released once the artifact is complete.
	MaxExports int
	// MaxArtifacts bounds completed artifacts still open for delivery, and so
	// the private temporary files held on disk. It is at least MaxExports.
	MaxArtifacts   int
	ExportTimeout  time.Duration
	MaxExportRows  int
	MaxExportBytes int64
	MaxXMLBytes    int64
	MaxCellBytes   int
	TempDir        string
}

func DefaultConfig

func DefaultConfig() Config

func (Config) Validate

func (c Config) Validate() error

type Dependencies

type Dependencies struct {
	Database *database.DB
	Locales  i18n.LocaleCatalog
	Labels   Labels
}

type Description

type Description struct {
	ID          TableID           `json:"id"`
	Row         contract.Schema   `json:"row"`
	Request     contract.Schema   `json:"request"`
	Columns     []ColumnInfo      `json:"columns"`
	Filters     []NamedFilterInfo `json:"filters,omitempty"`
	DefaultSort []Sort            `json:"default_sort,omitempty"`
	Exports     bool              `json:"exports"`
}

Description is the table contribution to the shared client manifest. Row and Request schemas originate from their typed contracts. No second TS schema is inferred from SQL, model fields, column names or arbitrary reflection.

func (Description) Normalize

func (d Description) Normalize() (Description, error)

Normalize validates serialized client metadata against its actual row graph. It reuses scalar/filter agreement and sorting rules without constructing SQL expressions, invoking authorization or claiming an executable table binding.

type Direction

type Direction string
const (
	Ascending  Direction = "asc"
	Descending Direction = "desc"
)

func DirectionValues

func DirectionValues() []Direction

DirectionValues returns declared values in source order, with independent slice ownership.

func ParseDirection

func ParseDirection(text string) (Direction, error)

ParseDirection decodes and validates an enum's text representation.

func (Direction) EnumDescriptor

func (Direction) EnumDescriptor() enum.Descriptor[Direction]

EnumDescriptor describes this enum type independently of the receiver's value.

func (Direction) IsValid

func (v Direction) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (Direction) MarshalJSON

func (v Direction) MarshalJSON() ([]byte, error)

func (Direction) MarshalText

func (v Direction) MarshalText() ([]byte, error)

func (*Direction) Scan

func (v *Direction) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*Direction) UnmarshalJSON

func (v *Direction) UnmarshalJSON(data []byte) error

func (*Direction) UnmarshalText

func (v *Direction) UnmarshalText(data []byte) error

func (Direction) Validate

func (v Direction) Validate() error

Validate reports invalid values without formatting the input.

func (Direction) Value

func (v Direction) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer through the shared typed codec.

type ExportFormat

type ExportFormat string
const (
	CSV  ExportFormat = "csv"
	XLSX ExportFormat = "xlsx"
)

func ExportFormatValues

func ExportFormatValues() []ExportFormat

ExportFormatValues returns declared values in source order, with independent slice ownership.

func ParseExportFormat

func ParseExportFormat(text string) (ExportFormat, error)

ParseExportFormat decodes and validates an enum's text representation.

func (ExportFormat) EnumDescriptor

func (ExportFormat) EnumDescriptor() enum.Descriptor[ExportFormat]

EnumDescriptor describes this enum type independently of the receiver's value.

func (ExportFormat) IsValid

func (v ExportFormat) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (ExportFormat) MarshalJSON

func (v ExportFormat) MarshalJSON() ([]byte, error)

func (ExportFormat) MarshalText

func (v ExportFormat) MarshalText() ([]byte, error)

func (*ExportFormat) Scan

func (v *ExportFormat) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*ExportFormat) UnmarshalJSON

func (v *ExportFormat) UnmarshalJSON(data []byte) error

func (*ExportFormat) UnmarshalText

func (v *ExportFormat) UnmarshalText(data []byte) error

func (ExportFormat) Validate

func (v ExportFormat) Validate() error

Validate reports invalid values without formatting the input.

func (ExportFormat) Value

func (v ExportFormat) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer through the shared typed codec.

type ExportOptions

type ExportOptions struct {
	Format       ExportFormat `json:"format"`
	Name         string       `json:"name,omitempty"`
	Presentation Presentation `json:"presentation"`
	// ByteOrderMark prefixes CSV with a UTF-8 byte-order mark so spreadsheet
	// programs that guess legacy encodings open non-ASCII text correctly. It
	// is rejected for XLSX, whose XML declares its encoding.
	ByteOrderMark bool `json:"byte_order_mark,omitempty"`
}

type ExportOptionsValidationFieldSet

type ExportOptionsValidationFieldSet struct {
	// ByteOrderMark validates the declared JSON property "byte_order_mark".
	//
	// ByteOrderMark prefixes CSV with a UTF-8 byte-order mark so spreadsheet
	// programs that guess legacy encodings open non-ASCII text correctly. It
	// is rejected for XLSX, whose XML declares its encoding.
	//
	ByteOrderMark foundryvalidation.Field[ExportOptions, bool]
	// Format validates the declared JSON property "format".
	Format foundryvalidation.Field[ExportOptions, ExportFormat]
	// Name validates the declared JSON property "name".
	Name foundryvalidation.Field[ExportOptions, string]
	// Presentation validates the declared JSON property "presentation".
	Presentation foundryvalidation.Field[ExportOptions, Presentation]
}

ExportOptionsValidationFieldSet retains concrete DTO and value types for validation.

func ExportOptionsValidationFields

func ExportOptionsValidationFields() ExportOptionsValidationFieldSet

ExportOptionsValidationFields returns typed field descriptors. Compose rules with these fields; JSON names and selectors are generated.

type Filter

type Filter struct {
	Op       Operator `json:"op"`
	Column   string   `json:"column,omitempty"`
	Values   []string `json:"values,omitempty"`
	Children []Filter `json:"children,omitempty"`
}

Filter is either one declared column/operator with scalar text values, or an AND/OR/NOT group with children. Groups cannot carry a column or values. Scalar text is parsed by the column's exact codec; it never becomes a SQL identifier.

type FilterInfo

type FilterInfo struct {
	Phase     FilterPhase               `json:"phase"`
	Scalar    foundryhttp.URLScalarInfo `json:"scalar"`
	Nullable  bool                      `json:"nullable"`
	Operators []Operator                `json:"operators"`
}

FilterInfo describes the exact scalar codec and supported operations. The declaration's owner/value types are erased only for inspection metadata.

type FilterPhase

type FilterPhase string
const (
	WherePhase  FilterPhase = "where"
	HavingPhase FilterPhase = "having"
)

type FilterRegistration

type FilterRegistration[S any] struct {
	// contains filtered or unexported fields
}

func DefineFilter

func DefineFilter[S, V any](name string, label i18n.MessageKey, source FilterSource[S, V]) FilterRegistration[S]

DefineFilter declares an extra server filter (for example a related model's name) independently of displayed DTO columns. It shares the strict allowlist.

type FilterSource

type FilterSource[S, V any] struct {
	// contains filtered or unexported fields
}

FilterSource retains both SQL scope and column value, including nullability. Construct with Where/Having or their nullable counterparts. Constructors infer supported comparisons from the supplied typed field/expression. The SQL pattern operator `like` is discovered but disabled until AllowLike.

func Having

func Having[S, V any](codec foundryhttp.QueryCodec[V], source GroupEquality[S, V]) FilterSource[S, V]

func NullableHaving

func NullableHaving[S, V any](codec foundryhttp.QueryCodec[V], source GroupNullable[S, V]) FilterSource[S, value.Nullable[V]]

func NullableWhere

func NullableWhere[S, V any](codec foundryhttp.QueryCodec[V], source RowNullable[S, V]) FilterSource[S, value.Nullable[V]]
func Related[S, C, V any](source FilterSource[C, V], exists func(expr.Predicate[C]) expr.Predicate[S]) FilterSource[S, V]

Related lifts a declared child filter through a typed relation predicate, such as child.Where(predicate).Exists(). It cannot lift HAVING into a row filter. The callback is server-owned; the table operation owns its isolation/lifetime. The lifted comparison is never unknown, so its negation is NOT EXISTS.

func Where

func Where[S, V any](codec foundryhttp.QueryCodec[V], source RowEquality[S, V]) FilterSource[S, V]

func (FilterSource[S, V]) AllowLike

func (s FilterSource[S, V]) AllowLike() FilterSource[S, V]

AllowLike explicitly enables `like`, whose value is a SQL LIKE pattern: `%` and `_` are wildcards chosen by the client. It is off by default because a client pattern can defeat indexes. `contains`/`icontains` keep literal text.

func (FilterSource[S, V]) Description

func (s FilterSource[S, V]) Description() (FilterInfo, error)

func (FilterSource[S, V]) Restrict

func (s FilterSource[S, V]) Restrict(operators ...Operator) FilterSource[S, V]

Restrict narrows the enabled comparison allowlist without changing codecs. Call AllowLike first when the restricted set includes `like`.

func (FilterSource[S, V]) Validate

func (s FilterSource[S, V]) Validate() error

type FilterValidationFieldSet

type FilterValidationFieldSet struct {
	// Children validates the declared JSON property "children".
	Children foundryvalidation.Field[Filter, []Filter]
	// Column validates the declared JSON property "column".
	Column foundryvalidation.Field[Filter, string]
	// Op validates the declared JSON property "op".
	Op foundryvalidation.Field[Filter, Operator]
	// Values validates the declared JSON property "values".
	Values foundryvalidation.Field[Filter, []string]
}

FilterValidationFieldSet retains concrete DTO and value types for validation.

func FilterValidationFields

func FilterValidationFields() FilterValidationFieldSet

FilterValidationFields returns typed field descriptors. Compose rules with these fields; JSON names and selectors are generated.

type GroupEquality

type GroupEquality[S, V any] interface {
	Eq(V) expr.HavingPredicate[S]
	Ne(V) expr.HavingPredicate[S]
	In(...V) expr.HavingPredicate[S]
}

type GroupNullable

type GroupNullable[S, V any] interface {
	GroupEquality[S, V]
	IsNull() expr.HavingPredicate[S]
	IsNotNull() expr.HavingPredicate[S]
}

type Labels

Labels resolves UI message keys for export headings. Catalogs are borrowed; it must be concurrency-safe, honor cancellation and return bounded text.

type Manager

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

Manager owns bounded query/export lifetimes, but borrows its database and locale/label dependencies. Construction performs no I/O and starts no worker. Export generation holds an export slot until its artifact is complete; the artifact then holds only a retention slot and its private file until Close.

func New

func New(dependencies Dependencies, config Config, registrations ...Registration) (*Manager, error)

func (*Manager) Close

func (m *Manager) Close(ctx context.Context) error

Close stops admission, cancels active queries and export generation, and closes every completed artifact that is still open: their readers observe fault.Closed and their private files are removed. Completed artifacts use no borrowed dependency, so shutdown never waits for their owners. The context bounds only the caller's wait for callbacks that are still running.

func (*Manager) DoneExports

func (m *Manager) DoneExports() <-chan struct{}

func (*Manager) DoneQueries

func (m *Manager) DoneQueries() <-chan struct{}

DoneQueries and DoneExports expose actual resource exit separately, without a joining background goroutine. Module shutdown waits for both.

func (*Manager) DownloadTimeout

func (m *Manager) DownloadTimeout() time.Duration

DownloadTimeout reports the download route deadline for this manager's configuration, capped at the HTTP route maximum.

func (*Manager) Registry

func (m *Manager) Registry() *Registry

func (*Manager) Validate

func (m *Manager) Validate() error

type NamedFilterInfo

type NamedFilterInfo struct {
	Name   string          `json:"name"`
	Label  i18n.MessageKey `json:"label"`
	Filter FilterInfo      `json:"filter"`
}

type Operator

type Operator string
const (
	Equal               Operator = "eq"
	NotEqual            Operator = "ne"
	In                  Operator = "in"
	NotIn               Operator = "not_in"
	Less                Operator = "lt"
	LessEqual           Operator = "lte"
	Greater             Operator = "gt"
	GreaterEqual        Operator = "gte"
	Between             Operator = "between"
	Contains            Operator = "contains"
	InsensitiveContains Operator = "icontains"
	Like                Operator = "like"
	IsNull              Operator = "is_null"
	IsNotNull           Operator = "is_not_null"
	All                 Operator = "and"
	Any                 Operator = "or"
	Not                 Operator = "not"
)

func OperatorValues

func OperatorValues() []Operator

OperatorValues returns declared values in source order, with independent slice ownership.

func ParseOperator

func ParseOperator(text string) (Operator, error)

ParseOperator decodes and validates an enum's text representation.

func (Operator) EnumDescriptor

func (Operator) EnumDescriptor() enum.Descriptor[Operator]

EnumDescriptor describes this enum type independently of the receiver's value.

func (Operator) IsValid

func (v Operator) IsValid() bool

IsValid checks membership; a Go cast alone does not validate external values.

func (Operator) MarshalJSON

func (v Operator) MarshalJSON() ([]byte, error)

func (Operator) MarshalText

func (v Operator) MarshalText() ([]byte, error)

func (*Operator) Scan

func (v *Operator) Scan(source any) error

Scan changes the receiver only after successful decoding. SQL NULL is rejected.

func (*Operator) UnmarshalJSON

func (v *Operator) UnmarshalJSON(data []byte) error

func (*Operator) UnmarshalText

func (v *Operator) UnmarshalText(data []byte) error

func (Operator) Validate

func (v Operator) Validate() error

Validate reports invalid values without formatting the input.

func (Operator) Value

func (v Operator) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer through the shared typed codec.

type Presentation

type Presentation struct {
	Locale   i18n.LocaleID `json:"locale"`
	TimeZone string        `json:"time_zone"`
}

Presentation is explicit, serializable export context, suitable for an ordinary typed job payload. It never consults process-global request state.

func (Presentation) Location

func (p Presentation) Location() (*time.Location, error)

type PresentationValidationFieldSet

type PresentationValidationFieldSet struct {
	// Locale validates the declared JSON property "locale".
	Locale foundryvalidation.Field[Presentation, i18n.LocaleID]
	// TimeZone validates the declared JSON property "time_zone".
	TimeZone foundryvalidation.Field[Presentation, string]
}

PresentationValidationFieldSet retains concrete DTO and value types for validation.

func PresentationValidationFields

func PresentationValidationFields() PresentationValidationFieldSet

PresentationValidationFields returns typed field descriptors. Compose rules with these fields; JSON names and selectors are generated.

type Registration

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

type Registry

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

func NewRegistry

func NewRegistry(registrations ...Registration) (*Registry, error)

func (*Registry) Descriptions

func (r *Registry) Descriptions() ([]Description, error)

func (*Registry) Validate

func (r *Registry) Validate() error

type Request

type Request struct {
	Page    int      `json:"page,omitempty"`
	Size    int      `json:"size,omitempty"`
	Sort    []Sort   `json:"sort,omitempty"`
	Filters []Filter `json:"filters,omitempty"`
	Search  string   `json:"search,omitempty"`
}

Request defaults omitted/zero Page and Size to 1 and 20. Everything else is explicit: unknown names, unsupported operators and invalid values are errors. Direct Go callers retain input ownership until the operation returns.

func DecodeRequest

func DecodeRequest(ctx context.Context, data []byte) (Request, error)

DecodeRequest rejects unknown/duplicate JSON keys, invalid Unicode, incorrect scalar representations and documents exceeding the shared bounded decoder. Table validation then checks the declaration-specific allowlist before SQL. Rejected input matches http.BadRequest and retains *contract.DecodeError for internal diagnostics. Cancellation and decoder infrastructure faults are not client rejection.

type RequestValidationFieldSet

type RequestValidationFieldSet struct {
	// Filters validates the declared JSON property "filters".
	Filters foundryvalidation.Field[Request, []Filter]
	// Page validates the declared JSON property "page".
	Page foundryvalidation.Field[Request, int]
	// Search validates the declared JSON property "search".
	Search foundryvalidation.Field[Request, string]
	// Size validates the declared JSON property "size".
	Size foundryvalidation.Field[Request, int]
	// Sort validates the declared JSON property "sort".
	Sort foundryvalidation.Field[Request, []Sort]
}

RequestValidationFieldSet retains concrete DTO and value types for validation.

func RequestValidationFields

func RequestValidationFields() RequestValidationFieldSet

RequestValidationFields returns typed field descriptors. Compose rules with these fields; JSON names and selectors are generated.

type RowEquality

type RowEquality[S, V any] interface {
	Eq(V) expr.Predicate[S]
	Ne(V) expr.Predicate[S]
	In(...V) expr.Predicate[S]
}

type RowNullable

type RowNullable[S, V any] interface {
	RowEquality[S, V]
	IsNull() expr.Predicate[S]
	IsNotNull() expr.Predicate[S]
}

type Sort

type Sort struct {
	Column    string    `json:"column"`
	Direction Direction `json:"direction"`
}

type SortValidationFieldSet

type SortValidationFieldSet struct {
	// Column validates the declared JSON property "column".
	Column foundryvalidation.Field[Sort, string]
	// Direction validates the declared JSON property "direction".
	Direction foundryvalidation.Field[Sort, Direction]
}

SortValidationFieldSet retains concrete DTO and value types for validation.

func SortValidationFields

func SortValidationFields() SortValidationFieldSet

SortValidationFields returns typed field descriptors. Compose rules with these fields; JSON names and selectors are generated.

type Spec

type Spec[S, R, A any] struct {
	ID          TableID
	Row         contract.JSON[R]
	Columns     []ColumnRegistration[S, R]
	Filters     []FilterRegistration[S]
	DefaultSort []Sort
	Stable      []expr.ProjectionOrder[S]
	Authorize   func(context.Context, A, Action) error
	Source      func(context.Context, A) (rows.Query[S, R], error)
	Exports     bool
}

Spec binds one row contract to server-owned authorization and row scope. Source must return the complete unpaginated query with mandatory tenant, visibility and soft-delete policy already applied. Authorize is mandatory even for explicitly public/system reports. A is trusted server context, never decoded from Request. Use auth.Guard[M] when binding an authenticated policy. Stable orders must uniquely identify a result (including grouped/joined rows).

type Table

type Table[S, R, A any] struct {
	// contains filtered or unexported fields
}

func Define

func Define[S, R, A any](spec Spec[S, R, A]) Table[S, R, A]

func (Table[S, R, A]) Count

func (t Table[S, R, A]) Count(ctx context.Context, m *Manager, subject A, request Request) (int64, error)

Count applies the exact Query authorization, server scope and client filters. Request pagination is validated but does not restrict the unpaginated total. The count query omits the table's ordering.

func (Table[S, R, A]) Description

func (t Table[S, R, A]) Description() (Description, error)

func (Table[S, R, A]) Download

func (t Table[S, R, A]) Download(ctx context.Context, m *Manager, subject A, request Request, options ExportOptions) (foundryhttp.Download, error)

Download freezes the bounded request, then uses Export when HTTP opens the representation. Every open repeats current authorization and query scoping. The existing HTTP file transport owns range handling and always closes the returned artifact. Subject A must remain valid for that request's lifetime.

Generation and transfer run under the request's single deadline. Declare the download route with WithTimeout(m.DownloadTimeout()) so a report is not cut by the kernel RequestTimeout; generation is also bounded by ExportTimeout. When the request context ends (deadline, client disconnect or shutdown), generation stops and releases its export slot, read transaction and temporary file. Responses carry the artifact's SHA-256 as a strong ETag plus Last-Modified, so a Range resume with If-Range receives the complete new file when a later run differs.

func (Table[S, R, A]) Export

func (t Table[S, R, A]) Export(ctx context.Context, m *Manager, subject A, request Request, options ExportOptions) (result *Artifact, err error)

Export applies the same validated request and server scope as Query. Page and Size are validated, but all matching rows are exported up to MaxExportRows. No artifact is returned until the database stream and complete CSV/ZIP finish. Locale defaults to the configured default; an empty time zone means the configured export zone. A cell that is not valid UTF-8, contains control characters or exceeds its bound is written safely instead of failing.

func (Table[S, R, A]) ID

func (t Table[S, R, A]) ID() TableID

func (Table[S, R, A]) Inspect

func (t Table[S, R, A]) Inspect(ctx context.Context, m *Manager, subject A) (Description, error)

func (Table[S, R, A]) Query

func (t Table[S, R, A]) Query(ctx context.Context, m *Manager, subject A, request Request) (orm.PageResult[R], error)

Query returns one numbered page and the complete matching total: one count query without the table's ordering and one ordered row query, in a single read-only repeatable-read transaction.

func (Table[S, R, A]) Registration

func (t Table[S, R, A]) Registration() Registration

func (Table[S, R, A]) SimpleQuery

func (t Table[S, R, A]) SimpleQuery(ctx context.Context, m *Manager, subject A, request Request) (orm.SimplePage[R], error)

SimpleQuery returns one page without counting: the row query reads one lookahead row to report HasMore. Use it for large or expensive sources where a total is not needed. Validation, authorization and scope match Query.

func (Table[S, R, A]) Validate

func (t Table[S, R, A]) Validate() error

type TableID

type TableID string

TableID is a semantic registration identity, never a SQL table name.

Directories

Path Synopsis
Package importer streams CSV and XLSX uploads into typed rows.
Package importer streams CSV and XLSX uploads into typed rows.
internal
spreadsheet
Package spreadsheet owns the SpreadsheetML (XLSX) conventions shared by datatable exports and imports: cell references, OOXML text escapes and serial dates.
Package spreadsheet owns the SpreadsheetML (XLSX) conventions shared by datatable exports and imports: cell references, OOXML text escapes and serial dates.

Jump to

Keyboard shortcuts

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