Tutorial 56
Write some static content.
Example
// Copyright (c) 2025 worldiety GmbH
//
// This file is part of the NAGO Low-Code Platform.
// Licensed under the terms specified in the LICENSE file.
//
// SPDX-License-Identifier: Custom-License
package main
import (
"fmt"
"github.com/worldiety/option"
"go.wdy.de/nago/application"
"go.wdy.de/nago/application/hapi"
cfghapi "go.wdy.de/nago/application/hapi/cfg"
"go.wdy.de/nago/auth"
"go.wdy.de/nago/pkg/std"
"go.wdy.de/nago/pkg/stoplight"
"go.wdy.de/nago/presentation/core"
. "go.wdy.de/nago/presentation/ui"
"go.wdy.de/nago/web/vuejs"
"mime/multipart"
"net/url"
"time"
)
func main() {
application.Configure(func(cfg *application.Configurator) {
cfg.SetApplicationID("de.worldiety.tutorial_56")
cfg.SetSemanticVersion("0.1.2")
cfg.SetName("Tutorial 56")
cfg.Serve(vuejs.Dist())
// we have multiple frontend openapi distributions provided, e.g. swagger, redocly or stoplight.
// Note, that ALL frontends are broken in one or another way. E.g. swagger does not support even simplest
// recursions and stoplight does not support multipart files.
cfg.Serve(stoplight.Dist())
//cfg.Serve(swagger.Dist())
//cfg.Serve(redocly.Dist())
cfg.SetDecorator(cfg.NewScaffold().
Decorator())
option.MustZero(cfg.StandardSystems())
std.Must(std.Must(cfg.UserManagement()).UseCases.EnableBootstrapAdmin(time.Now().Add(time.Hour), "%6UbRsCuM8N$auy"))
api := std.Must(cfghapi.Enable(cfg)).API
tokens := std.Must(cfg.TokenManagement())
configureMyAPI(api, tokens)
cfg.RootViewWithDecoration(".", func(wnd core.Window) core.View {
return VStack(Text("hello world")).
Frame(Frame{}.MatchScreen())
})
}).
Run()
}
func configureMyAPI(api *hapi.API, tokens application.TokenManagement) {
type StackElement struct {
Line int
File string
}
type Exception struct {
Name string `json:"name"`
Stack []StackElement `json:"stack"`
Cause *Exception `json:"cause"`
}
type UploadMetadata struct {
DeviceName string
AppVersion string
KeyValues map[string]string
Exception *Exception
}
type UploadRequest struct {
TestHeader string
TestQuery string
Metadata UploadMetadata
Files []*multipart.FileHeader
Subject auth.Subject
}
type SomeID string
type NestedResponse struct {
ID SomeID `json:"id,omitempty" example:"1234"`
Url url.URL `json:"url,omitempty"`
OtherNum int32 `json:"other_num,omitempty"`
}
type UploadResponse struct {
ID string `json:"id"`
Yes bool `json:"yes" doc:"say no" required:"true"`
Num int `json:"num" supportingText:"Irgendeine Nummer"`
When time.Time `json:"when"`
Nested NestedResponse `json:"nested"`
}
hapi.Post[UploadRequest](api, hapi.Operation{Path: "/api/v1/events", Summary: "Create a new event", Description: "A post will take the given meta data and files and persists it as an event. A unique tracking code is returned."}).
Request(
hapi.BearerAuth[UploadRequest](tokens.UseCases.AuthenticateSubject, func(dst *UploadRequest, subject auth.Subject) error {
dst.Subject = subject
return nil
}),
hapi.StrFromHeader(hapi.StrParam[UploadRequest]{Name: "test-header", IntoModel: func(dst *UploadRequest, value string) error {
dst.TestHeader = value
return nil
}}),
hapi.StrFromQuery(hapi.StrParam[UploadRequest]{Name: "test-query", IntoModel: func(dst *UploadRequest, value string) error {
dst.TestQuery = value
return nil
}}),
// this can be a simple alternative
/*hapi.JSONFromBody(func(dst *UploadRequest, model UploadMetadata) error {
dst.Metadata = model
return nil
}),*/
hapi.JSONFromFormField("meta", func(dst *UploadRequest, model UploadMetadata) error {
dst.Metadata = model
return nil
}),
hapi.FilesFromFormField("files", func(dst *UploadRequest, files []*multipart.FileHeader) error {
dst.Files = files
return nil
}),
).
Response(
hapi.ToJSON[UploadRequest, UploadResponse](func(in UploadRequest) (UploadResponse, error) {
fmt.Printf("%+v\n", in)
return UploadResponse{ID: "1234-" + in.TestHeader, When: time.Now()}, nil
}),
/*hapi.ToBinary[UploadRequest](func(in UploadRequest) (io.Reader, error) {
return bytes.NewReader([]byte(in.TestHeader)), nil
}),*/
)
}
Info
More static content.
Image