gonertia

package module
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 15, 2024 License: MIT Imports: 16 Imported by: 0

README

Gonertia

gonertia

Gonertia is a well-tested and zero-dependency Inertia.js server-side adapter for Golang. Visit inertiajs.com to learn more.

Audit Workflow Go Report Card Go Reference MIT license

Introduction

Inertia allows you to create fully client-side rendered, single-page apps, without the complexity that comes with modern SPAs. It does this by leveraging existing server-side patterns that you already love.

This package based on the official Laravel adapter for Inertia.js: inertiajs/inertia-laravel.

Roadmap

  • Tests
  • Helpers for testing
  • Helpers for validation errors
  • Examples
  • SSR

Installation

Install using go get command:

go get github.com/romsar/gonertia

Usage

Basic example

Initialize Gonertia in your main.go:

package main

import (
    "log"
    "net/http"
	
    inertia "github.com/romsar/gonertia"
)

func main() {
    i, err := inertia.New("resources/views/root.html") // put here HTML or path to the root template file
    if err != nil {
        log.Fatal(err)
    }

    // Now create your HTTP server.
    // Gonertia works well with standard http server library,
    // but you are free to use some external routers like Gorilla Mux or Chi.
    mux := http.NewServeMux()

    mux.Handle("/home", i.Middleware(homeHandler(i)))
}

func homeHandler(i *inertia.Inertia) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        err := i.Render(w, r, "Home/Index", inertia.Props{
            "some": "data",
        })
		
        if err != nil {
            handleServerErr(w, err)
            return
        }
    }

    return http.HandlerFunc(fn)
}

Create root.html template:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Put here your styles, meta and other stuff -->
    {{ .inertiaHead }}
</head>

<body>
{{ .inertia }}
<script type="module" src="/build/assets/app.js"></script>
</body>
</html>

You can also find more examples and starter kits in examples folder or in section above.

More examples
Set asset version (learn more)
i, err := inertia.New(
    /* ... */
    inertia.WithVersion("some-version"), // by any string
    inertia.WithVersionFromFile("./public/build/manifest.json"), // by file checksum
)
Replace standard JSON marshall function
import jsoniter "github.com/json-iterator/go"

// ...

i, err := inertia.New(
    /* ... */, 
    inertia.WithMarshalJSON(jsoniter.Marshal),
)
Use your logger
i, err := inertia.New(
    /* ... */
    inertia.WithLogger(), // default logger
    inertia.WithLogger(somelogger.New()), // custom logger
)
Set custom container id
i, err := inertia.New(
    /* ... */
    inertia.WithContainerID("inertia"),
)
Closure and lazy props (learn more)
props := inertia.Props{
    "regular": "prop",
    "closure": func () (any) { return "prop" },
    "closure_with_err": func () (any, error) { return "prop", nil },
    "lazy": inertia.LazyProp(func () (any, error) {
        return "prop", nil
    },
}

i.Render(w, r, "Some/Page", props)

Also, Gonertia have support for always props (learn more):

props := inertia.Props{
    "foo": AlwaysProp(func() any { return "bar" }),
}
Redirects (learn more)
func homeHandler(i *inertia.Inertia) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        i.Location(w, r, "/some-url")
    }

    return http.HandlerFunc(fn)
}

NOTES: If response is empty - user will be redirected to the previous url, just like in Laravel official adapter.

To manually redirect back, you can use Back helper:

i.Back(w, r)
Share template data (learn more)
i.ShareTemplateData("title", "Home page")
<h1>{{ .title }}</h1>
Share template func
i.ShareTemplateFunc("trim", strings.TrimSpace)
<h1>{{ trim " foo bar " }}</h1>
Pass template data via context (in middleware)
ctx := inertia.WithTemplateData(r.Context(), "title", "Home page")

// pass it to the next middleware or inertia.Render function using r.WithContext(ctx).
Share prop globally (learn more)
i.ShareProp("name", "Roman")
Pass props via context (in middleware)
ctx := inertia.WithProp(r.Context(), "name", "Roman")
// or inertia.WithProps(r.Context(), inertia.Props{"name": "Roman"})

// pass it to the next middleware or inertia.Render function using r.WithContext(ctx).
Validation errors (learn more)
ctx := inertia.WithValidationError(r.Context(), "some_field", "some error")
// or inertia.WithValidationErrors(r.Context(), inertia.ValidationErrors{"some_field": "some error"})

// pass it to the next middleware or inertia.Render function using r.WithContext(ctx).
SSR (Server Side Rendering) (learn more)

To enable server side rendering you have to provide an option in place where you initialize Gonertia:

i, err := inertia.New(
/* ... */
    inertia.WithSSR(), // default is http://127.0.0.1:13714
    inertia.WithSSR("http://127.0.0.1:1234"), // custom url
)

Also, you have to use asset bundling tools like Vite or Webpack (especially with Laravel Mix). The setup will vary depending on this choice, you can read more about it in official docs or check an example that works on Vite.

Testing

Of course, this package provides convenient interfaces for testing!

func TestHomepage(t *testing.T) {
    body := ... // get an HTML or JSON using httptest package or real HTTP request. 
	
    // ...
	
    assertable := inertia.Assert(t, body) // from io.Reader body
    // OR
    assertable := inertia.AssertFromBytes(t, body) // from []byte body
    // OR
    assertable := inertia.AssertFromString(t, body) // from string body
	
    // now you can do assertions using assertable.Assert[...] methods:
    assertable.AssertComponent("Foo/Bar")
    assertable.AssertVersion("foo bar")
    assertable.AssertURL("https://example.com")
    assertable.AssertProps(inertia.Props{"foo": "bar"})

    // or work with the data yourself:
    assertable.Component // Foo/Bar
    assertable.Version // foo bar
    assertable.URL // https://example.com
    assertable.Props // inertia.Props{"foo": "bar"}
    assertable.Body // full response body
}

More community adapters

Also, you can check one more golang adapter called petaki/inertia-go.

Full list of community adapters is located on inertiajs.com.

Credits

This package is based on inertiajs/inertia-laravel and uses some ideas of petaki/inertia-go.

License

Gonertia is released under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsInertiaRequest

func IsInertiaRequest(r *http.Request) bool

IsInertiaRequest returns true if the request is an Inertia request.

func WithProp added in v1.1.0

func WithProp(ctx context.Context, key string, val any) context.Context

WithProp appends prop value to the passed context.Context.

func WithProps added in v1.1.0

func WithProps(ctx context.Context, props Props) context.Context

WithProps appends props values to the passed context.Context.

func WithTemplateData added in v1.1.0

func WithTemplateData(ctx context.Context, key string, val any) context.Context

WithTemplateData appends template data value to the passed context.Context.

func WithValidationError added in v1.1.0

func WithValidationError(ctx context.Context, key string, msg any) context.Context

WithValidationError appends validation error to the passed context.Context.

func WithValidationErrors added in v1.1.0

func WithValidationErrors(ctx context.Context, errors ValidationErrors) context.Context

WithValidationErrors appends validation errors to the passed context.Context.

Types

type AlwaysProp added in v1.0.7

type AlwaysProp func() any

AlwaysProp is a property value that will always evaluated.

https://github.com/inertiajs/inertia-laravel/pull/627

type AssertableInertia added in v1.0.2

type AssertableInertia struct {
	Body io.Reader
	// contains filtered or unexported fields
}

AssertableInertia is an Inertia response struct with assert methods.

func Assert added in v1.0.4

func Assert(t t, body io.Reader) AssertableInertia

Assert creates AssertableInertia from the io.Reader body.

func AssertFromBytes added in v1.0.4

func AssertFromBytes(t t, body []byte) AssertableInertia

AssertFromBytes creates AssertableInertia from the bytes body.

func AssertFromString added in v1.0.4

func AssertFromString(t t, body string) AssertableInertia

AssertFromString creates AssertableInertia from the string body.

func (AssertableInertia) AssertComponent added in v1.0.2

func (i AssertableInertia) AssertComponent(want string)

AssertComponent verifies that component from Inertia response and the passed component are the same.

func (AssertableInertia) AssertProps added in v1.0.2

func (i AssertableInertia) AssertProps(want Props)

AssertProps verifies that props from Inertia response and the passed props are the same.

func (AssertableInertia) AssertURL added in v1.0.2

func (i AssertableInertia) AssertURL(want string)

AssertURL verifies that url from Inertia response and the passed url are the same.

func (AssertableInertia) AssertVersion added in v1.0.2

func (i AssertableInertia) AssertVersion(want string)

AssertVersion verifies that version from Inertia response and the passed version are the same.

type Inertia

type Inertia struct {
	// contains filtered or unexported fields
}

Inertia is a main Gonertia structure, which contains all the logic for being an Inertia adapter.

func New

func New(rootTemplate string, opts ...Option) (*Inertia, error)

New initializes and returns Inertia.

func (*Inertia) Back added in v1.0.5

func (i *Inertia) Back(w http.ResponseWriter, r *http.Request, status ...int)

Back creates redirect response to the previous url.

func (*Inertia) Location

func (i *Inertia) Location(w http.ResponseWriter, r *http.Request, url string, status ...int)

Location creates redirect response.

If request was made by Inertia - sets status to 409 and url will be in "X-Inertia-Location" header. Otherwise, it will do an HTTP redirect with specified status (default is 302 for GET, 303 for POST/PUT/PATCH).

func (*Inertia) Middleware

func (i *Inertia) Middleware(next http.Handler) http.Handler

Middleware returns Inertia middleware handler.

All of your handlers that can be handled by the Inertia should be under this middleware.

func (*Inertia) Render

func (i *Inertia) Render(w http.ResponseWriter, r *http.Request, component string, props ...Props) (err error)

Render returns response with Inertia data.

If request was made by Inertia - it will return data in JSON format. Otherwise, it will return HTML with root template.

If SSR is enabled, pre-renders JavaScript and return HTML (https://inertiajs.com/server-side-rendering).

func (*Inertia) ShareProp

func (i *Inertia) ShareProp(key string, val any)

ShareProp adds passed prop to shared props.

func (*Inertia) ShareTemplateData

func (i *Inertia) ShareTemplateData(key string, val any)

ShareTemplateData adds passed data to shared template data.

func (*Inertia) ShareTemplateFunc

func (i *Inertia) ShareTemplateFunc(key string, val any)

ShareTemplateFunc adds passed value to the shared template func map.

func (*Inertia) SharedProp

func (i *Inertia) SharedProp(key string) (any, bool)

SharedProp return the shared prop.

func (*Inertia) SharedProps

func (i *Inertia) SharedProps() Props

SharedProps returns shared props.

type LazyProp

type LazyProp func() (any, error)

LazyProp is a property value that will only evaluated then needed.

https://inertiajs.com/partial-reloads

type Option

type Option func(i *Inertia) error

Option is an option parameter that modifies Inertia.

func WithContainerID

func WithContainerID(id string) Option

WithContainerID returns Option that will set Inertia's container id.

func WithLogger

func WithLogger(logs ...logger) Option

WithLogger returns Option that will set Inertia's logger.

func WithMarshalJSON

func WithMarshalJSON(f marshallJSON) Option

WithMarshalJSON returns Option that will set Inertia's marshallJSON func.

func WithSSR added in v1.1.0

func WithSSR(url ...string) Option

WithSSR returns Option that will enable server side rendering on Inertia.

func WithVersion

func WithVersion(version string) Option

WithVersion returns Option that will set Inertia's version.

func WithVersionFromFile added in v1.1.0

func WithVersionFromFile(path string) Option

WithVersionFromFile returns Option that will set Inertia's version based on file checksum.

type Props

type Props map[string]any

Props are the data that will be transferred and will be available in the front-end component.

func PropsFromContext added in v1.0.5

func PropsFromContext(ctx context.Context) (Props, error)

PropsFromContext returns props from the context.

type TemplateData

type TemplateData map[string]any

TemplateData are data that will be available in the root template.

func TemplateDataFromContext added in v1.0.5

func TemplateDataFromContext(ctx context.Context) (TemplateData, error)

TemplateDataFromContext returns template data from the context.

type TemplateFuncs added in v1.1.0

type TemplateFuncs map[string]any

TemplateFuncs are functions that will be available in the root template.

type ValidationErrors added in v1.0.5

type ValidationErrors map[string]any

ValidationErrors are messages, that will be stored in the "errors" prop.

func ValidationErrorsFromContext added in v1.0.5

func ValidationErrorsFromContext(ctx context.Context) (ValidationErrors, error)

ValidationErrorsFromContext returns validation errors from the context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL