Skip to content

Commit ef8104f

Browse files
committed
docs: enhance documentation with detailed comments for API builder, endpoint, and OpenAPI spec functionalities
1 parent ea06e85 commit ef8104f

19 files changed

Lines changed: 75 additions & 13 deletions

File tree

app.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Package simplapi provides a declarative HTTP API builder with optional
2+
// OpenAPI 3.1 spec generation. Use New with options to create an App, then
3+
// register routes via GET, POST, etc. and call ListenAndServe.
14
package simplapi
25

36
import (
@@ -8,38 +11,46 @@ import (
811
"github.com/go-simpl/simplapi/pkg/spec"
912
)
1013

14+
// App is the main API builder. It holds a framework adapter, optional OpenAPI
15+
// spec, and a list of endpoints that are registered on Sync or ListenAndServe.
1116
type App struct {
1217
framework framework.Framework
1318
spec *spec.Spec
1419

1520
endpoints []*Endpoint
1621
}
1722

23+
// AppConfig holds options applied by AppOption functions during New.
1824
type AppConfig struct {
1925
framework framework.Framework
2026
spec *spec.Spec
2127
}
2228

29+
// AppOption configures an App at construction time (e.g. WithCreateFramework, WithAutoOpenAPISpec).
2330
type AppOption func(*AppConfig)
2431

32+
// WithCreateFramework creates an App that uses the named framework (e.g. "fiber", "gin").
2533
func WithCreateFramework(frameworkName string) AppOption {
2634
return func(c *AppConfig) {
2735
c.framework = framework.GetFramework(frameworkName)
2836
}
2937
}
3038

39+
// WithFramework creates an App that uses the given framework instance.
3140
func WithFramework(framework framework.Framework) AppOption {
3241
return func(c *AppConfig) {
3342
c.framework = framework
3443
}
3544
}
3645

46+
// WithAutoOpenAPISpec enables OpenAPI 3.1 spec generation and built-in doc routes. basePkgName is stripped from schema type names.
3747
func WithAutoOpenAPISpec(basePkgName string) AppOption {
3848
return func(c *AppConfig) {
3949
c.spec = spec.New(basePkgName)
4050
}
4151
}
4252

53+
// New creates an App with the given options. If WithAutoOpenAPISpec is used, doc routes are registered immediately.
4354
func New(opts ...AppOption) *App {
4455
config := &AppConfig{}
4556
for _, opt := range opts {
@@ -57,40 +68,48 @@ func New(opts ...AppOption) *App {
5768
return s
5869
}
5970

71+
// GetApp returns the underlying framework (e.g. for middleware or testing).
6072
func (s *App) GetApp() framework.Framework {
6173
return s.framework
6274
}
6375

76+
// GET registers a GET route; returns an Endpoint for fluent options (WithTag, WithoutSpec, etc.).
6477
func (s *App) GET(path string, handlers ...interface{}) *Endpoint {
6578
endpoint := newEndpoint(http.MethodGet, path, handlers...)
6679
s.addEndpoint(endpoint)
6780
return endpoint
6881
}
6982

83+
// POST registers a POST route; returns an Endpoint for fluent options.
7084
func (s *App) POST(path string, handlers ...interface{}) *Endpoint {
7185
endpoint := newEndpoint(http.MethodPost, path, handlers...)
7286
s.addEndpoint(endpoint)
7387
return endpoint
7488
}
7589

90+
// PUT registers a PUT route; returns an Endpoint for fluent options.
7691
func (s *App) PUT(path string, handlers ...interface{}) *Endpoint {
7792
endpoint := newEndpoint(http.MethodPut, path, handlers...)
7893
s.addEndpoint(endpoint)
7994
return endpoint
8095
}
8196

97+
// DELETE registers a DELETE route; returns an Endpoint for fluent options.
8298
func (s *App) DELETE(path string, handlers ...interface{}) *Endpoint {
8399
endpoint := newEndpoint(http.MethodDelete, path, handlers...)
84100
s.addEndpoint(endpoint)
85101
return endpoint
86102
}
87103

104+
// PATCH registers a PATCH route; returns an Endpoint for fluent options.
88105
func (s *App) PATCH(path string, handlers ...interface{}) *Endpoint {
89106
endpoint := newEndpoint(http.MethodPatch, path, handlers...)
90107
s.addEndpoint(endpoint)
91108
return endpoint
92109
}
93110

111+
// Sync registers all endpoints with the framework and (if enabled) the OpenAPI spec.
112+
// Registration is deferred until Sync or ListenAndServe so fluent options (WithTag, etc.) are applied first.
94113
func (s *App) Sync() {
95114
for _, e := range s.endpoints {
96115
s.framework.Register(e.path, e.method, s.createHandler(e.handlers...))
@@ -100,8 +119,8 @@ func (s *App) Sync() {
100119
}
101120
}
102121

122+
// ListenAndServe registers all endpoints with the framework then starts the server.
103123
func (s *App) ListenAndServe(addr string) error {
104-
// Actual registration of endpoints happen here
105124
s.Sync()
106125

107126
return s.framework.ListenAndServe(addr)
@@ -112,7 +131,7 @@ func (s *App) addEndpoint(endpoint *Endpoint) {
112131
}
113132

114133
func (s *App) createHandler(handlers ...interface{}) framework.FrameworkHandler {
115-
// Reverse the handlers slice
134+
// Reverse so the first handler in the chain is outermost (middleware), last is innermost (route handler).
116135
for i, j := 0, len(handlers)-1; i < j; i, j = i+1, j-1 {
117136
handlers[i], handlers[j] = handlers[j], handlers[i]
118137
}

endpoint.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package simplapi
22

3+
// Endpoint is the fluent builder for a single route. Use WithTag, WithSummary, etc.,
4+
// or WithoutSpec to omit it from the OpenAPI spec.
35
type Endpoint struct {
46
method string
57
path string
@@ -40,6 +42,7 @@ func (e *Endpoint) WithOperationId(operationId string) *Endpoint {
4042
return e
4143
}
4244

45+
// WithoutSpec marks this route so it is not added to the OpenAPI spec (e.g. for internal doc routes).
4346
func (e *Endpoint) WithoutSpec() *Endpoint {
4447
e.addToSpec = false
4548
return e

errors/errors.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
// Package errors defines error types used by simplapi. TypeError is returned for
2+
// handler input binding failures and is sent as HTTP 422 with a JSON body.
13
package errors
24

35
import (
46
"fmt"
57
)
68

9+
// TypeError represents a validation or parsing error for a specific field during handler input binding.
710
type TypeError struct {
811
FieldName string `json:"fieldName"`
912
Message string `json:"message"`

openapi.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ const redocUI = `<!DOCTYPE html>
8181
</body>
8282
</html>`
8383

84+
// addOpenAPIRoutes registers built-in doc routes when WithAutoOpenAPISpec is used:
85+
// /_try/swagger, /_try/stoplight, /_try/redoc, and /openapi.json. These are internal and not in the main API spec.
8486
func addOpenAPIRoutes(app *App) {
8587
// TODO make the routes configurable
8688
app.GET("/_try/swagger", func() (*types.HTMLResponse, error) {

pkg/context/context.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
1+
// Package context provides a request-scoped key-value store passed into handlers.
12
package context
23

4+
// Context holds data for the duration of a request. Handlers can Set/Get values to pass data along the chain.
35
type Context struct {
46
data map[string]any
57
}
68

9+
// New returns a new empty request context.
710
func New() *Context {
811
return &Context{
912
data: make(map[string]any),
1013
}
1114
}
1215

16+
// Set stores a value in the context for this request.
1317
func (c *Context) Set(key string, value any) {
1418
c.data[key] = value
1519
}
1620

21+
// Get returns the value for key, or nil if not set.
1722
func (c *Context) Get(key string) any {
1823
return c.data[key]
1924
}
2025

26+
// Contains reports whether key is set in the context.
2127
func (c *Context) Contains(key string) bool {
2228
_, ok := c.data[key]
2329
return ok
2430
}
2531

32+
// Delete removes key from the context.
2633
func (c *Context) Delete(key string) {
2734
delete(c.data, key)
2835
}

pkg/framework/fiberframework/framework.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func (f *fiberFramework) GetNativeApp() interface{} {
2626
return f.app
2727
}
2828

29+
// GetOpenAPICompatiblePathPattern converts Fiber's :param syntax to OpenAPI's {param} for the spec.
2930
func (f *fiberFramework) GetOpenAPICompatiblePathPattern(path string) string {
3031
pathParts := strings.Split(path, "/")
3132
for i, part := range pathParts {

pkg/framework/fiberv3framework/framework.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func (f *fiberV3Framework) GetNativeApp() interface{} {
2626
return f.app
2727
}
2828

29+
// GetOpenAPICompatiblePathPattern converts Fiber's :param syntax to OpenAPI's {param} for the spec.
2930
func (f *fiberV3Framework) GetOpenAPICompatiblePathPattern(path string) string {
3031
pathParts := strings.Split(path, "/")
3132
for i, part := range pathParts {

pkg/framework/ginframework/framework.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func (g *ginFramework) GetNativeApp() interface{} {
2727
return g.engine
2828
}
2929

30+
// GetOpenAPICompatiblePathPattern returns path unchanged for the OpenAPI spec.
3031
func (g *ginFramework) GetOpenAPICompatiblePathPattern(path string) string {
3132
return path
3233
}

pkg/framework/iface.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Package framework defines the abstraction over HTTP frameworks (Fiber, Gin, etc.).
2+
// Implementations register via RegisterFramework in init(); the App uses GetFramework by name.
13
package framework
24

35
import (
@@ -7,6 +9,7 @@ import (
79
"github.com/go-simpl/simplapi/pkg/context"
810
)
911

12+
// Framework is the interface that each backend (Fiber, Gin, etc.) must implement.
1013
type Framework interface {
1114
Register(path string, method string, handler FrameworkHandler)
1215

@@ -19,8 +22,10 @@ type Framework interface {
1922
TestRequest(req *http.Request) (*http.Response, error)
2023
}
2124

25+
// FrameworkHandler is the function type that the framework calls for each request.
2226
type FrameworkHandler func(req FrameworkRequest, res FrameworkResponse, ctx *context.Context) error
2327

28+
// FrameworkRequest abstracts reading body, params, headers, etc. from the underlying framework.
2429
type FrameworkRequest interface {
2530
ParseJSONBody(target interface{}) error
2631
GetHeader(key string) string
@@ -31,6 +36,7 @@ type FrameworkRequest interface {
3136
GetFile(key string) (*multipart.FileHeader, error)
3237
}
3338

39+
// FrameworkResponse abstracts writing status, headers, and body to the underlying framework.
3440
type FrameworkResponse interface {
3541
SetHeader(key string, value string)
3642
SetCookie(cookie http.Cookie)

pkg/framework/registration.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package framework
22

3+
// availableFrameworks is populated by each framework's init() (fiber, gin, fiberv3, etc.).
34
var availableFrameworks map[string]func() Framework
45

56
func init() {
67
availableFrameworks = map[string]func() Framework{}
78
}
89

10+
// RegisterFramework registers a framework by name. Called from framework packages in init().
911
func RegisterFramework(name string, factory func() Framework) {
1012
availableFrameworks[name] = factory
1113
}
1214

15+
// GetFramework returns the framework instance for the given name. Panics if not registered.
1316
func GetFramework(name string) Framework {
1417
factory, ok := availableFrameworks[name]
1518
if !ok {

0 commit comments

Comments
 (0)