jet icon indicating copy to clipboard operation
jet copied to clipboard

Adding support for Go 1.16's FS interface

Open advdv opened this issue 3 years ago • 5 comments

Go 1.16 introduces the fs package and a FS interface. Implementing a Jet loader for this seems like an ideal use case. Are there any plans for this, would it be easy?

EDIT: actually, maybe it is as simple as this?

type StdFileSystemLoader struct{ fs.FS }

func (l StdFileSystemLoader) Open(templatePath string) (io.ReadCloser, error) {
	return l.FS.Open(templatePath)
}

func (l StdFileSystemLoader) Exists(templatePath string) bool {
	_, err := l.Open(templatePath)
	return err == nil && !os.IsNotExist(err)
}

advdv avatar Mar 18 '21 10:03 advdv

Yes, that adapter should be all you need to use 1.16's FS interface! Let me know if it works, It probably makes sense to have this boilerplate directly in Jet.

sauerbraten avatar Mar 18 '21 14:03 sauerbraten

I actually just found a way to do this without an extra type by using jets loaders/httpfs package:

//go:embed *.html
var tfs embed.FS

// loader allows for loading templates
func loader() (jet.Loader, error) {
	return httpfs.NewLoader(http.FS(tfs))
}

it is a bit weird to require a "httpfs/http" package for something that just have to deal with filesystems but it works as expected.

advdv avatar Mar 25 '21 11:03 advdv

@advanderveer How did you pass this func loader to Jet Engine so it is loading files from tfs ?

I have someting like this: main.go:

//go:embed templates
var assets embed.FS //stored in: Repo.App.TemplatesFS

handlers.go:

var view = jet.NewSet(
	jet.NewOSFileSystemLoader("./templates"),
	jet.InDevelopmentMode(), // remove in production
)

func loader() (jet.Loader, error) {
	return httpfs.NewLoader(http.FS(Repo.App.TemplatesFS))
}

but I have no idea how to link this together :-)

replay111 avatar Sep 27 '21 14:09 replay111

Hello again,

I've tried this way:

var view *jet.Set

func init() {
	httpFsLoader, err := loader()
	if err != nil {
		log.Panicln("error: ", err)
	}
	view = jet.NewSet(
		httpFsLoader,
		jet.InDevelopmentMode(),
	)
}

func loader() (jet.Loader, error) {
	return httpfs.NewLoader(http.FS(Repo.App.TemplatesFS))
}

where Repo.App.TemplatesFS stores:

type ApplicationConfig struct {
	InfoLog       *log.Logger
	ErrorLog      *log.Logger
	InDevelopment bool
	Session       *scs.SessionManager
	TemplatesFS   embed.FS
}

//go:embed templates
var assets embed.FS
var app config.ApplicationConfig

app.TemplatesFS = assets

But compiler does not like this part:

func loader() (jet.Loader, error) {
	return httpfs.NewLoader(http.FS(Repo.App.TemplatesFS))
}

error: cannot use httpfs.NewLoader(http.FS(Repo.App.TemplatesFS)) (value of type jet.Loader) as jet.Loader value in return statement: wrong type for method Open (have func(templatePath string) (io.ReadCloser, error), want func(templatePath string) (io.ReadCloser, error))compilerInvalidIfaceAssign

but Repo.App.TemplatesFS is embed.FS so it is the same type as in example from @advanderveer

replay111 avatar Sep 28 '21 16:09 replay111

Ok I also found solution for my case:

func InitTemplateSystem(assets embed.FS) *jet.Set {
	httpFsLoader, err := httpfs.NewLoader(http.FS(assets))
	if err != nil {
		log.Panicln("error: ", err)
	}
	return jet.NewSet(httpFsLoader, jet.InDevelopmentMode())
}

the error was caused by wrong import - VSCode is suggesting:

	"github.com/CloudyKit/jet/v6"
	"github.com/CloudyKit/jet/loaders/httpfs"

instead of:

	"github.com/CloudyKit/jet/v6"
	"github.com/CloudyKit/jet/v6/loaders/httpfs"

Now I am calling: app.View = handlers.InitTemplateSystem(web.WebFiles) in my main.go file and initialize once Jet engine. Web files are loaded in "./web/web.go" module:

import "embed"

//go:embed templates
var WebFiles embed.FS

which is on the same level as templates directory.

Maybe not the best solution (because of passing Jet engine to app config - which I do not like very much for now) but for the beginning I think it is ok. When I learn more then problably will change that to maybe something more sophisticated.

replay111 avatar Sep 29 '21 15:09 replay111