Release Notes
User-facing changes in each Salusa framework release, newest first. New identifiers link to their documentation on pkg.go.dev; each section links to the framework release itself.
v0.30.0 - 2026-10-09
The optional package is renamed to option, the local filesystem moves out of
filesystem into a new wfs package that can write as well as read, and the DI
container gains a declarative way to declare and validate a dependency. Release:
v0.30.0.
Option package
- The
optionalpackage is renamed tooptionandoptional.Optional[T]tooption.Option[T]. See Option Values. - New
Option.FlatMap[U]applies a function that itself returns anOption[U], so the result is not nested.
Files
- New
wfspackage. It keeps the injectablefs.FSfromfilesystemand adds optional writes throughWriteFileFS,OpenFileFS,MkdirFS,RemoveFS, andRenameFS, with matching package-level helpers. See Files & File Serving. - The generated template stores
Config.FileSystemas a plain pathstringand registers it withwfs.RegisterLocal.
Dependency injection
- New
di.Uses[T]. Embed it to give a struct aValidate(ctx)method that checks everyinjectfield ofT. - New
di.ValidatorFor[T](ctx), the generic form ofdi.Validator. See Dependency Injection.
HTTP
Router.Validatenow validates route-level middleware that implementsvalidate.Validator, in addition to handlers.Route.Middlewarenow installs the wrapped handler on the underlying route, so per-route middleware added after registration runs at request time. See Routing.
Database
mixins.SoftDeletenow storesDeletedAtas anoption.Option[time.Time]rather than a*time.Time.
Breaking changes
- The
optionalpackage is renamed tooption. Replaceimport "gosalusa.com/optional"withimport "gosalusa.com/option"andoptional.Optional[T]withoption.Option[T]. - The
filesystempackage is removed. Replacefilesystem.Register(ctx, cfg)withwfs.RegisterLocal(ctx, path), and dropfilesystem.Configfor a plain pathstring. mixins.SoftDelete.DeletedAtis now anoption.Option[time.Time]rather than a*time.Time. UseDeletedAt.Valid()where a nil check was used.
v0.29.0 - 2026-09-29
optional.Optional[T] is now a struct with an unexported
sql.Null[T] inside it rather than a defined type over it, so the wrapped
value and its validity flag can no longer be reached through fields. Three
methods replace the field access that is gone: Valid() for a plain check,
Or for a lazily built fallback, and All for iteration.
Release: v0.29.0.
optional.Optional[T]no longer exposesVandValidas exported fields. Build values withSomeandNone[T]()instead of a composite literal, and read the wrapped value withOrElseorOk. See Optional Values.- New
Optional.Valid()method reporting whether the value is present. - New
Optional.Or, which returns the value unchanged when it is valid and otherwise calls a function for the fallback. The function is only evaluated when the value is absent, so an expensive default costs nothing on the common path. - New
Optional.All, returning aniter.Seq[T]that yields the wrapped value once when theOptionalis valid and nothing when it is not. It drops straight intorangeand intostreampipelines. optional.OfNullgained a correct doc comment; it is unchanged.
Breaking changes
Optional.IfPresentwas removed. Replacen.IfPresent(fn)withn.Or(func() optional.Optional[T] { /* fallback */ return optional.None[T]() })when you want a value back, or branch onn.Valid()and callfnyourself.- The
VandValidfields ofOptional[T]are no longer exported. Replaceoptional.Optional[string]{V: "a", Valid: true}withoptional.Some("a"), andn.Validwithn.Valid().
v0.27.0 - 2026-09-25
A small release with three new pieces of API: a cache abstraction with an
in-process implementation, a minimal nullable wrapper published at a /v2
import path, and a builder option on the event service. The query builder also
grows raw ordering. Release: v0.27.0.
- New
cachepackage. TheMemoryCacheinterface coversGet,GetOrCreate,Set, andRemoveover[]byte, andSetOptionsis a placeholder for per-write options. See Caching. MapCacheis the shipped in-process implementation, built byNewMapCachewith a five-minute TTL, and entries areMapCacheItemvalues with an absolute expiration.cache.Registerregisters aMemoryCacheas a lazy singleton, so handlers can inject the interface rather than constructing a cache.Builder.OrderByRawandModelBuilder.OrderByRawappend an unencoded sort expression toORDER BY, for the cases a column name cannot express: aCASE, or a function call. See Builder.EventService.Synchronousis a new builder option on the service returned byevent.Service, for choosing between handling each dequeued message inline and handling it on its own goroutine. See Events.- New
nulls/v2package holdingNull[T], asql.Null[T]wrapper with JSON and SQL support only. It is a smaller alternative tooptional.Optional[T]; see Optional Values.
Breaking changes
dialects.OrderColumn.Column is now adialects.Columnrather than astring, so an order column can carry a raw expression. If you buildOrderColumnvalues directly, wrap the name:dialects.OrderColumn{Column: dialects.Column{Column: "name"}, Descending: true}. Queries built through the builder’sOrderByandOrderByDescneed no change.