feat: introduce embed package for static file management

This commit is contained in:
Prad N
2025-03-28 14:07:27 -04:00
parent cb40581a6f
commit 67a37e7d3f
24 changed files with 239 additions and 194 deletions

View File

@@ -11,7 +11,7 @@ builds:
release:
github:
owner: onsonr
owner: sonr-io
name: motr
name_template: "{{ .Tag }} | {{ .Env.RELEASE_DATE }}"
draft: false

View File

@@ -1,15 +1,91 @@
# https://taskfile.dev
version: "3"
silent: true
tasks:
sqlc:gen:
dir: internal
default:
cmds:
- sqlc generate
silent: true
- task: test
- task: gen
- task: build
templ:gen:
test:
desc: Runs tests
cmds:
- defer: rm -rf .task
- task: test:go
build:
desc: Builds code
cmds:
- rm -rf bin
- defer: rm -rf .task
- task: build:go
# - task: build:docker
gen:
desc: Generates code
cmds:
- defer: rm -rf .task
- task: gen:templ
- task: gen:sqlc
#
# Internal tasks
#
build:go:
desc: Builds Go code
env:
GOOS: js
GOARCH: wasm
sources:
- "main.go"
- "**/*.go"
generates:
- bin/motr.wasm
cmds:
- go build -o bin/motr.wasm .
build:docker:
desc: Builds Docker image
env:
GOOS: js
GOARCH: wasm
sources:
- "main.go"
- "**/*.go"
generates:
- bin/motr.wasm
cmds:
- go build -o bin/motr.wasm .
gen:templ:
internal: true
sources:
- "**/*.templ"
generates:
- "**/_templ.go"
cmds:
- templ generate
silent: true
gen:sqlc:
internal: true
sources:
- pkg/sink/query.sql
- pkg/sink/schema.sql
generates:
- pkg/models/db.go
- pkg/models/querier.go
- pkg/models/models.go
- pkg/models/query.sql.go
cmds:
- sqlc generate
test:go:
internal: true
sources:
- "**/*.go"
cmds:
- go test -v ./...

View File

@@ -7,8 +7,7 @@ COMMIT := $(shell git log -1 --format='%H')
all: generate build
build:
GOOS=js GOARCH=wasm go build -o bin/motr.wasm .
@task -t .taskfile.dist.yml build
generate:
@task -t .taskfile.dist.yml sqlc:gen
@task -t .taskfile.dist.yml templ:gen
@task -t .taskfile.dist.yml gen

View File

@@ -5,15 +5,15 @@ package app
import (
"github.com/labstack/echo/v4"
echomiddleware "github.com/labstack/echo/v4/middleware"
"github.com/onsonr/motr/internal/config"
"github.com/onsonr/motr/internal/context"
"github.com/onsonr/motr/internal/models"
"github.com/onsonr/motr/context"
"github.com/onsonr/motr/pkg/models"
"github.com/onsonr/motr/pkg/types"
)
type Vault = *echo.Echo
// New returns a new Vault instance
func New(config *config.Config, dbq *models.Queries) (Vault, error) {
func New(config *types.Config, dbq *models.Queries) (Vault, error) {
e := echo.New()
// Override default behaviors
e.IPExtractor = echo.ExtractIPDirect()

View File

@@ -1,49 +0,0 @@
package embed
import (
"github.com/onsonr/motr/internal/config"
)
// motr "github.com/onsonr/motr/pkg/config"
const SchemaVersion = 1
const (
AppManifestFileName = "app.webmanifest"
DWNConfigFileName = "dwn.json"
IndexHTMLFileName = "index.html"
MainJSFileName = "main.js"
ServiceWorkerFileName = "sw.js"
)
// // spawnVaultDirectory creates a new directory with the default files
//
// func NewVaultFS(cfg *Config) (files.Directory, error) {
// manifestBz, err := NewWebManifest()
// if err != nil {
// return nil, err
// }
// cnfBz, err := json.Marshal(cfg)
// if err != nil {
// return nil, err
// }
// return files.NewMapDirectory(map[string]files.Node{
// AppManifestFileName: files.NewBytesFile(manifestBz),
// DWNConfigFileName: files.NewBytesFile(cnfBz),
// IndexHTMLFileName: files.NewBytesFile(IndexHTML),
// MainJSFileName: files.NewBytesFile(MainJS),
// ServiceWorkerFileName: files.NewBytesFile(WorkerJS),
// }), nil
// }
//
// NewVaultConfig returns the default vault config
func NewVaultConfig(addr string, ucanCID string) *config.Config {
return &config.Config{
MotrToken: ucanCID,
MotrAddress: addr,
IpfsGatewayURL: "http://localhost:80",
SonrAPIURL: "http://localhost:1317",
SonrRPCURL: "http://localhost:26657",
SonrChainID: "sonr-testnet-1",
}
}

View File

@@ -1,47 +0,0 @@
package embed
import (
_ "embed"
"reflect"
"strings"
)
//go:embed index.html
var IndexHTML []byte
//go:embed main.js
var MainJS []byte
//go:embed sw.js
var WorkerJS []byte
func getSchema(structType interface{}) string {
t := reflect.TypeOf(structType)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return ""
}
var fields []string
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fieldName := toCamelCase(field.Name)
fields = append(fields, fieldName)
}
// Add "++" at the beginning, separated by a comma
return "++, " + strings.Join(fields, ", ")
}
func toCamelCase(s string) string {
if s == "" {
return s
}
if len(s) == 1 {
return strings.ToLower(s)
}
return strings.ToLower(s[:1]) + s[1:]
}

7
go.mod
View File

@@ -3,27 +3,20 @@ module github.com/onsonr/motr
go 1.23.4
require (
github.com/a-h/templ v0.3.819
github.com/apple/pkl-go v0.9.0
github.com/ipfs/boxo v0.26.0
github.com/labstack/echo/v4 v4.13.3
github.com/ncruces/go-sqlite3 v0.21.3
)
require (
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/ncruces/julianday v1.0.0 // indirect
github.com/onsonr/nebula v0.1.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/tetratelabs/wazero v1.8.2 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect

18
go.sum
View File

@@ -1,15 +1,5 @@
github.com/a-h/templ v0.3.819 h1:KDJ5jTFN15FyJnmSmo2gNirIqt7hfvBD2VXVDTySckM=
github.com/a-h/templ v0.3.819/go.mod h1:iDJKJktpttVKdWoTkRNNLcllRI+BlpopJc+8au3gOUo=
github.com/apple/pkl-go v0.9.0 h1:aA4Bh+WQ797p8nEnQhHzCahVuQP2HJ40ffSQWlAR5es=
github.com/apple/pkl-go v0.9.0/go.mod h1:5Hwil5tyZGrOekh7JXLZJvIAcGHb4gT19lnv4WEiKeI=
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf h1:dwGgBWn84wUS1pVikGiruW+x5XM4amhjaZO20vCjay4=
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/ipfs/boxo v0.26.0 h1:RRxEon7rJMy8ScVaTLncSZ5/nA6majYhRSbzc80snO8=
github.com/ipfs/boxo v0.26.0/go.mod h1:iHyc9cjoF7/zoiKVY65d2fBWRhoS2zx4cMk8hKgqrac=
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
@@ -23,10 +13,6 @@ github.com/ncruces/go-sqlite3 v0.21.3 h1:hHkfNQLcbnxPJZhC/RGw9SwP3bfkv/Y0xUHWsr1
github.com/ncruces/go-sqlite3 v0.21.3/go.mod h1:zxMOaSG5kFYVFK4xQa0pdwIszqxqJ0W0BxBgwdrNjuA=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/onsonr/nebula v0.1.0 h1:hVwq/rlCRGVxUhs2ZGkF/pSOEYg0k9/TuhzWMHjdV+c=
github.com/onsonr/nebula v0.1.0/go.mod h1:60FFGLF4fUfOeNURep3rndIoazpKg+lzfXL1WMxj4eA=
github.com/onsonr/nebula v0.1.1 h1:YBIbf4JSt8jVz6DI04fa7gKY9fBZ47YBIzwe3Nom+YQ=
github.com/onsonr/nebula v0.1.1/go.mod h1:1Dcmw5lB4dvKRKSp55B/iLmN4ejZ4vp1/EB/RzXetAQ=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@@ -37,10 +23,6 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=

View File

@@ -19,9 +19,8 @@ import (
_ "github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
vault "github.com/onsonr/motr/app"
"github.com/onsonr/motr/internal/models"
sink "github.com/onsonr/motr/internal/sink"
// motr "github.com/onsonr/motr/pkg/config"
"github.com/onsonr/motr/pkg/models"
sink "github.com/onsonr/motr/pkg/sink"
)
var (
@@ -64,6 +63,7 @@ func main() {
// return &config, err
// }
//
// createDB initializes and returns a configured database connection
func createDB() (*models.Queries, error) {
db, err := sql.Open("sqlite3", ":memory:")

142
pkg/embed/embed.go Normal file
View File

@@ -0,0 +1,142 @@
package embed
import (
"encoding/json"
"reflect"
"strings"
_ "embed"
"github.com/onsonr/motr/pkg/types"
)
//go:embed index.html
var IndexHTML []byte
//go:embed main.js
var MainJS []byte
//go:embed sw.js
var WorkerJS []byte
const SchemaVersion = 1
const (
AppManifestFileName = "app.webmanifest"
DWNConfigFileName = "dwn.json"
IndexHTMLFileName = "index.html"
MainJSFileName = "main.js"
ServiceWorkerFileName = "sw.js"
)
// // spawnVaultDirectory creates a new directory with the default files
//
// func NewVaultFS(cfg *Config) (files.Directory, error) {
// manifestBz, err := NewWebManifest()
// if err != nil {
// return nil, err
// }
// cnfBz, err := json.Marshal(cfg)
// if err != nil {
// return nil, err
// }
// return files.NewMapDirectory(map[string]files.Node{
// AppManifestFileName: files.NewBytesFile(manifestBz),
// DWNConfigFileName: files.NewBytesFile(cnfBz),
// IndexHTMLFileName: files.NewBytesFile(IndexHTML),
// MainJSFileName: files.NewBytesFile(MainJS),
// ServiceWorkerFileName: files.NewBytesFile(WorkerJS),
// }), nil
// }
//
// NewVaultConfig returns the default vault config
func NewVaultConfig(addr string, ucanCID string) *types.Config {
return &types.Config{
MotrToken: ucanCID,
MotrAddress: addr,
IpfsGatewayURL: "http://localhost:80",
SonrAPIURL: "http://localhost:1317",
SonrRPCURL: "http://localhost:26657",
SonrChainID: "sonr-testnet-1",
}
}
func NewWebManifest() ([]byte, error) {
return json.Marshal(baseWebManifest)
}
var baseWebManifest = types.WebManifest{
Name: "Sonr Vault",
ShortName: "Sonr.ID",
StartURL: "/index.html",
Display: "standalone",
DisplayOverride: []string{
"fullscreen",
"minimal-ui",
},
Icons: []types.IconDefinition{
{
Src: "/icons/icon-192x192.png",
Sizes: "192x192",
Type: "image/png",
},
},
ServiceWorker: types.ServiceWorker{
Scope: "/",
Src: "/sw.js",
UseCache: true,
},
ProtocolHandlers: []types.ProtocolHandler{
{
Scheme: "did.sonr",
URL: "/resolve/sonr/%s",
},
{
Scheme: "did.eth",
URL: "/resolve/eth/%s",
},
{
Scheme: "did.btc",
URL: "/resolve/btc/%s",
},
{
Scheme: "did.usdc",
URL: "/resolve/usdc/%s",
},
{
Scheme: "did.ipfs",
URL: "/resolve/ipfs/%s",
},
},
}
func getSchema(structType interface{}) string {
t := reflect.TypeOf(structType)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return ""
}
var fields []string
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fieldName := toCamelCase(field.Name)
fields = append(fields, fieldName)
}
// Add "++" at the beginning, separated by a comma
return "++, " + strings.Join(fields, ", ")
}
func toCamelCase(s string) string {
if s == "" {
return s
}
if len(s) == 1 {
return strings.ToLower(s)
}
return strings.ToLower(s[:1]) + s[1:]
}

View File

@@ -1,4 +1,4 @@
package config
package types
type Config struct {
// TODO

View File

@@ -1,55 +1,4 @@
package embed
import "encoding/json"
func NewWebManifest() ([]byte, error) {
return json.Marshal(baseWebManifest)
}
var baseWebManifest = WebManifest{
Name: "Sonr Vault",
ShortName: "Sonr.ID",
StartURL: "/index.html",
Display: "standalone",
DisplayOverride: []string{
"fullscreen",
"minimal-ui",
},
Icons: []IconDefinition{
{
Src: "/icons/icon-192x192.png",
Sizes: "192x192",
Type: "image/png",
},
},
ServiceWorker: ServiceWorker{
Scope: "/",
Src: "/sw.js",
UseCache: true,
},
ProtocolHandlers: []ProtocolHandler{
{
Scheme: "did.sonr",
URL: "/resolve/sonr/%s",
},
{
Scheme: "did.eth",
URL: "/resolve/eth/%s",
},
{
Scheme: "did.btc",
URL: "/resolve/btc/%s",
},
{
Scheme: "did.usdc",
URL: "/resolve/usdc/%s",
},
{
Scheme: "did.ipfs",
URL: "/resolve/ipfs/%s",
},
},
}
package types
type WebManifest struct {
// Required fields

View File

@@ -1,11 +1,11 @@
version: "2"
sql:
- engine: "sqlite"
queries: "./sink/query.sql"
schema: "./sink/schema.sql"
queries: "./pkg/sink/query.sql"
schema: "./pkg/sink/schema.sql"
gen:
go:
emit_interface: true
emit_json_tags: true
package: "models"
out: "./models"
out: "./pkg/models"