Documentation
¶
Overview ¶
Package types holds framework value types that are shared by generated models, handler DTOs, and the admin data plane. They exist so a single Go type flows through the model, the Huma contract (OpenAPI/TS client), and GORM persistence without the DTO drifting from the model (see #222 / #218).
Index ¶
- Constants
- func CheckDecimalSize(d decimal.Decimal) error
- func CheckDecimalSpelling(s string) error
- func DateWithin(d Date) error
- func DecimalWithin(d Decimal, min, max string) error
- func IsPlainDecimalSpelling(s string) bool
- func TimeBounds() (minimum, maximum time.Time)
- func TimeWithin(t time.Time) error
- type Date
- func (Date) GormDataType() string
- func (d Date) IsZero() bool
- func (d Date) MarshalJSON() ([]byte, error)
- func (d Date) MarshalText() ([]byte, error)
- func (d *Date) Scan(src any) error
- func (d Date) String() string
- func (d Date) Time() time.Time
- func (d *Date) UnmarshalJSON(b []byte) error
- func (d *Date) UnmarshalText(b []byte) error
- func (d Date) Value() (driver.Value, error)
- type Decimal
- type DecimalShape
- type Duration
- func (d Duration) Duration() time.Duration
- func (Duration) GormDataType() string
- func (d Duration) MarshalJSON() ([]byte, error)
- func (d Duration) MarshalText() ([]byte, error)
- func (d *Duration) Scan(src any) error
- func (d Duration) String() string
- func (d *Duration) UnmarshalJSON(b []byte) error
- func (d *Duration) UnmarshalText(b []byte) error
- func (d Duration) Value() (driver.Value, error)
- type File
- type Image
- type JSON
- type NullJSON
- type TimeOfDay
- func (TimeOfDay) GormDataType() string
- func (t TimeOfDay) MarshalJSON() ([]byte, error)
- func (t TimeOfDay) MarshalText() ([]byte, error)
- func (t *TimeOfDay) Scan(src any) error
- func (t TimeOfDay) String() string
- func (t *TimeOfDay) UnmarshalJSON(b []byte) error
- func (t *TimeOfDay) UnmarshalText(b []byte) error
- func (t TimeOfDay) Value() (driver.Value, error)
Constants ¶
const DecimalPattern = `^-?[0-9]+(\.[0-9]+)?$`
DecimalPattern is the create-body spelling of a decimal. Huma enforces it on the string schema. Bounds and defaults must use the same token so the form, the magnitude check, and the request accept one spelling.
const MaxDecimalDigits = 1000
MaxDecimalDigits bounds the digits a decimal value may spell: the digits String writes for it, before and after the point ("0.05" is 3). It is far beyond any money column (MySQL's widest is decimal(65,30)) and exists because a decimal's exponent is otherwise unbounded: "1e1000000000" parses in microseconds, but formatting or comparing it materialises every digit and holds a core and gigabytes of memory (issue #440 review).
It is the one size rule for decimals: parsing (UnmarshalJSON, UnmarshalText, NewDecimalFromString), reading (Scan), and the database write guard all judge a value with DecimalShapeOf, so a value one of them accepts the others accept too. A PostgreSQL numeric with no declared precision can hold more; such a value fails to load.
const TimeOfDayPattern = `^([01][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9](Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])?)?$`
TimeOfDayPattern is the one clock grammar. Huma's format "time" accepts HH:MM:SS and a numeric offset, and rejects HH:MM. This pattern accepts all three, which is what UnmarshalText parses and stores as HH:MM:SS. The generator, the admin write, and the type all use it. Format "time" is not that grammar.
Variables ¶
This section is empty.
Functions ¶
func CheckDecimalSize ¶ added in v0.7.1
CheckDecimalSize returns an error when d is beyond the size rule; see DecimalShapeOf.
func CheckDecimalSpelling ¶ added in v0.7.1
CheckDecimalSpelling refuses decimal text too long for any value within the size rule, before it is parsed (parsing a long coefficient is quadratic).
func DateWithin ¶ added in v0.7.1
DateWithin reports whether d is a date every supported database can store (DateBounds), with a message for the field otherwise.
func DecimalWithin ¶ added in v0.3.0
DecimalWithin reports whether d is inside the optional bounds. Empty min or max is unbounded on that side. Bounds are decimal magnitudes: Huma's minimum/maximum apply only to number and integer schemas, and Decimal's schema is a string.
func IsPlainDecimalSpelling ¶ added in v0.7.1
IsPlainDecimalSpelling reports whether s is a plain decimal spelling: [sign] digits [. digits] [e [sign] digits], with at least one digit before or after the point and an exponent of at most nine digits. That is the grammar SQLite, PostgreSQL and MySQL all read as a number ("5.", ".5", "+.5", "1.e5", "1e+05"). It is narrower than shopspring's parser, which also accepts a sign after a leading point (".-5" is -0.05) that no database reads, so code deciding what a database will store must check this, not only whether shopspring parses it (#440 review, round 6).
func TimeBounds ¶ added in v0.7.1
TimeBounds returns the earliest and latest timestamp TimeWithin accepts: 1000-01-02T00:00:00Z and 9999-12-30T23:59:59Z.
func TimeWithin ¶ added in v0.7.1
TimeWithin reports whether t is a timestamp every supported database can store and return (TimeBounds), with a message for the field otherwise.
Types ¶
type Date ¶ added in v0.3.0
type Date struct {
// contains filtered or unexported fields
}
Date is a calendar date. It is not a timestamp and not a time of day.
JSON and text are "YYYY-MM-DD". GORM's default column type is "date" (Postgres DATE, MySQL DATE, SQLite TEXT affinity). Value returns that calendar day as UTC midnight so PostgreSQL can encode it as a binary date. The zero Date is not a stored value: Value and MarshalJSON reject it. JSON null is a nil *Date.
func DateBounds ¶ added in v0.7.1
func DateBounds() (minimum, maximum Date)
DateBounds returns the earliest and latest date DateWithin accepts: 1000-01-01 and 9999-12-31.
func NewDate ¶ added in v0.3.0
NewDate returns the calendar date of t in UTC, dropping the clock time.
func (Date) GormDataType ¶ added in v0.3.0
GormDataType tells GORM the column family when a model field omits an explicit type tag. Generated models also set gorm:"type:date".
func (Date) MarshalJSON ¶ added in v0.3.0
MarshalJSON encodes the date as "YYYY-MM-DD". The zero date has no JSON form: "0001-01-01" is that zero value, and publishing it would round-trip through Value as an error. JSON null is a nil *Date.
func (Date) MarshalText ¶ added in v0.3.0
MarshalText implements encoding.TextMarshaler.
func (*Date) Scan ¶ added in v0.3.0
Scan implements sql.Scanner. Drivers return a time.Time, a date string, or nil.
func (*Date) UnmarshalJSON ¶ added in v0.3.0
UnmarshalJSON accepts null, "YYYY-MM-DD", or an RFC3339 timestamp (the date part is kept). The timestamp form is what admin coercion produces when it JSON-encodes a time.Time.
func (*Date) UnmarshalText ¶ added in v0.3.0
UnmarshalText implements encoding.TextUnmarshaler.
func (Date) Value ¶ added in v0.3.0
Value implements driver.Valuer. The stored value is UTC midnight on the calendar day, which is what PostgreSQL's binary date codec accepts. A zero Date is not SQL NULL: NULL is a nil *Date, and the zero value is refused so a required column does not silently insert NULL.
type Decimal ¶
Decimal is a fixed-point decimal for money and other exact numeric values.
It wraps shopspring/decimal.Decimal, so it inherits exact arithmetic, JSON (a quoted string — no float rounding), text (un)marshaling, and the database sql.Scanner / driver.Valuer used by GORM. On top of that it advertises an OpenAPI schema (a string with format "decimal") via huma.SchemaProvider, so the generated OpenAPI document and TypeScript client see a string instead of an opaque object. Use the gorm tag `type:decimal(p,s)` on the model field to pin precision/scale for the migration (gombit make resource emits decimal(19,4) by default).
A database opened with database.Open refuses, with a 422-mapped database.ValidationError, a value its column would not store exactly: one that does not fit decimal(p,s), and on SQLite, which has no fixed-point type, one with more than database.SQLiteDecimalDigits digits. Without a `type:decimal(p,s)` tag (a `precision:`/`scale:` tag does not reach the column for this type) the column is the driver's bare decimal, which on MySQL is DECIMAL(10,0) (whole numbers only), so pin decimal(p,s) for money.
func MustDecimal ¶ added in v0.3.0
MustDecimal parses s and panics if it is not a decimal. Generated mappers use it for a default the generator already validated.
func NewDecimalFromString ¶
NewDecimalFromString parses a decimal string (e.g. "19.99"), refusing one beyond MaxDecimalDigits.
func (Decimal) GormDataType ¶
GormDataType tells GORM the default column family when a model field omits an explicit `type:` tag. Generated models pin exact precision with `gorm:"type:decimal(19,4)"`, which takes precedence over this default.
func (*Decimal) Scan ¶ added in v0.7.1
Scan reads a decimal from the database and refuses one beyond the size rule, so a row the guard would refuse to write (stored before the guard existed, or by raw SQL) fails to load with an error instead of hanging the first formatting of it. A non-finite float is refused too: SQLite stores the literal "1e1000000000" in a decimal column as REAL Inf, and shopspring panics on it.
func (Decimal) Schema ¶
Schema implements huma.SchemaProvider so the contract represents a Decimal as a JSON string (matching its MarshalJSON), not a reflected struct.
func (*Decimal) UnmarshalJSON ¶ added in v0.7.1
UnmarshalJSON parses a decimal and refuses one beyond MaxDecimalDigits before anything formats it. A JSON null leaves d unchanged, as encoding/json's convention (and shopspring's own decoder) has it.
func (*Decimal) UnmarshalText ¶ added in v0.7.1
UnmarshalText parses a decimal and refuses one beyond MaxDecimalDigits before anything formats it.
type DecimalShape ¶ added in v0.7.1
type DecimalShape struct {
// Whole is the number of digits before the point, 0 for a value below 1.
Whole int
// Frac is the number of digits after the point, trailing zeros dropped.
Frac int
// Significant runs from the first non-zero digit to the last digit
// written, trailing integer zeros included (1000 has 4, 0.0012 has 2).
Significant int
}
DecimalShape is how a decimal is written, as String writes it.
func DecimalShapeOf ¶ added in v0.7.1
func DecimalShapeOf(d decimal.Decimal) (DecimalShape, error)
DecimalShapeOf measures d without formatting it beyond its bounded coefficient, and refuses it when its exponent is beyond ±MaxDecimalDigits or it spells more than MaxDecimalDigits digits.
The exponent is bounded on its own, whatever the coefficient: formatting or comparing a shopspring decimal rescales it, which computes 10^|exponent| before the coefficient matters, so "0e1000000000" costs as much as "1e1000000000" (issue #440 review). The coefficient's size is bounded from its bit length before it is formatted.
func (DecimalShape) Digits ¶ added in v0.7.1
func (s DecimalShape) Digits() int
Digits is the number of digits String writes: the leading "0" of a value below 1 included.
type Duration ¶ added in v0.3.0
type Duration struct {
// contains filtered or unexported fields
}
Duration is a span of time. JSON and text use Go's duration syntax ("1h30m", "300ms", "0s", "-1s"), which is what Huma's format "duration" accepts. The stored column is a signed bigint of nanoseconds so SQLite, PostgreSQL, and MySQL sort the same integer. A zero Duration is "0s" and is stored. SQL NULL is a nil *Duration.
func MustDuration ¶ added in v0.3.0
MustDuration parses s and panics if it is not a duration. Generated mappers use it for a default the generator already validated.
func ParseDuration ¶ added in v0.3.0
ParseDuration parses a Go duration string.
func (Duration) GormDataType ¶ added in v0.3.0
GormDataType tells GORM the column family when a model field omits an explicit type tag. Generated models also set gorm:"type:bigint".
func (Duration) MarshalJSON ¶ added in v0.3.0
MarshalJSON encodes the canonical duration string. Zero is "0s".
func (Duration) MarshalText ¶ added in v0.3.0
MarshalText implements encoding.TextMarshaler.
func (*Duration) Scan ¶ added in v0.3.0
Scan implements sql.Scanner. Drivers return an integer nanosecond count, or the duration text.
func (Duration) String ¶ added in v0.3.0
String returns the canonical Go duration spelling. "1h30m" becomes "1h30m0s".
func (*Duration) UnmarshalJSON ¶ added in v0.3.0
UnmarshalJSON accepts null or a duration string.
func (*Duration) UnmarshalText ¶ added in v0.3.0
UnmarshalText implements encoding.TextUnmarshaler. An empty string is rejected: zero is "0s", and "" is not that span.
type File ¶ added in v0.7.0
type File string
File is a storage-backed field's value: the key of an object in the application's storage (framework.App.Storage()), never the file's bytes. The column holds the key as a string; an empty File is no file. The generated resource code accepts a key only for an upload that passed the field's policy, returns a file object (key, filename, size, content type, URL) on reads, and stores one record per file (a unique index), so the record owns it. See docs/fields.md.
type Image ¶ added in v0.7.0
type Image string
Image is a File whose field accepts images only (detected from their bytes); everything else is as for File.
type JSON ¶ added in v0.3.0
type JSON json.RawMessage
JSON is a JSON object or array stored as text. Null is not a document: UnmarshalJSON and Schema reject it. Optional columns use NullJSON, because Huma validates anyOf before it honors a nullable tag, so one schema cannot both reject null (required) and allow it (optional).
func (JSON) GormDataType ¶ added in v0.3.0
GormDataType tells GORM the column family when a model field omits an explicit type tag. Generated models also set gorm:"type:text".
func (JSON) MarshalJSON ¶ added in v0.3.0
MarshalJSON returns null for a nil document and the raw document otherwise.
func (JSON) Schema ¶ added in v0.3.0
Schema implements huma.SchemaProvider. Null is not a member: a required field rejects JSON null. Optional fields use NullJSON.
func (*JSON) UnmarshalJSON ¶ added in v0.3.0
UnmarshalJSON stores a JSON object or array. Null is rejected.
type NullJSON ¶ added in v0.3.0
type NullJSON JSON
NullJSON is a JSON object, a JSON array, or null. Generated optional json columns use it so a stored NULL validates against the published contract.
func (NullJSON) GormDataType ¶ added in v0.3.0
GormDataType tells GORM the column family when a model field omits an explicit type tag. Generated models also set gorm:"type:text".
func (NullJSON) MarshalJSON ¶ added in v0.3.0
MarshalJSON returns null for a nil document and the raw document otherwise.
func (NullJSON) Schema ¶ added in v0.3.0
Schema implements huma.SchemaProvider. Object, array, and null are members.
func (*NullJSON) UnmarshalJSON ¶ added in v0.3.0
UnmarshalJSON stores a JSON object or array. Null clears the value.
type TimeOfDay ¶ added in v0.3.0
type TimeOfDay struct {
// contains filtered or unexported fields
}
TimeOfDay is a clock time with no date and no zone. JSON and text are "HH:MM:SS". "HH:MM" and a time with a numeric offset ("15:04:05+07:00", the second form Huma's format "time" accepts) are read as that clock and stored as "HH:MM:SS". The offset is not applied: a time of day has no date to convert.
The zero TimeOfDay is midnight, which is a real clock time, and Value stores it. SQL NULL is a nil *TimeOfDay. The column is char(8) so SQLite, PostgreSQL, and MySQL share one sortable text form.
func MustTimeOfDay ¶ added in v0.3.0
MustTimeOfDay parses s and panics if it is not a clock time. Generated mappers use it for a default the generator already validated.
func ParseTimeOfDay ¶ added in v0.3.0
ParseTimeOfDay parses a clock time.
func (TimeOfDay) GormDataType ¶ added in v0.3.0
GormDataType tells GORM the column family when a model field omits an explicit type tag. Generated models also set gorm:"type:char(8)".
func (TimeOfDay) MarshalJSON ¶ added in v0.3.0
MarshalJSON encodes the clock as "HH:MM:SS".
func (TimeOfDay) MarshalText ¶ added in v0.3.0
MarshalText implements encoding.TextMarshaler.
func (*TimeOfDay) UnmarshalJSON ¶ added in v0.3.0
UnmarshalJSON accepts null, "HH:MM:SS", "HH:MM", or a clock with a numeric offset.
func (*TimeOfDay) UnmarshalText ¶ added in v0.3.0
UnmarshalText implements encoding.TextUnmarshaler. An empty string is rejected: midnight is "00:00:00", and "" is not that clock. The accepted spellings are TimeOfDayPattern, the same pattern the request and the admin write enforce.