mirror of
https://github.com/onsonr/sonr.git
synced 2025-03-10 13:07:09 +00:00
feat: implement HTMX for dynamic updates
This commit is contained in:
parent
ddacc127c6
commit
f8974b3d1f
21
go.mod
21
go.mod
@ -1,6 +1,6 @@
|
|||||||
module github.com/onsonr/sonr
|
module github.com/onsonr/sonr
|
||||||
|
|
||||||
go 1.23.3
|
go 1.23.4
|
||||||
|
|
||||||
// overrides
|
// overrides
|
||||||
replace (
|
replace (
|
||||||
@ -67,14 +67,16 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||||
github.com/gtank/merlin v0.1.1
|
github.com/gtank/merlin v0.1.1
|
||||||
|
github.com/ipfs/boxo v0.26.0
|
||||||
github.com/ipfs/go-cid v0.4.1
|
github.com/ipfs/go-cid v0.4.1
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/libp2p/go-libp2p v0.37.2
|
github.com/libp2p/go-libp2p v0.38.1
|
||||||
github.com/mr-tron/base58 v1.2.0
|
github.com/mr-tron/base58 v1.2.0
|
||||||
github.com/multiformats/go-multibase v0.2.0
|
github.com/multiformats/go-multibase v0.2.0
|
||||||
github.com/multiformats/go-multicodec v0.9.0
|
github.com/multiformats/go-multicodec v0.9.0
|
||||||
github.com/multiformats/go-multihash v0.2.3
|
github.com/multiformats/go-multihash v0.2.3
|
||||||
github.com/multiformats/go-varint v0.0.7
|
github.com/multiformats/go-varint v0.0.7
|
||||||
|
github.com/onsonr/motr v0.0.0-20250106200953-0f9e40a14ad8
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/spf13/cast v1.7.1
|
github.com/spf13/cast v1.7.1
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.8.1
|
||||||
@ -100,6 +102,7 @@ require (
|
|||||||
github.com/99designs/keyring v1.2.1 // indirect
|
github.com/99designs/keyring v1.2.1 // indirect
|
||||||
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
|
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
|
||||||
github.com/DataDog/zstd v1.5.5 // indirect
|
github.com/DataDog/zstd v1.5.5 // indirect
|
||||||
|
github.com/apple/pkl-go v0.9.0 // indirect
|
||||||
github.com/aws/aws-sdk-go v1.55.5 // indirect
|
github.com/aws/aws-sdk-go v1.55.5 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||||
@ -124,6 +127,7 @@ require (
|
|||||||
github.com/cosmos/iavl v1.1.2 // indirect
|
github.com/cosmos/iavl v1.1.2 // indirect
|
||||||
github.com/cosmos/ics23/go v0.10.0 // indirect
|
github.com/cosmos/ics23/go v0.10.0 // indirect
|
||||||
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
|
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
|
||||||
|
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
|
||||||
github.com/creachadair/atomicfile v0.3.1 // indirect
|
github.com/creachadair/atomicfile v0.3.1 // indirect
|
||||||
github.com/creachadair/tomledit v0.0.24 // indirect
|
github.com/creachadair/tomledit v0.0.24 // indirect
|
||||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||||
@ -204,7 +208,6 @@ require (
|
|||||||
github.com/mtibben/percent v0.2.1 // indirect
|
github.com/mtibben/percent v0.2.1 // indirect
|
||||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||||
github.com/multiformats/go-multiaddr v0.14.0 // indirect
|
|
||||||
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
|
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
|
||||||
github.com/oklog/run v1.1.0 // indirect
|
github.com/oklog/run v1.1.0 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
@ -231,6 +234,8 @@ require (
|
|||||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||||
github.com/tidwall/btree v1.7.0 // indirect
|
github.com/tidwall/btree v1.7.0 // indirect
|
||||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||||
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
github.com/zondax/hid v0.9.2 // indirect
|
github.com/zondax/hid v0.9.2 // indirect
|
||||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||||
go.etcd.io/bbolt v1.3.10 // indirect
|
go.etcd.io/bbolt v1.3.10 // indirect
|
||||||
@ -239,18 +244,16 @@ require (
|
|||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
go.opentelemetry.io/otel v1.31.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.31.0 // indirect
|
go.opentelemetry.io/otel/metric v1.31.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.31.0 // indirect
|
|
||||||
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d // indirect
|
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
|
||||||
golang.org/x/net v0.32.0 // indirect
|
golang.org/x/net v0.33.0 // indirect
|
||||||
golang.org/x/oauth2 v0.23.0 // indirect
|
golang.org/x/oauth2 v0.24.0 // indirect
|
||||||
golang.org/x/sync v0.10.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.28.0 // indirect
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
golang.org/x/term v0.27.0 // indirect
|
golang.org/x/term v0.27.0 // indirect
|
||||||
golang.org/x/text v0.21.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.8.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
|
||||||
google.golang.org/api v0.172.0 // indirect
|
google.golang.org/api v0.172.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
|
||||||
|
32
go.sum
32
go.sum
@ -843,6 +843,8 @@ github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0I
|
|||||||
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
|
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
|
||||||
github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg=
|
github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg=
|
||||||
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
|
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
|
||||||
|
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/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||||
@ -977,6 +979,8 @@ github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5n
|
|||||||
github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8=
|
github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
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/creachadair/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q=
|
github.com/creachadair/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q=
|
||||||
github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU=
|
github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU=
|
||||||
github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ=
|
github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ=
|
||||||
@ -1351,6 +1355,8 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt
|
|||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/ipfs/boxo v0.26.0 h1:RRxEon7rJMy8ScVaTLncSZ5/nA6majYhRSbzc80snO8=
|
||||||
|
github.com/ipfs/boxo v0.26.0/go.mod h1:iHyc9cjoF7/zoiKVY65d2fBWRhoS2zx4cMk8hKgqrac=
|
||||||
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
|
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
|
||||||
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
|
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
|
||||||
github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
|
github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
|
||||||
@ -1406,8 +1412,8 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
|||||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
|
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
|
||||||
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
||||||
github.com/libp2p/go-libp2p v0.37.2 h1:Irh+n9aDPTLt9wJYwtlHu6AhMUipbC1cGoJtOiBqI9c=
|
github.com/libp2p/go-libp2p v0.38.1 h1:aT1K7IFWi+gZUsQGCzTHBTlKX5QVZQOahng8DnOr6tQ=
|
||||||
github.com/libp2p/go-libp2p v0.37.2/go.mod h1:M8CRRywYkqC6xKHdZ45hmqVckBj5z4mRLIMLWReypz8=
|
github.com/libp2p/go-libp2p v0.38.1/go.mod h1:QWV4zGL3O9nXKdHirIC59DoRcZ446dfkjbOJ55NEWFo=
|
||||||
github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ=
|
github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ=
|
||||||
github.com/linxGnu/grocksdb v1.8.14/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA=
|
github.com/linxGnu/grocksdb v1.8.14/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA=
|
||||||
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
|
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
|
||||||
@ -1515,6 +1521,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
|
|||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||||
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
||||||
|
github.com/onsonr/motr v0.0.0-20250106200953-0f9e40a14ad8 h1:mRyGBI8HbCtvBOy+glT47Tz2Hlz2BYUU/r2MOckgNgg=
|
||||||
|
github.com/onsonr/motr v0.0.0-20250106200953-0f9e40a14ad8/go.mod h1:lGU/f0rProgg/SzEko5NTD8n2uXjOodewcudSPf2GJQ=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
|
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
|
||||||
@ -1676,6 +1684,10 @@ github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95
|
|||||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
||||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
|
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=
|
||||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@ -1782,8 +1794,8 @@ golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8H
|
|||||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
|
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
|
||||||
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
@ -1904,8 +1916,8 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
|||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -1940,8 +1952,8 @@ golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE
|
|||||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||||
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
|
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
|
||||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
|
||||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -2127,8 +2139,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
1
x/dwn/types/attns.go
Normal file
1
x/dwn/types/attns.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package types
|
48
x/dwn/types/embed/codec.go
Normal file
48
x/dwn/types/embed/codec.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package embed
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/ipfs/boxo/files"
|
||||||
|
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 *motr.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) *motr.Config {
|
||||||
|
return &motr.Config{
|
||||||
|
MotrToken: ucanCID,
|
||||||
|
MotrAddress: addr,
|
||||||
|
IpfsGatewayUrl: "http://localhost:80",
|
||||||
|
SonrApiUrl: "http://localhost:1317",
|
||||||
|
SonrRpcUrl: "http://localhost:26657",
|
||||||
|
SonrChainId: "sonr-testnet-1",
|
||||||
|
}
|
||||||
|
}
|
138
x/dwn/types/embed/index.html
Normal file
138
x/dwn/types/embed/index.html
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Sonr DWN</title>
|
||||||
|
|
||||||
|
<!-- HTMX -->
|
||||||
|
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||||
|
|
||||||
|
<!-- WASM Support -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/golang/go@go1.22.5/misc/wasm/wasm_exec.js"></script>
|
||||||
|
|
||||||
|
<!-- Main JS -->
|
||||||
|
<script src="main.js"></script>
|
||||||
|
|
||||||
|
<!-- Tailwind (assuming you're using it based on your classes) -->
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
|
||||||
|
<!-- Add manifest for PWA support -->
|
||||||
|
<link
|
||||||
|
rel="manifest"
|
||||||
|
href="/app.webmanifest"
|
||||||
|
crossorigin="use-credentials"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Offline detection styles -->
|
||||||
|
<style>
|
||||||
|
.offline-indicator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.offline .offline-indicator {
|
||||||
|
display: block;
|
||||||
|
background: #f44336;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.5rem;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body
|
||||||
|
class="flex items-center justify-center h-full bg-zinc-50 lg:p-24 md:16 p-4"
|
||||||
|
>
|
||||||
|
<!-- Offline indicator -->
|
||||||
|
<div class="offline-indicator">
|
||||||
|
You are currently offline. Some features may be limited.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Loading indicator -->
|
||||||
|
<div
|
||||||
|
id="loading-indicator"
|
||||||
|
class="fixed top-0 left-0 w-full h-1 bg-blue-200 transition-all duration-300"
|
||||||
|
style="display: none"
|
||||||
|
>
|
||||||
|
<div class="h-full bg-blue-600 w-0 transition-all duration-300"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main
|
||||||
|
class="flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
id="content"
|
||||||
|
hx-get="/#"
|
||||||
|
hx-trigger="load"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-indicator="#loading-indicator"
|
||||||
|
>
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- WASM Ready Indicator (hidden) -->
|
||||||
|
<div
|
||||||
|
id="wasm-status"
|
||||||
|
class="hidden fixed bottom-4 right-4 p-2 rounded-md bg-green-500 text-white"
|
||||||
|
hx-swap-oob="true"
|
||||||
|
>
|
||||||
|
WASM Ready
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Initialize service worker
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
window.addEventListener("load", async function () {
|
||||||
|
try {
|
||||||
|
const registration =
|
||||||
|
await navigator.serviceWorker.register("/sw.js");
|
||||||
|
console.log(
|
||||||
|
"Service Worker registered with scope:",
|
||||||
|
registration.scope,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Service Worker registration failed:", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTMX loading indicator
|
||||||
|
htmx.on("htmx:beforeRequest", function (evt) {
|
||||||
|
document.getElementById("loading-indicator").style.display = "block";
|
||||||
|
});
|
||||||
|
|
||||||
|
htmx.on("htmx:afterRequest", function (evt) {
|
||||||
|
document.getElementById("loading-indicator").style.display = "none";
|
||||||
|
});
|
||||||
|
|
||||||
|
// WASM ready event handler
|
||||||
|
document.addEventListener("wasm-ready", function () {
|
||||||
|
const status = document.getElementById("wasm-status");
|
||||||
|
status.classList.remove("hidden");
|
||||||
|
setTimeout(() => {
|
||||||
|
status.classList.add("hidden");
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Offline status handler
|
||||||
|
window.addEventListener("offline", function () {
|
||||||
|
document.body.classList.add("offline");
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("online", function () {
|
||||||
|
document.body.classList.remove("offline");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial offline check
|
||||||
|
if (!navigator.onLine) {
|
||||||
|
document.body.classList.add("offline");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
158
x/dwn/types/embed/main.js
Normal file
158
x/dwn/types/embed/main.js
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// MessageChannel for WASM communication
|
||||||
|
let wasmChannel;
|
||||||
|
let wasmPort;
|
||||||
|
|
||||||
|
async function initWasmChannel() {
|
||||||
|
wasmChannel = new MessageChannel();
|
||||||
|
wasmPort = wasmChannel.port1;
|
||||||
|
|
||||||
|
// Setup message handling from WASM
|
||||||
|
wasmPort.onmessage = (event) => {
|
||||||
|
const { type, data } = event.data;
|
||||||
|
switch (type) {
|
||||||
|
case "WASM_READY":
|
||||||
|
console.log("WASM is ready");
|
||||||
|
document.dispatchEvent(new CustomEvent("wasm-ready"));
|
||||||
|
break;
|
||||||
|
case "RESPONSE":
|
||||||
|
handleWasmResponse(data);
|
||||||
|
break;
|
||||||
|
case "SYNC_COMPLETE":
|
||||||
|
handleSyncComplete(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize WebAssembly and Service Worker
|
||||||
|
async function init() {
|
||||||
|
try {
|
||||||
|
// Register service worker
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
const registration = await navigator.serviceWorker.register("./sw.js");
|
||||||
|
console.log("ServiceWorker registered");
|
||||||
|
|
||||||
|
// Wait for the service worker to be ready
|
||||||
|
await navigator.serviceWorker.ready;
|
||||||
|
|
||||||
|
// Initialize MessageChannel
|
||||||
|
await initWasmChannel();
|
||||||
|
|
||||||
|
// Send the MessageChannel port to the service worker
|
||||||
|
navigator.serviceWorker.controller.postMessage(
|
||||||
|
{
|
||||||
|
type: "PORT_INITIALIZATION",
|
||||||
|
port: wasmChannel.port2,
|
||||||
|
},
|
||||||
|
[wasmChannel.port2],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register for periodic sync if available
|
||||||
|
if ("periodicSync" in registration) {
|
||||||
|
try {
|
||||||
|
await registration.periodicSync.register("wasm-sync", {
|
||||||
|
minInterval: 24 * 60 * 60 * 1000, // 24 hours
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Periodic sync could not be registered:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize HTMX with custom config
|
||||||
|
htmx.config.withCredentials = true;
|
||||||
|
htmx.config.wsReconnectDelay = "full-jitter";
|
||||||
|
|
||||||
|
// Override HTMX's internal request handling
|
||||||
|
htmx.config.beforeRequest = function (config) {
|
||||||
|
// Add request ID for tracking
|
||||||
|
const requestId = "req_" + Date.now();
|
||||||
|
config.headers["X-Wasm-Request-ID"] = requestId;
|
||||||
|
|
||||||
|
// If offline, handle through service worker
|
||||||
|
if (!navigator.onLine) {
|
||||||
|
return false; // Let service worker handle it
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle HTMX after request
|
||||||
|
htmx.config.afterRequest = function (config) {
|
||||||
|
// Additional processing after request if needed
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle HTMX errors
|
||||||
|
htmx.config.errorHandler = function (error) {
|
||||||
|
console.error("HTMX Error:", error);
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Initialization failed:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleWasmResponse(data) {
|
||||||
|
const { requestId, response } = data;
|
||||||
|
// Process the WASM response
|
||||||
|
// This might update the UI or trigger HTMX swaps
|
||||||
|
const targetElement = document.querySelector(
|
||||||
|
`[data-request-id="${requestId}"]`,
|
||||||
|
);
|
||||||
|
if (targetElement) {
|
||||||
|
htmx.process(targetElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSyncComplete(data) {
|
||||||
|
const { url } = data;
|
||||||
|
// Handle successful sync
|
||||||
|
// Maybe refresh the relevant part of the UI
|
||||||
|
htmx.trigger("body", "sync:complete", { url });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle offline status changes
|
||||||
|
window.addEventListener("online", () => {
|
||||||
|
document.body.classList.remove("offline");
|
||||||
|
// Trigger sync when back online
|
||||||
|
if (wasmPort) {
|
||||||
|
wasmPort.postMessage({ type: "SYNC_REQUEST" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("offline", () => {
|
||||||
|
document.body.classList.add("offline");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Custom event handlers for HTMX
|
||||||
|
document.addEventListener("htmx:beforeRequest", (event) => {
|
||||||
|
const { elt, xhr } = event.detail;
|
||||||
|
// Add request tracking
|
||||||
|
const requestId = xhr.headers["X-Wasm-Request-ID"];
|
||||||
|
elt.setAttribute("data-request-id", requestId);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("htmx:afterRequest", (event) => {
|
||||||
|
const { elt, successful } = event.detail;
|
||||||
|
if (successful) {
|
||||||
|
elt.removeAttribute("data-request-id");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize everything when the page loads
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
||||||
|
|
||||||
|
// Export functions that might be needed by WASM
|
||||||
|
window.wasmBridge = {
|
||||||
|
triggerUIUpdate: function (selector, content) {
|
||||||
|
const target = document.querySelector(selector);
|
||||||
|
if (target) {
|
||||||
|
htmx.process(
|
||||||
|
htmx.parse(content).forEach((node) => target.appendChild(node)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showNotification: function (message, type = "info") {
|
||||||
|
// Implement notification system
|
||||||
|
console.log(`${type}: ${message}`);
|
||||||
|
},
|
||||||
|
};
|
257
x/dwn/types/embed/sw.js
Normal file
257
x/dwn/types/embed/sw.js
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
// Cache names for different types of resources
|
||||||
|
const CACHE_NAMES = {
|
||||||
|
wasm: "wasm-cache-v1",
|
||||||
|
static: "static-cache-v1",
|
||||||
|
dynamic: "dynamic-cache-v1",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Import required scripts
|
||||||
|
importScripts(
|
||||||
|
"https://cdn.jsdelivr.net/gh/golang/go@go1.22.5/misc/wasm/wasm_exec.js",
|
||||||
|
"https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@v1.1.0/sw.js",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Initialize WASM HTTP listener
|
||||||
|
const wasmInstance = registerWasmHTTPListener(
|
||||||
|
"https://cdn.sonr.id/wasm/app.wasm",
|
||||||
|
);
|
||||||
|
|
||||||
|
// MessageChannel port for WASM communication
|
||||||
|
let wasmPort;
|
||||||
|
|
||||||
|
// Request queue for offline operations
|
||||||
|
let requestQueue = new Map();
|
||||||
|
|
||||||
|
// Setup message channel handler
|
||||||
|
self.addEventListener("message", async (event) => {
|
||||||
|
if (event.data.type === "PORT_INITIALIZATION") {
|
||||||
|
wasmPort = event.data.port;
|
||||||
|
setupWasmCommunication();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupWasmCommunication() {
|
||||||
|
wasmPort.onmessage = async (event) => {
|
||||||
|
const { type, data } = event.data;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "WASM_REQUEST":
|
||||||
|
handleWasmRequest(data);
|
||||||
|
break;
|
||||||
|
case "SYNC_REQUEST":
|
||||||
|
processSyncQueue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Notify that WASM is ready
|
||||||
|
wasmPort.postMessage({ type: "WASM_READY" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhanced install event
|
||||||
|
self.addEventListener("install", (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
Promise.all([
|
||||||
|
skipWaiting(),
|
||||||
|
// Cache WASM binary and essential resources
|
||||||
|
caches
|
||||||
|
.open(CACHE_NAMES.wasm)
|
||||||
|
.then((cache) =>
|
||||||
|
cache.addAll([
|
||||||
|
"https://cdn.sonr.id/wasm/app.wasm",
|
||||||
|
"https://cdn.jsdelivr.net/gh/golang/go@go1.22.5/misc/wasm/wasm_exec.js",
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enhanced activate event
|
||||||
|
self.addEventListener("activate", (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
Promise.all([
|
||||||
|
clients.claim(),
|
||||||
|
// Clean up old caches
|
||||||
|
caches.keys().then((keys) =>
|
||||||
|
Promise.all(
|
||||||
|
keys.map((key) => {
|
||||||
|
if (!Object.values(CACHE_NAMES).includes(key)) {
|
||||||
|
return caches.delete(key);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Intercept fetch events
|
||||||
|
self.addEventListener("fetch", (event) => {
|
||||||
|
const request = event.request;
|
||||||
|
|
||||||
|
// Handle API requests differently from static resources
|
||||||
|
if (request.url.includes("/api/")) {
|
||||||
|
event.respondWith(handleApiRequest(request));
|
||||||
|
} else {
|
||||||
|
event.respondWith(handleStaticRequest(request));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleApiRequest(request) {
|
||||||
|
try {
|
||||||
|
// Try to make the request
|
||||||
|
const response = await fetch(request.clone());
|
||||||
|
|
||||||
|
// If successful, pass through WASM handler
|
||||||
|
if (response.ok) {
|
||||||
|
return await processWasmResponse(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If offline or failed, queue the request
|
||||||
|
await queueRequest(request);
|
||||||
|
|
||||||
|
// Return cached response if available
|
||||||
|
const cachedResponse = await caches.match(request);
|
||||||
|
if (cachedResponse) {
|
||||||
|
return cachedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return offline response
|
||||||
|
return new Response(JSON.stringify({ error: "Currently offline" }), {
|
||||||
|
status: 503,
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
await queueRequest(request);
|
||||||
|
return new Response(JSON.stringify({ error: "Request failed" }), {
|
||||||
|
status: 500,
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleStaticRequest(request) {
|
||||||
|
// Check cache first
|
||||||
|
const cachedResponse = await caches.match(request);
|
||||||
|
if (cachedResponse) {
|
||||||
|
return cachedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(request);
|
||||||
|
|
||||||
|
// Cache successful responses
|
||||||
|
if (response.ok) {
|
||||||
|
const cache = await caches.open(CACHE_NAMES.static);
|
||||||
|
cache.put(request, response.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
// Return offline page for navigation requests
|
||||||
|
if (request.mode === "navigate") {
|
||||||
|
return caches.match("/offline.html");
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processWasmResponse(request, response) {
|
||||||
|
// Clone the response before processing
|
||||||
|
const responseClone = response.clone();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Process through WASM
|
||||||
|
const processedResponse = await wasmInstance.processResponse(responseClone);
|
||||||
|
|
||||||
|
// Notify client through message channel
|
||||||
|
if (wasmPort) {
|
||||||
|
wasmPort.postMessage({
|
||||||
|
type: "RESPONSE",
|
||||||
|
requestId: request.headers.get("X-Wasm-Request-ID"),
|
||||||
|
response: processedResponse,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return processedResponse;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("WASM processing error:", error);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function queueRequest(request) {
|
||||||
|
const serializedRequest = await serializeRequest(request);
|
||||||
|
requestQueue.set(request.url, serializedRequest);
|
||||||
|
|
||||||
|
// Register for background sync
|
||||||
|
try {
|
||||||
|
await self.registration.sync.register("wasm-sync");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Sync registration failed:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function serializeRequest(request) {
|
||||||
|
const headers = {};
|
||||||
|
for (const [key, value] of request.headers.entries()) {
|
||||||
|
headers[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: request.url,
|
||||||
|
method: request.method,
|
||||||
|
headers,
|
||||||
|
body: await request.text(),
|
||||||
|
timestamp: Date.now(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle background sync
|
||||||
|
self.addEventListener("sync", (event) => {
|
||||||
|
if (event.tag === "wasm-sync") {
|
||||||
|
event.waitUntil(processSyncQueue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function processSyncQueue() {
|
||||||
|
const requests = Array.from(requestQueue.values());
|
||||||
|
|
||||||
|
for (const serializedRequest of requests) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
new Request(serializedRequest.url, {
|
||||||
|
method: serializedRequest.method,
|
||||||
|
headers: serializedRequest.headers,
|
||||||
|
body: serializedRequest.body,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
requestQueue.delete(serializedRequest.url);
|
||||||
|
|
||||||
|
// Notify client of successful sync
|
||||||
|
if (wasmPort) {
|
||||||
|
wasmPort.postMessage({
|
||||||
|
type: "SYNC_COMPLETE",
|
||||||
|
url: serializedRequest.url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Sync failed for request:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle payment requests
|
||||||
|
self.addEventListener("canmakepayment", function (e) {
|
||||||
|
e.respondWith(Promise.resolve(true));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle periodic sync if available
|
||||||
|
self.addEventListener("periodicsync", (event) => {
|
||||||
|
if (event.tag === "wasm-sync") {
|
||||||
|
event.waitUntil(processSyncQueue());
|
||||||
|
}
|
||||||
|
});
|
47
x/dwn/types/embed/utils.go
Normal file
47
x/dwn/types/embed/utils.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
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:]
|
||||||
|
}
|
124
x/dwn/types/embed/webworker.go
Normal file
124
x/dwn/types/embed/webworker.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebManifest struct {
|
||||||
|
// Required fields
|
||||||
|
Name string `json:"name"` // Full name of the application
|
||||||
|
ShortName string `json:"short_name"` // Short version of the name
|
||||||
|
|
||||||
|
// Display and appearance
|
||||||
|
Description string `json:"description,omitempty"` // Purpose and features of the application
|
||||||
|
Display string `json:"display,omitempty"` // Preferred display mode: fullscreen, standalone, minimal-ui, browser
|
||||||
|
DisplayOverride []string `json:"display_override,omitempty"`
|
||||||
|
ThemeColor string `json:"theme_color,omitempty"` // Default theme color for the application
|
||||||
|
BackgroundColor string `json:"background_color,omitempty"` // Background color during launch
|
||||||
|
Orientation string `json:"orientation,omitempty"` // Default orientation: any, natural, landscape, portrait
|
||||||
|
|
||||||
|
// URLs and scope
|
||||||
|
StartURL string `json:"start_url"` // Starting URL when launching
|
||||||
|
Scope string `json:"scope,omitempty"` // Navigation scope of the web application
|
||||||
|
ServiceWorker ServiceWorker `json:"service_worker,omitempty"`
|
||||||
|
|
||||||
|
// Icons
|
||||||
|
Icons []IconDefinition `json:"icons,omitempty"`
|
||||||
|
|
||||||
|
// Optional features
|
||||||
|
RelatedApplications []RelatedApplication `json:"related_applications,omitempty"`
|
||||||
|
PreferRelatedApplications bool `json:"prefer_related_applications,omitempty"`
|
||||||
|
Shortcuts []Shortcut `json:"shortcuts,omitempty"`
|
||||||
|
|
||||||
|
// Experimental features (uncomment if needed)
|
||||||
|
FileHandlers []FileHandler `json:"file_handlers,omitempty"`
|
||||||
|
ProtocolHandlers []ProtocolHandler `json:"protocol_handlers,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileHandler struct {
|
||||||
|
Action string `json:"action"`
|
||||||
|
Accept map[string][]string `json:"accept"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LaunchHandler struct {
|
||||||
|
Action string `json:"action"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IconDefinition struct {
|
||||||
|
Src string `json:"src"`
|
||||||
|
Sizes string `json:"sizes"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Purpose string `json:"purpose,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProtocolHandler struct {
|
||||||
|
Scheme string `json:"scheme"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RelatedApplication struct {
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Shortcut struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ShortName string `json:"short_name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Icons []IconDefinition `json:"icons,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceWorker struct {
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
Src string `json:"src"`
|
||||||
|
UseCache bool `json:"use_cache"`
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user