Skip to content

Commit

Permalink
Cleans up the documentation, puts data flow on its own page
Browse files Browse the repository at this point in the history
  • Loading branch information
EwenQuim committed Nov 29, 2024
1 parent 96920cd commit 2da063c
Show file tree
Hide file tree
Showing 14 changed files with 154 additions and 50 deletions.
9 changes: 9 additions & 0 deletions documentation/docs/guides/01-data-flow.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import FlowChart from '@site/src/components/FlowChart';

# Data Flow

Here's a high-level overview of how data flows through a Fuego application.

Please note that every step can send an error to the error handler.

<FlowChart />
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import FlowChart from '@site/src/components/FlowChart';

# Controllers

Controllers are the main way to interact with the application. They are responsible for handling the requests and responses.

<FlowChart selected="Controller" />

Check failure on line 5 in documentation/docs/guides/controllers.md

View workflow job for this annotation

GitHub Actions / lint

Multiple consecutive blank lines [Expected: 1; Actual: 2]
## Controller types

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import FlowChart from '@site/src/components/FlowChart';

# Error handling

Error handling is a crucial part of any application. It is important to handle errors gracefully and provide meaningful feedback to the user. In this guide, we will cover how to handle errors in a Fuego application.


<FlowChart selected="ErrorHandler" />

## Error handling in Fuego

Fuego [controllers](./controllers) returns a value and an error. If the error is not `nil`, it means that an error occurred while processing the request. The error will be returned to the client as a JSON response.

By default, Fuego implements [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457), which defines a standard error format for HTTP APIs. We strongly recommend following this standard, but you can also use your own errors.

The error type returned as JSON is `fuego.HTTPError`. It has a `Status` and a `Info` field. The `Status` field is an integer that represents the error code. The `Info` field is a string that contains a human-readable error message.

If your error implements `Status() int` and `Info()` methods, the error will include the status code and the error message in the `fuego.HTTPError` response.
Expand Down
13 changes: 9 additions & 4 deletions documentation/docs/guides/middlewares.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ authentication, etc.

You can add middlewares to the whole server using the `Use` method:

```go
```go title="main.go" showLineNumbers
package main

import (
Expand Down Expand Up @@ -45,7 +45,7 @@ func main() {

You can also add middlewares to a group of routes using the `Group` method:

```go
```go title="main.go" showLineNumbers
package main

import (
Expand Down Expand Up @@ -82,9 +82,10 @@ func main() {
## Route middlewares

You can also add middlewares to a single route.
They are treated as an option to the route handler.
Simply add the middlewares as the last arguments of the route handler:

```go
```go title="main.go" showLineNumbers {13-14}
package main

import (
Expand All @@ -95,7 +96,11 @@ func main() {
s := fuego.NewServer()

// Declare the middlewares after the route handler
fuego.Get(s, "/", myController, middleware1, middleware2, middleware3)
fuego.Get(s, "/", myController,
option.QueryInt("page", "The page number"),
option.Middleware(middleware1),
option.Middleware(middleware2, middleware3),
)

s.Run()
}
Expand Down
31 changes: 29 additions & 2 deletions documentation/docs/guides/openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func main() {
Fuego `Server` exposes a `UIHandler` field that enables you
to implement your custom UI.

Example with http-swagger:
Example with `http-swagger`:

```go
import (
Expand Down Expand Up @@ -146,7 +146,34 @@ by more than 10Mb.
| | StopLight Elements | Swagger | Disabled |
| ------------- | ------------------ | -------------- | -------- |
| Works offline | No ❌ | Yes ✅ | - |
| Binary Size | Smaller | Larger (+10Mb) | Smaller |
| Binary Size | Smaller | Larger (+10Mb) | Smallest |

## Get OpenAPI Spec at build time

With Go, you cannot generate things at build time, but you can separate the
OpenAPI generation from the server, by using the
`(Server).OutputOpenAPISpec()` function.

```go title="main.go" showLineNumbers
package main

import (
"github.com/go-fuego/fuego"
)

func main() {
s := fuego.NewServer()

fuego.Get(s, "/", helloWorld)

if justGenerateOpenAPI { // A CLI flag, an env variable, etc.
s.OutputOpenAPISpec()
return
}

s.Run()
}
```

## Hide From OpenAPI Spec

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import FlowChart from '@site/src/components/FlowChart';

# Serialization / Deserialization

Serialization is the process of converting Go data into a format that can be stored or transmitted. Deserialization is the process of converting serialized data back into its original Go form.
Expand All @@ -8,8 +6,6 @@ The classic example is transforming **Go data into JSON** and back.

Fuego automatically serializes and deserializes inputs and outputs with standard `encoding/json` package.

<FlowChart selected="Serialization" />

## Serialize data

To serialize data, just return the data you want to serialize from your controller. It will be automatically serialized into JSON, XML, YAML, or HTML, depending on the `Accept` header in the request.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import FlowChart from '@site/src/components/FlowChart';

# Transformation

With Fuego, you can transform data coming in and out of your application. This is useful for a variety of reasons, such as:
Expand All @@ -10,8 +8,6 @@ With Fuego, you can transform data coming in and out of your application. This i
- Masking sensitive data
- And more...

<FlowChart selected="Transformation" />

## Input Transformation

Input transformation is the process of transforming the data coming **into** your application.
Expand All @@ -38,7 +34,7 @@ func (u *User) InTransform(ctx context.Context) error {
}

var _ fuego.InTransformer = (*User)(nil) // Ensure *User implements fuego.InTransformer
// This check is a classic example of Go's interface implementation check and we highly recommend to use it
// This check is a classic example of Go's interface implementation check and we highly recommend to use it
```

In the example above, we have a `User` struct with two fields: `FirstName` and `LastName`. We also have a method called `InTransform` that takes a `context.Context` and returns an `error`. This method is called before the data is unmarshaled into the `User` struct. In this method, we are transforming the `FirstName` to uppercase and trimming any whitespace from the `LastName`.
Expand Down
58 changes: 58 additions & 0 deletions documentation/docs/guides/validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Validation

Validation is the process of ensuring that the data provided to the application
is correct and meaningful.

With fuego, you have several options for validating data.

- struct tags with `go-validator`
- custom validation functions

## Struct tags

You can use struct tags to validate the data coming into your application.
This is a common pattern in Go and is used by many libraries,
and we use [`go-playground/validator`](https://github.com/go-playground/validator) to do so.

```go
type User struct {
FirstName string `json:"first_name" validate:"required"`
LastName string `json:"last_name" validate:"required"`
Age int `json:"age" validate:"gte=0,lte=130"`
Email string `json:"email" validate:"email"`
}
```

## Custom validation

You can also use Fuego's [Transformation](./transformation.md) methods to validate the data.

```go
package main

import (
"context"
"errors"
"strings"

"github.com/go-fuego/fuego"
)

type User struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}

func (u *User) InTransform(ctx context.Context) error {
u.FirstName = strings.ToUpper(u.FirstName)
u.LastName = strings.TrimSpace(u.LastName)

if u.FirstName == "" {
return errors.New("first name is required")
}
return nil
}

var _ fuego.InTransformer = (*User)(nil) // Ensure *User implements fuego.InTransformer
// This check is a classic example of Go's interface implementation check and we highly recommend to use it
```
13 changes: 0 additions & 13 deletions documentation/docs/guides/validation.mdx

This file was deleted.

14 changes: 8 additions & 6 deletions documentation/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ Try our [Hello World](./tutorials/01-hello-world.md)!
go run github.com/go-fuego/fuego/examples/hello-world@latest
```

This runs the code for a simple hello world server.
Look at all it generates from a simple code!
You'll get a URL to see the result in your browser.
This simple code snippet runs a 'Hello World' server.
See how much Fuego generates from just a few lines of code!
You'll even get a URL to view the result directly in your browser

```go showLineNumbers
package main
Expand All @@ -42,10 +42,12 @@ func helloWorld(c fuego.ContextNoBody) (string, error) {
}
```

## Try example from real Fuego source code in 3 sec
![Swagger UI](../static/img/hello-world-openapi.jpeg)

Try Fuego immediately by cloning [the repo](https://github.com/go-fuego/fuego)
and running one of our examples.
## Try examples with real source code in 3 sec

Just copy/paste these commands in your terminal,
you'll be iterating on a real example in no time.

```bash
git clone git@github.com:go-fuego/fuego.git
Expand Down
6 changes: 4 additions & 2 deletions documentation/docs/tutorials/02-crud.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ for the code generator of Fuego, but you can implement it in any way you want.
To implement the service, you need to slightly modify the
generated `controllers/books.go` and `main.go` files.

```go title="controllers/books.go" {8-9,28-39} showLineNumbers
```go title="controllers/books.go" {8-9,28-42} showLineNumbers
package controller

import (
Expand Down Expand Up @@ -53,7 +53,9 @@ type BooksService interface {

// Implement the BooksService interface
type RealBooksService struct {
BooksService // Embed the interface to satisfy it -this pattern is just there to make the code compile but you should implement all methods
// Embed the interface to satisfy it.
// This pattern is just there to make the code compile but you should implement all methods.
BooksService
}

func (s RealBooksService) GetBooks(id string) (Books, error) {
Expand Down
8 changes: 4 additions & 4 deletions documentation/docs/tutorials/03-hot-reload.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ see the changes in real-time without restarting the server.
This is very useful for development,
as it allows you to see the changes you make to your code immediately.

To enable hot reload, you need to install the `air` command-line tool:
To enable hot reload, you need to install the `air` command-line tool.

```sh
go install github.com/cosmtrek/air@latest
go install github.com/air-verse/air@latest
```

Then, create a `.air.toml` file in the root of your project with the following content:
Optionally, create a `.air.toml` configuration file to customize the hot reload behavior.

```sh
air init
```

Finally, simply the following command to start the server with hot reload:
Simply the following command to start the server with hot reload.

```sh
air
Expand Down
28 changes: 28 additions & 0 deletions documentation/docs/tutorials/rendering/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,31 @@ Fuego is not only capable to handle XML and JSON, it can also render HTML.

It supports templating with [html/template](https://pkg.go.dev/html/template),
[Templ](https://github.com/a-h/templ), and [Gomponents](https://github.com/maragudk/gomponents).

## Content Negotiation

Remember that Fuego handles [Content Negotiation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation),
so you can serve different content types based on the `Accept` header of the request.

Fuego also provides a helper to render HTML or JSON data for a single controller!

```go
package main

import (
"github.com/go-fuego/fuego"
)

func main() {
s := fuego.NewServer()

fuego.Get(s, "/", func(c fuego.ContextNoBody) (interface{}, error) {
return fuego.DataOrHTML(
data, // When asking for JSON/XML, this data will be returned
MyTemplateInjectedWithData(data), // When asking for HTML, this template will be rendered
), nil
})

s.Run()
}
```
4 changes: 2 additions & 2 deletions documentation/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ const config: Config = {
title: "Community",
items: [
{
label: "Twitter",
href: "https://twitter.com/FuegoFramework",
label: "Discord",
href: "https://discord.gg/tdGPnnxf",
},
{
label: "Youtube",
Expand Down

0 comments on commit 2da063c

Please sign in to comment.