gonertia

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Feb 3, 2023 License: MIT Imports: 19 Imported by: 0

README

Gonertia

gonertia

Gonertia is a Inertia.js server-side adapter for Golang. Visit inertiajs.com to learn more.

Audit Workflow Go Report Card Go Reference MIT license

Introdution

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
  • SSR
  • CLI

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"
    "http"
    "time"
    
    inertia "github.com/romsar/gonertia"
)

func main() {
    i, err := inertia.New(
        "https://yourwebsite.com",
        "./ui/templates/root.html",
    )
    if err != nil {
        log.Fatal(err)
    }

    // Now create your HTTP server.
    // Gonertia works well with standard http handlers,
    // but you are free to use some frameworks 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 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">
    <title>title</title>
    {{ .inertiaHead }}
</head>

<body>
{{ .inertia }}
<script src="/static/js/app.js"></script>
</body>
</html>
More examples
Load root template using embed
import "embed"

//go:embed templates
var templateFS embed.FS

// ...

i, err := inertia.New(
    /* ... */
    inertia.WithTemplateFS(templateFS),
)
Set asset version (learn more)
i, err := inertia.New(
    /* ... */
    inertia.WithVersion("some-version"), // by any string
    inertia.WithAssetURL("/static/js/1f0f8sc6.js"), // by asset url
    inertia.WithManifestFile("./ui/manifest.json"), // by manifest file
)
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(somelogger.New()),
    // or inertia.WithoutLogger(),
)
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, error) { return "prop", nil },
    "lazy": inertia.LazyProp(func () (any, error) {
        return "prop", nil
    },
}

i.Render(w, r, "Some/Page", props)
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.

Share template data (learn more)
i.ShareTemplateData("title", "Home page")
<title>{{ .title }}</title>
Share template func
i.ShareTemplateFunc("trim", strings.Trim)
<title>{{ trim "foo bar" }}</title>
Pass template data via context (in middleware)
ctx := i.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 := i.WithProp(r.Context(), "name", "Roman")

// pass it to the next middleware or inertia.Render function using r.WithContext(ctx).
Testing

Of course, this package provides convenient interfaces for testing!

func TestHomepage(t *testing.T) {
    body := ... // get an HTML using httptest package or real HTTP request. 
	
    // ...
	
    assertable := inertia.AssertInertia(t, body) // io.Reader body
    // OR
    assertable := inertia.AssertInertiaFromBytes(t, body) // []byte body
    // OR
    assertable := inertia.AssertInertiaFromString(t, body) // 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"}
}

Credits

This package is based on inertiajs/inertia-laravel and uses some parts 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.

Types

type AssertableInertia added in v1.0.2

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

func AssertInertia added in v1.0.2

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

func AssertInertiaFromBytes added in v1.0.2

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

func AssertInertiaFromString added in v1.0.2

func AssertInertiaFromString(t t, body string) AssertableInertia

func (AssertableInertia) AssertComponent added in v1.0.2

func (i AssertableInertia) AssertComponent(component string)

func (AssertableInertia) AssertProps added in v1.0.2

func (i AssertableInertia) AssertProps(props Props)

func (AssertableInertia) AssertURL added in v1.0.2

func (i AssertableInertia) AssertURL(url string)

func (AssertableInertia) AssertVersion added in v1.0.2

func (i AssertableInertia) AssertVersion(version string)

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(url, rootTemplatePath string, opts ...Option) (*Inertia, error)

New initializes and returns Inertia.

func (*Inertia) FlushSharedProps

func (i *Inertia) FlushSharedProps()

FlushSharedProps flushes shared props.

func (*Inertia) FlushSharedTemplateData

func (i *Inertia) FlushSharedTemplateData()

FlushSharedTemplateData flushes shared template data.

func (*Inertia) FlushSharedTemplateFuncs added in v1.0.1

func (i *Inertia) FlushSharedTemplateFuncs()

FlushSharedTemplateFuncs flushes the shared template func map.

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 return 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.

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.

func (*Inertia) WithProp

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

WithProp appends prop value to the passed context.Context.

func (*Inertia) WithProps

func (i *Inertia) WithProps(ctx context.Context, props Props) context.Context

WithProps appends props values to the passed context.Context.

func (*Inertia) WithTemplateData

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

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

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 WithAssetURL

func WithAssetURL(url string) Option

WithAssetURL returns Option that will set Inertia's version based on asset url.

func WithContainerID

func WithContainerID(id string) Option

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

func WithLogger

func WithLogger(log logger) Option

WithLogger returns Option that will set Inertia's logger.

func WithManifestFile

func WithManifestFile(path string) Option

WithManifestFile returns Option that will set Inertia's version based on manifest file.

func WithMarshalJSON

func WithMarshalJSON(f marshallJSON) Option

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

func WithTemplateFS

func WithTemplateFS(templateFS fs.FS) Option

WithTemplateFS returns Option that will set Inertia's templateFS.

func WithVersion

func WithVersion(version string) Option

WithVersion returns Option that will set Inertia's version.

func WithoutLogger

func WithoutLogger() Option

WithoutLogger returns Option that will unset Inertia's logger. Actually set a logger with io.Discard output.

type Props

type Props map[string]any

Props are key-value data structure, that will be available in your front-end component.

Jump to

Keyboard shortcuts

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