Changelog
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
[Unreleased]
[2.3.0] - 2026-11-13
Deprecated
jwt.ExtractClaimsFromJwt: useExtractClaimsFromJWT.middleware.ContextMiddleware: usemiddleware.RequestContext.i18n.MWOption: usei18n.MiddlewareOption.
The old names keep working and will be removed in fibr v3.
Added
fibrtest:NewRedis(t)starts an in-memory Redis (miniredis) and returns it with a connected go-redis client, both closed at test end.ws:WithLoggersets the logger for decode and backplane errors.rediskit:Redis.Loggersets the logger forSubscribebackground errors.mailer:NewLogSenderWithLogger.
Changed
- Error messages from
config,jwt,slug, andbootstrapnow start with the package name (for exampleslug: check uniqueness: …), like the rest of the library. Code that matches these errors by text needs updating;errors.Is/errors.Asare unaffected. - Generator: generated apps import fibr packages under
fibr*aliases (fibrmailer,fibrjobs, …) instead of the legacyfh*prefix. outbox: the relay marks a whole batch as published with oneUPDATEinstead of one per event, and renews its lock by elapsed time (a third of the TTL) instead of before every event. A batch of 100 is about 5x faster, and about 19x faster with a lock. Progress is still recorded when the context is cancelled mid-batch. If the process dies mid-batch, the events already published in that batch are sent again (previously at most one); delivery was and remains at-least-once.
[2.2.0] - 2026-11-13
Changed
- Requires Bun v1.3.0 (was v1.2.18). Bun 1.3 changed
LimitandOffsetto takeint64andCountto returnint64, so fibr can only build against one side of that change. Upgrading fibr therefore moves your module to Bun 1.3 too: convert your ownLimit(n)/Offset(n)arguments toint64and expectint64fromCount. Apps generated byfibr neware updated accordingly. - The minimum Go version is now 1.26.10 (required by updated dependencies).
- Other dependency updates: go-redis v9.23.0, minio-go v7.4.1, prometheus/client_golang v1.25.0, validator v10.30.6, go-mail v0.8.2, OpenTelemetry OTLP exporter v1.47.0, miniredis v2.40.0 (test-only).
[2.1.0] - 2026-11-13
Deprecated
sse: use Fiber's owngithub.com/gofiber/fiber/v3/middleware/sse, which adds heartbeats,Last-Event-ID, and disconnect detection. The package keeps working and will be removed in fibr v3.reqctx:GetContext,SetLocal, andGetLocal. Fiber v3 covers them withc.Context()and the genericfiber.Locals.GetRequestIDstays.
Added
slug:GenerateReadablereturns the plain slug (my-title) when it is free and falls back to the suffixed form otherwise.outbox: theAttemptmodel andoutbox_attemptstable (created byMigrate).
Fixed
bootstrap: a request whose handler panicked was missing from the request log and from the metrics. A second recover middleware inside them now turns the panic into a 500 that both record.metrics: requests that matched no route were all counted underpath="/", mixed with the real root route. They are now labeledpath="unmatched".
Changed
outbox:WithMaxAttemptscounts failed publishes in theoutbox_attemptstable instead of in memory, so the count survives restarts and is shared across replicas. Re-runoutbox.Migrateafter upgrading if you useWithMaxAttempts.Prunealso clears counters of events that are no longer pending.- Generator: the realtime sample (
fibr new --realtime) now uses Fiber's SSE middleware, and ends its stream when the server starts shutting down so an open stream does not hold up a graceful shutdown.
[2.0.1] - 2026-11-13
Fixed
sse: an SSE stream could crash the whole process.Handlerruns the stream function after the route handler has returned, when Fiber v3 has already recycled thefiber.Ctx; usingcthere (for examplec.RequestCtx().Done(), as the generated realtime sample does) dereferenced a nil pointer on a goroutine no recover middleware covers.Handlernow keeps the context alive for the duration of the stream, and recovers and logs a panic in the stream function instead of letting it kill the server.- Generator: the sample CRUD model now requires
name, soPOST /<plural>with an empty body returns 422 instead of creating an empty record.
[2.0.0] - 2026-11-13
fibr v2 targets Fiber v3. See MIGRATING.md for upgrade steps. v1 (Fiber v2) continues on the v1 branch.
Changed
- Breaking: the module path is now
github.com/rahmadafandi/fibr/v2. Update imports andgo get github.com/rahmadafandi/fibr/v2. - Breaking: fibr now targets Fiber v3 (
github.com/gofiber/fiber/v3) instead of the deprecated Fiber v2. For code that uses fibr: - Handlers and middleware take
fiber.Ctx(an interface) instead of*fiber.Ctx. - The request context is
c.Context()(wasc.UserContext());ContextMiddlewaresets it withc.SetContext. - Use
c.Bind().Body/Query/URIinstead ofc.BodyParser/QueryParser/ParamsParser; path-parameter struct tags areuri:"…"instead ofparams:"…". Thebindpackage does this for you. bootstrap.Options.FiberConfigandOptions.CORSare the Fiber v3 types;cors.Config.AllowOriginsis now a[]string.redis.Storageimplements Fiber v3'sfiber.Storage, including the new…WithContextmethods.- Tracing uses
github.com/gofiber/contrib/v3/otelandwsusesgithub.com/gofiber/contrib/v3/websocket. - Apps generated by
fibr neware Fiber v3 apps. - Breaking: three packages are renamed so they no longer collide with the packages they are used alongside (no more import aliases):
context→reqctx,http→httpclient,redis→rediskit. Only the package name and import path change; the APIs are the same. - Breaking: safer defaults.
uploader: files are stored as<random>-<name>by default, so same-named uploads never overwrite each other.WithUniqueNamesis gone; useWithOriginalNames()to keep the original name (and the overwrite behavior).uploader:Uploader.Uploadtakes acontext.Contextas its first argument.UploadContextandContextUploaderare removed.auth:RequireAuthandOptionalreject tokens without anexpclaim.WithExpirationRequiredis gone; useWithExpirationOptional()to accept non-expiring tokens.bootstrap:Options.EnableCORSis removed; CORS is off unless you setOptions.CORSOrigins(a list of allowed origins) orOptions.CORS(full config). Nothing allows every origin implicitly any more.- Apps generated by
fibr newread allowed origins fromCORS_ALLOW_ORIGINS(comma-separated); CORS is off when it is unset.
[1.6.1] - 2026-11-13
Changed
- Dependency updates: Fiber v2.52.15, go-redis v9.22.0, fasthttp v1.73.0, minio-go v7.3.0, go-mail v0.8.1, prometheus/client_golang v1.24.1, OpenTelemetry v1.46.0, validator v10.30.4, mimetype v1.4.16, fasthttp/websocket v1.5.12, and (test-only) testify v1.12.1 and miniredis v2.39.0.
[1.6.0] - 2026-11-12
Added
apierror:StatusOf(err)returns the HTTP statusHandlerresponds with for an error.uploader:WithUniqueNames()stores each file as<random>-<name>so same-named uploads cannot overwrite each other;UploadContexton both uploaders and theContextUploaderinterface make uploads cancellable.parser:MaxLimit(default1000) caps the page size applied byPaginateandKeyset.jwt:ErrEmptySecret.auth:WithExpirationRequired()rejects tokens without anexpclaim.outbox:WithMaxAttempts(n)moves an event that keeps failing to the newoutbox_deadtable (DeadEvent) instead of blocking the queue;Prunedeletes old published events;WithLoggersets the relay's logger.inbox:Prunedeletes old dedup markers.ratelimit:Newaccepts options;WithLoggersets the logger used when Redis fails.bootstrap:Options.CORS(*cors.Config) to restrict allowed origins.- Integration tests against real Postgres and Redis (
make integration), run in CI.
Changed
parser: page sizes aboveMaxLimitare now clamped (previously unbounded). Setparser.MaxLimit = 0to restore the old behavior.jwt:GenerateToken,GenerateTokenWithExpiry, andValidateTokenreturnErrEmptySecretfor an empty secret. Consequentlyauth.RequireAuth("")rejects every request and anIssuerwith an empty secret cannot issue tokens.middleware:ContextMiddlewarederives the request context fromc.UserContext()and also stores it there, soc.UserContext()now carries the request timeout and request id. Handlers that passc.UserContext()to slow calls are therefore bounded by the request timeout (bootstrap.Options.RequestTimeout, default 10s), ascontext.GetContext(c)callers already were.bootstrap: the tracing middleware runs beforeContextMiddleware, so the request context is a child of the request span.outbox:Migratealso creates theoutbox_deadtable; withWithLock, the relay renews its lock before each event.examples/.envis nowexamples/.env.example.
Security
- Bumped
golang.org/x/net(v0.60.0),golang.org/x/text(v0.42.0),klauspost/compress(v1.20.2),andybalholm/brotli(v1.2.7), OpenTelemetry (v1.45.0), andgoogle.golang.org/grpc(v1.83.1), and the Go toolchain to 1.26.11, to pick up fixes for vulnerabilities reported bygovulncheck.
Fixed
middleware: the request logger loggedstatus: 200for any error returned by a handler; it now logs the status the client receives.metrics:*apierror.Errorresponses (e.g. a 404) were counted asstatus="500".server: a zeroTimeoutmade the shutdown context expire immediately, aborting shutdown and cleanup hooks; it now defaults to 10 seconds.lock:Dodid not release the lock when its context was cancelled whilefnran, leaving the key held until its TTL.parser: search usedILIKEon every database and failed on SQLite; it now usesLIKEoutside Postgres.
[1.5.0] - 2026-06-14
Added
retrypackage: generic retry with exponential backoff + optional jitter —Do(ctx, fn, opts...)andDoValue[T], withWithAttempts/WithDelay/WithMaxDelay/WithMultiplier/WithJitter/WithRetryIf.inboxpackage: idempotent-consumer dedup —Once(ctx, db, messageID, fn)records a marker and runs fn in one transaction (duplicate IDs skip fn; a failing fn rolls the marker back). The consumer-side complement tooutbox.dbresolverpackage: explicit read/write split over Bun —New(primary, replicas...)withWriter()(primary) andReader()(round-robin replica, primary when none), plusPing/Close.
[1.4.0] - 2026-06-14
Added
pagination:(*CursorPage[T]).LinkHeader(baseURL)builds an RFC 5988Linkheader withrel="next"/rel="prev"from the page cursors.http:WithContextHeader(header, extract)sets a per-request header from the call's context (e.g. propagate a request id or trace correlation downstream).
[1.3.0] - 2026-06-14
Added
cachepackage: a generic in-memory cacheCache[V]with TTL, LRU max-size eviction, and singleflightGetOrLoad. Complementsredis.Remember(remote) for hot data without a network round-trip.ratelimitpackage: a Redis-backed token-bucket limiter (per-key buckets, cost-per-request viaAllow) with a FiberMiddleware(429 +Retry-After+X-RateLimit-*headers).apikeypackage: API-key authentication (distinct from JWTauth) — hash a presented key and resolve its identity + scopes via a pluggableStore(MapStore), withGenerate/Hash, a FiberMiddleware,RequireScope, andFromContext/HasScope.
[1.2.0] - 2026-06-14
Added
health: dependency probesPingRedis,PingHTTP, andPingTCP.health.ReadinessGate+server.RunGracefulWithConfig/server.Config: flip/readyzto not-ready and wait a drain delay before shutting down, so a load balancer stops routing first.server.RunGracefulis unchanged (delegates with the new defaults).http: optional circuit breaker viaWithCircuitBreaker(maxFailures, openTimeout)— rejects calls withErrCircuitOpenwhile a dependency is failing, with a half-open probe after the timeout.redis.Remember: in-process singleflight deduplication so concurrent misses for the same key run the loader once (cache-stampede protection).eventspackage: in-process typed event bus (Subscribe[T]/Publish[T]), synchronous by default with an opt-in async mode (WithAsync). Complementsoutboxfor intra-process fan-out.featureflagpackage: runtime flags (boolean, percentage rollout, per-user/group targeting) via a pluggableProvider—Static,Rules, andRedis— plus a FiberMiddlewareandEnabled(c, flag)helper.auditpackage: structured audit log — aRecorderwrites actor/action/target entries through a pluggableSink(NewBunSink+Migrate+List), with a FiberFromRequesthelper prefilling actor/IP/request-id.
[1.1.0] - 2026-06-13
Fixed
lock:Acquirenow reportsErrNotAcquiredwhen the context is cancelled or times out during an acquisition attempt (previously the raw Redis transport error could leak through, soerrors.Is(err, ErrNotAcquired)was unreliable).
Added
lockpackage: single-instance Redis distributed mutex (TryAcquire/Acquire/Do, owner-onlyRelease/Extend) for single-execution across replicas.- Keyset (cursor) pagination:
parser.KeysetBun modifier with opaque cursors (EncodeCursor/DecodeCursor) andpagination.CursorPage/NewCursorPagewith forward and backward navigation. Complements the existing offset pagination. outboxpackage: transactional outbox (Enqueuewithin a Bun transaction + a backgroundRelaythat publishes pending events at-least-once, withNewRedisPublisherand optional single-relay coordination vialock). Solves the dual-write problem between the database and Redis pub/sub.fibrtestpackage: a test harness for fibr/Fiber apps — a fluent HTTPClientover*fiber.App(Get/Post/Requestbuilder,WithBearer), response assertions (ExpectStatus/JSON/Text), plusNewDB(in-memory SQLite Bun) andToken(JWT minting) helpers.
[1.0.0] - 2026-06-13
First stable release. The public API is now covered by the compatibility guarantee in the README — no breaking changes will land within the v1.x series; anything breaking will go to v2.
No functional changes since v0.6.0. This release marks the API as stable after the v0.6.0 hardening pass (idiomatic-Go cleanup, stricter linters, fuzz tests for the parser surfaces, and the final breaking renames).
[0.6.0] - 2026-06-13
Added
redis: bulk and atomic helpers —MSet/MGet(pipelined),Incr/Decr,SetNX,GetSet.http:PostForm(urlencoded) andPostMultipart(file upload) requests.jobs: option helpersWithRetry/WithPriority/WithProcessIn/WithDeadline(returnasynq.Option, so callers need not import asynq).i18n: CLDR cardinal plural categories (zero/one/two/few/many/other) for en/fr/ru/uk/pl/ar and the no-plural languages; unknown locales use the English rule.Pluralnow resolves<key>.<category>.ws:(*Hub[T]).BackplaneErr()surfaces a failed Redis backplane subscription (the hub still serves local connections).
Changed
- Added
// Packagedoc comments to 16 packages; replacedinterface{}withany. - Stricter golangci-lint set (revive, unconvert, unparam, …) enforced in CI.
Removed
- Breaking:
http.Httprenamed tohttp.HTTPandhttp.HTTPErrortohttp.Error(stutter fixes). Update references accordingly. - Breaking:
middleware.Authremoved — useauth.RequireAuth(adds token revocation and scope checks).
[0.5.0] - 2026-06-11
Added
openapipackage: build an OpenAPI 3.0.3 spec from registered routes and reflected request/response structs (json + validator tags → JSON Schema with$refs, enums, formats, and min/max constraints). Serve it at/openapi.jsonwith a CDN-backed Swagger UI at/docs. Newbootstrap.Options.OpenAPI(plusOpenAPISpecURL/OpenAPIDocsURL) mounts both endpoints, and generated apps expose API docs out of the box (auth routes pre-registered when--auth).wspackage: typed WebSocketHub[T](rooms,Broadcast/ToRoom, per-connection write pump, keepalive ping) on gofiber/contrib/websocket, with an optional Redis backplane (WithRedis) bridging broadcasts across replicas via the existingredispub/sub.ssepackage: Server-Sent Events stream helper (Handler+Stream.Send/SendRaw/Comment/Event) with JSON encoding and multi-line data framing.- Generator: new
fibr new --realtimeflag scaffolds a WebSocket chat (/ws/:room) + SSE counter (/events); backplane auto-enabled whenREDIS_URLis set. i18npackage: dependency-free internationalization — a messageBundleloaded from nested JSON (flattened to dotted keys) with{placeholder}substitution, one/other pluralization (Plural/N), and a fallback locale; a locale-detection middleware (query > cookie >Accept-Language) andT/N/Localerequest helpers. Newbootstrap.Options.I18nmounts the middleware, andfibr new --i18nscaffolds en/id catalogs + a sample localized route.
[0.4.0] - 2026-06-10
Added
bindpackage:Body[T]/Query[T]/Params[T]parse a request intoT, validate it, and on failure write a400(malformed) or422(validation, with per-field errors) response — returningok=falseso handlers stop withreturn nil.jobs.Scheduler: cron-triggered job scheduling (Register/Run/Shutdown/Unregister,WithLocation) on top of asynq. Generated--queueapps gain aschedulersubcommand and a sample daily cleanup cron.uploader.S3Uploader: S3-compatible uploads (AWS S3, MinIO, R2, ...) via minio-go, behind the existingUploaderinterface, withWithKeyPrefix/WithBaseURL. Validation (size, MIME, filename) is now shared withLocalUploader; theOptiontype is unified across both.-
redis.Storage(NewStorage/WithPrefix): afiber.Storageadapter over go-redis, plusbootstrap.Options.RateLimitStorage. Generated apps use a Redis-backed (multi-instance-consistent) rate limiter whenREDIS_URLis set. -
apierrorpackage: typed HTTP errors (BadRequest/Unauthorized/NotFound/Conflict/Internal/...) withWithCode/WithDetails/Wrap, plus a FiberErrorHandler.bootstrapinstalls it by default, so a returned error renders as the JSON envelope. Adds an optionalerrorfield toresponse.Response. Generated auth handlers now return typed errors. -
bootstrap.Options.SecurityHeaders(helmet security response headers) andCompression(gzip/deflate/brotli) opt-in middlewares; generated apps enable both by default. bootstrap.Options.Idempotency+IdempotencyStorage: opt-in idempotency-key middleware (replays the cached response for a repeatedX-Idempotency-Keyon unsafe methods). Generated apps enable it, backed by Redis whenREDIS_URLis set.webhookpackage: HMAC-SHA256Sign/Verify(Stripe-stylet=,v1=with timestamp replay protection) and aMiddlewarethat guards inbound webhook routes (401 on bad signature).redispub/sub:(*Redis).Publishand genericSubscribe[T](background goroutine +Subscription.Close) for cross-instance events like cache invalidation and broadcasts.
Changed
- Generated handlers (module CRUD + auth register/login/refresh) now use
bind.Bodyand validate input via struct tags. Missing required fields now return422instead of400.
[0.3.0] - 2026-06-08
Changed
- BREAKING: renamed the project from
fiber-helperstofibr. The module path is nowgithub.com/rahmadafandi/fibr; update all imports. The repository moved togithub.com/rahmadafandi/fibr(the old URL redirects). - BREAKING: the generator CLI is now
fibrwith subcommands. Scaffold a project withfibr new <name>(wascreate-fiber-app <name>);fibr add module <name>is unchanged. Install withgo install github.com/rahmadafandi/fibr/cmd/fibr@latest. Release binaries are namedfibr.
[0.2.2] - 2026-06-08
Added
- Developer tooling: root
Makefile(build/test/cover/lint/vet/vuln/tidy/check),lefthook.ymlgit hooks (gofmt + golangci-lint on commit, tests on push). - CI:
govulncheckvulnerability scan job; test coverage profile uploaded to Codecov;examplesbuild/vet job. - Documentation: runnable godoc
Examplefunctions forpagination,jwt,validator,parser,response, andslug(rendered on pkg.go.dev). examples/: runnable demo apps forauth,mailer, andqueue, plus a README index.
[0.2.1] - 2026-06-08
Changed
go.mod: retract pre-release tags[v0.1.0, v0.1.13]. They predate the project stabilizing and point at commits removed by a history rewrite; they were never intended as supported releases.go getand pkg.go.dev now steer users to v0.2.0+.
[0.2.0] - 2026-06-07
Added
metricspackage: Prometheus request metrics middleware +/metricshandler (http_requests_total/http_request_duration_secondswith route-template labels; default Go/process collectors). Opt-in viabootstrap.Options.Metrics; generated apps toggle it withMETRICS_ENABLED.tracingpackage: OpenTelemetry tracer setup (Setupwith OTLP/HTTP exporter, global provider + W3C propagator,WithServiceName/WithSampler). Opt-in viabootstrap.Options.Tracing(otelfiber spans) +Options.Cleanup; request logs gaintrace_id/span_id; generated apps toggle withTRACING_ENABLED.database.WithTracing(): installs Bun'sbunotelOpenTelemetry query hook so SQL queries are recorded as spans. Generated apps enable it automatically whenTRACING_ENABLEDis set.rediscache helpers:Delete(variadic),Exists,Expire, andTTLon*Redisfor invalidating and inspecting cached entries.jobspackage: typed asynq queue wrapper (Client.Enqueue, genericHandle[T], workerServerwithRun/ProcessTask) and a mountable asynqmon monitoring handler (MonitoringHandler).bootstrap.Options.Asynqmon(AsynqmonMount): opt-in mount for a monitoring UIhttp.Handlerwith optional guard middleware (asynqmon dependency stays out ofbootstrap).create-fiber-app --queue: scaffolds a sample job, aworkersubcommand, the asynqmon UI mount, andREDIS_URL/QUEUE_CONCURRENCY/ASYNQMON_PATHconfig (both ddd and layered layouts). EmptyREDIS_URLdisables the queue with a warning (fail-soft).mailerpackage: pluggableSender(SMTPSendervia go-mail,LogSenderdev fallback,MemorySenderfor tests),Message, and aRenderHTML+text template helper.Newfalls back toLogSenderwhen no SMTP host is set.create-fiber-app --mailer: scaffolds SMTP config/env, a/email/testroute, and real send wiring for the welcome job (--queue, async via anemail:sendjob) and team invitation email (--auth-with-team). Both layouts.authpackage: bcryptHash/Compare, JWT bearer middleware (RequireAuth/Optional), claims accessors (Claims/Subject), and scope checks (RequireScope/HasScope/Scopes).authrefresh tokens + revocation:Issuer(Issue/Refresh/Logout) mints rotating access+refresh JWT pairs (TokenPair) with family-based reuse detection;TokenStoreinterface withRedisStoreandMemoryStoreimpls;WithBlocklistmakesRequireAuth/Optionalreject revoked tokens byjti(refresh tokens are also rejected for API access).create-fiber-app --auth: scaffolds an auth module (Account, register/login/me- scope-gated route, accounts migration) and generates a random
JWT_SECRET. Login returns an access+refreshTokenPair; adds/auth/refreshand/auth/logout; wires a redis-backed token store whenREDIS_URLis set, falling back to an in-memory store otherwise. authteam/workspace helpers:ActiveTeam,TeamRole,RequireTeam, andRequireRoleread the active team carried in the JWT (team/roleclaims); theIssuernow propagatesteam/rolethrough refresh.create-fiber-app --auth-with-team(implies--auth): multi-tenant scaffold where one account belongs to many teams via memberships, each team role maps to a permission set (carried as the active team'sscopes). Adds Team/Membership entities + migrations,POST /auth/switch-team,GET /teams,POST /teams,POST /teams/:id/members(gated bymember:manage), team-aware/me, and ateam:manageexample route; register auto-creates a personal team.create-fiber-app --auth-with-teamdynamic roles: each team owns its roles in the database (roles+role_permissionstables, seeded with owner/admin/member/viewer on team creation) instead of a static code map. Permissions are drawn from a fixed code catalog (GET /permissions) and resolved into the JWT at login/switch-team. Adds role management —GET/POST /teams/:id/roles,PUT/DELETE /teams/:id/roles/:name(owner- protected, in-use 409), andPUT /teams/:id/members(change a member's role) — all gated byrole:manage/member:manageand scoped to the active team.migratepackage:bun/migratewrapper (Up/Down/Status/Create) plus a ready cobraNewCommand(up/down/status/create).- Generated projects are now a single cobra binary with
serve+migratesubcommands and aninternal/migrations/package;--sampleandadd moduleemitcreate tablemigrations. bootstrap.Options.AutoMigrateto run moduleMigrateat startup (dev).bootstrap.Moduleinterface andApp.Mountfor self-wiring feature modules, with optionalMigratorandHealthCheckercapabilities.health.RegisterProvider/RegisterProviderAtfor live readiness checks.create-fiber-app add module <name>subcommand scaffolding a complete feature module for the detected layout (ddd/layered).database:NewBunopens a Bun ORM connection with automatic Postgres/SQLite dialect detection from the DSN; pool options (WithMaxOpenConns,WithMaxIdleConns,WithConnMaxLifetime,WithPingTimeout,WithoutPing).health:Register/RegisterAtmount/livez(liveness) and/readyz(readiness) endpoints that run named checks concurrently;/readyzapplies an overall deadline so a stuck check cannot hang the server.PingBunandCheckhelpers provided.server:RunGracefulstarts a Fiber app and blocks until SIGINT/SIGTERM, then shuts the server down cleanly and calls optional cleanup hooks.bootstrap:New(Options)wires recover, request-id, structured logging, optional CORS, optional rate limiting (health probes are exempt), optional DB health checks, and graceful shutdown in a single call.App.Run(addr)replacesfiber.App.Listen.config:default:"..."andrequired:"true"struct tags; extended type support (time.Duration, float, bool, integer with per-kind overflow detection, comma-separated[]string); combined error reporting across all fields.http: Context-aware JSON client built on fasthttp. All methods (Get,Post,Put,Patch,Delete) acceptcontext.Contextand return(statusCode int, err error).WithRetryretries only on 5xx;WithTimeout,WithHeaderoptions;FireAndForgetfor background non-blocking calls;HTTPErrortype for status-code errors.redis: GenericRemembercache-aside helper that returns a cached value or calls a loader on miss.ParseRedisOptionsparses a Redis URL into*redis.Optionsand returns an error on bad input.validator:Registerfor custom validation rules; error messages use JSON field names and include the failing value; handles non-struct input without panicking.jwt:GenerateTokenWithExpiryfor generating tokens with an explicit expiry duration.uploader:WithMaxSizeandWithAllowedMimeoptions forNewLocalUploader; filenames are sanitized and permissions are tightened; partial files are removed on write error.middleware:X-Request-IDresponse header added by the request-id middleware so callers can correlate responses.context:SetLocalandGetLocaltyped helpers replace the formerCustomContext.pagination:paginationpackage extracted to manage page/limit logic independently.
Changed
bootstrap.App.Mountruns a module'sMigrateonly when the app was built withAutoMigrate: true(previously always). Schema is owned by migrations by default.create-fiber-app --samplenow generates the sampleuserfeature as abootstrap.Modulemounted viaapp.Mount(previously hand-wired in main.go).- ORM migration: GORM removed; Bun is now the ORM throughout the library.
parserpagination scopes andslug.Generate(nowslug.Generate(ctx, db, table, text) (string, error)) migrated accordingly. config.LoadConfig: Signature changed from a generic return (LoadConfig[T]() (T, error)) to pointer-out (LoadConfig(out any) error), matching idiomatic Go.httpmethods: All request methods now accept a leadingcontext.Contextargument and return(int, error)instead of a plain error.commonpackage removed: Functionality split into theresponseandloggerpackages.
Removed
commonpackage: Replaced by dedicatedresponseandloggerpackages.parser.ParseBody/ParseQuery/ParseParams: Removed generic parse helpers; use Fiber's built-inc.BodyParser,c.QueryParser, andc.ParamsParserdirectly.redis.GormResult: Removed broken GORM-coupled helper; useRememberinstead.
Fixed
pagination: Guard against divide-by-zero whenlimitis zero; clamp page number to a valid range.parser: Corrected ILIKE pattern construction; added SQL-injection guard on the sort column expression.uploader: Path-traversal protection on uploaded filenames; partial file is cleaned up on write error; file permissions tightened.validator: No longer panics on non-struct input.config: Per-kind numeric overflow detection; errors from all fields are combined and reported together.slug: Uniqueness retry loop is now capped to prevent an infinite spin.redis:ParseRedisOptionsreturns an error instead ofnilon a bad URL.server: Signal-notify goroutine and exit bridge goroutine are cleaned up correctly on return.database: Malformed DSN schemes are rejected with an error instead of being silently treated as SQLite.http:FireAndForgetdetaches from the caller's context so cancellation does not abort background requests; retry backoff is context-aware.