Make Server take a variadic array of Options and store config in ServerConfig (#72) - #103
Conversation
Server.New now accepts `...config.ServerOption` instead of a `config.ServerConfig` value, and the resolved values live in a `config.ServerConfig` embedded in the Server. ServerConfig is no longer a container of option slices: it holds the resolved BlogRoot, Port, Host, Logger, CacheControlTTL, HealthChecks, AssetsDir and TemplateDir values, plus the middleware chain and the generator/renderer options forwarded to the internal generator and template renderer. BaseServerOption is renamed ServerOption to match GeneratorOption, RendererOption and WatcherOption. Generator and renderer options reach the server through new AsServerOption methods, and the template filesystem through the new WithTemplateDir option. BREAKING CHANGE: server.New takes variadic config.ServerOption values, config.BaseServerOption is renamed to config.ServerOption, and config.ServerConfig no longer carries Server, Gen, TemplateDir and RendererOpts option slices. Refs #72 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assert that New resolves defaults and every server option into the embedded config.ServerConfig, and that generator, renderer and template directory options supplied as ServerOption values reach the generator and template renderer the server builds. Refs #72 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rewrite the server, config and README examples for the new server.New(posts, opts...) signature, and describe how base, generator and renderer options are converted with AsServerOption. Refs #72 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The server forwards its resolved blog root to the generator, so the option only needs supplying once. Refs #72 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CLI passes --root-path as a server option only and relies on the server forwarding its resolved blog root to the generator, but nothing asserted that forwarding. Existing blog-root tests only exercise routing, which is driven by the server's own BlogRoot, so dropping the forwarding would silently emit wrong in-page link and image paths with every test still green. Assert the forwarded field in TestNew_OptionsResolveIntoServerConfig and add TestNew_BlogRootForwardedToGenerator, which serves a post under a custom blog root and checks the rendered page data and the rewritten relative image path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Automated reviewI read the full diff, the surrounding code in The core change is sound. All eleven One finding:
Agent responsePushed as Review points1. The finding was accurate: nothing asserted that Two changes, both in
Mutation-checked: with I left the CLI comment at Verification
Posted by rain. Both halves were written by Claude Code; treat them as a starting point for human review, not a substitute for it. |
Closes #72
Note
This pull request was written by rain running Claude Code. It has not been reviewed by a human. CI and an automated review pass run before it is handed over.
It targets
v3-changesrather than the default branch:72-make-server-take-a-variadic-array-of-options-and-store-config-in-serverconfigwas already linked to the issue, and its history says it was cut fromv3-changes.Issue
#72: Make Server take a variadic array of Options and store config in ServerConfig
What the agent reports
Pushed. Four commits on the branch, baselined on
v3-changes.What changed
pkg/configServerConfigis now the resolved server configuration —BlogRoot,Port,Host,Logger,CacheControlTTL,HealthChecks,AssetsDir,TemplateDir, plusMiddleware,GeneratorOpts,RendererOpts. It no longer carriesServer/Gen/TemplateDir/RendererOptsoption slices.BaseServerOption→ServerOption, matchingGeneratorOption/RendererOption/WatcherOption.GeneratorOption.AsServerOption(),RendererOption.AsServerOption(), and a newTemplateDirconfig type withWithTemplateDir(fs.FS)(+AsOption).BaseOption.AsServerOption()is unchanged.pkg/serverfunc New(posts fs.FS, opts ...config.ServerOption) (*Server, error);Serverembedsconfig.ServerConfiginstead of seven separate config types and three unexported deferred-init fields. Field promotion meanssrv.Port,srv.Logger.Logger,srv.HealthChecks.Enabledetc. still read the same way.cli/internal/server— builds a[]config.ServerOption;runServenow takes(ctx, postsPath, posts, watch, opts...). I dropped the duplicate blog-root generator option there (and in one test):initializeassignss.generator.BlogRoot = s.BlogRootunconditionally, so applying it twice was a no-op.Tests — all existing call sites migrated (
pkg/server,cli/internal/server,integration). Newpkg/server/options_test.gocovers defaults, every option resolving into the embeddedServerConfig, health-checks deferring generator construction, and generator/renderer/template-dir options reaching the internal generator and renderer (the last renders a custom template through a forwardedWithFuncsentry). These fail without the change — the APIs they use don't exist on the old signature.Docs —
pkg/server/doc.go(new "# Configuration" section),pkg/config/doc.go, the option godoc examples, and README examples all rewritten for the variadic form; added a short serve example to the library section of README.Verification
go vet ./...,go test ./...andgo test -race ./...for both.andcli;go vet ./...forintegration;gofmt -lclean;go mod tidya no-op in all three modules. I did not run the integration suite (just test-integration) — it needs Docker; those tests compile and were updated. A CLI smoke run was blocked by a permission prompt, so end-to-end serve coverage rests on the CLI unit tests (index, post, blog-root, watch-reload, feeds).For review
BaseServerOption→ServerOptionand theServerConfigredefinition are the breaking parts; commit 1 is markedfeat(server)!with aBREAKING CHANGE:footer. Worth confirming this is the naming you want for v3 given the issue wroteconfig.ServerOptions.Newappends the server's own logger toServerConfig.GeneratorOpts, so that slice holds one more option than the caller passed.GeneratorOption.AsServerOptionshadows theAsServerOptionpromoted from its embeddedBaseOption;config.WithLogger(l).AsGeneratorOption().AsServerOption()therefore routes to the generator, whileconfig.WithLogger(l).AsServerOption()configures the server (which forwards it anyway).Changelog (#103)
📚 Documentation
🧪 Tests
❓ Uncategorised!