From 8b74fb7cbb50e288cbdf5bfb4967f8f39978b580 Mon Sep 17 00:00:00 2001 From: Filip Borkiewicz Date: Fri, 20 Sep 2024 17:01:07 +0000 Subject: [PATCH] Add support for pretty priting CBOR values (#6) Also hex representation is always displayed now so that users can easily copy it. --- .github/workflows/ci.yml | 2 +- README.md | 7 ++ display/cbor.go | 44 +++++++++ display/json.go | 25 ++++++ display/pretty.go | 63 +++++++++++++ display/pretty_test.go | 61 +++++++++++++ display/string.go | 29 ++++++ frontend/src/components/Value.scss | 4 + frontend/src/components/Value.ts | 27 +++--- frontend/src/components/Value.vue | 12 ++- frontend/src/dto/Entry.ts | 7 +- go.mod | 29 ++---- go.sum | 82 +++++------------ ports/http/dto.go | 109 ++++++++++++++++------- ports/http/frontend/css/app.b705d1e3.css | 1 + ports/http/frontend/index.html | 2 +- ports/http/frontend/js/app.316f3b59.js | 1 + ports/http/frontend/js/app.9207cec1.js | 1 + ports/http/handler.go | 9 +- 19 files changed, 384 insertions(+), 131 deletions(-) create mode 100644 display/cbor.go create mode 100644 display/json.go create mode 100644 display/pretty.go create mode 100644 display/pretty_test.go create mode 100644 display/string.go create mode 100644 ports/http/frontend/css/app.b705d1e3.css create mode 100644 ports/http/frontend/js/app.316f3b59.js create mode 100644 ports/http/frontend/js/app.9207cec1.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3513fea..c83d070 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.22 + go-version: 1.23 id: go - name: Check out code into the Go module directory diff --git a/README.md b/README.md index e9c9da7..1be55b7 100644 --- a/README.md +++ b/README.md @@ -25,5 +25,12 @@ To view `bolt.database` using Bolt UI execute the following command: The security features can be disabled by using command line flags if you are using the program locally. +## Building + +### Frontend + +1. You need to downgrade to Node v16 to build the frontend project. +2. Use `_tools/build_frontend.sh`. + [actions]: https://github.com/boreq/bolt-ui/actions [screenshot]: https://user-images.githubusercontent.com/1935975/128639070-6c335b7a-26d9-4575-ae94-2250e31149c1.png diff --git a/display/cbor.go b/display/cbor.go new file mode 100644 index 0000000..ac6bd32 --- /dev/null +++ b/display/cbor.go @@ -0,0 +1,44 @@ +package display + +import ( + "bufio" + "bytes" + "github.com/acarl005/stripansi" + "github.com/boreq/errors" + "github.com/fxamacker/cbor/v2" + refmtcbor "github.com/polydawn/refmt/cbor" + refmtpretty "github.com/polydawn/refmt/pretty" + refmtshared "github.com/polydawn/refmt/shared" +) + +type PrettifierCBOR struct { +} + +func NewPrettifierCBOR() *PrettifierCBOR { + return &PrettifierCBOR{} +} + +func (p PrettifierCBOR) Prettify(b []byte) (string, error) { + if err := cbor.Wellformed(b); err != nil { + return "", errors.Wrap(err, "invalid cbor") + } + return cborToText(b) +} + +// from https://github.com/boreq/bolt-ui/pull/2 +func cborToText(dataCBOR []byte) (string, error) { + var buf bytes.Buffer + bufWriter := bufio.NewWriter(&buf) + err := refmtshared.TokenPump{ + TokenSource: refmtcbor.NewDecoder(refmtcbor.DecodeOptions{}, bytes.NewReader(dataCBOR)), + TokenSink: refmtpretty.NewEncoder(bufWriter), + }.Run() + if err != nil { + return "", errors.Wrap(err, "tokenpump run failed") + } + err = bufWriter.Flush() + if err != nil { + return "", errors.Wrap(err, "error flushing the buffer") + } + return stripansi.Strip(buf.String()), nil +} diff --git a/display/json.go b/display/json.go new file mode 100644 index 0000000..20be03d --- /dev/null +++ b/display/json.go @@ -0,0 +1,25 @@ +package display + +import ( + "bytes" + "encoding/json" + "github.com/boreq/errors" +) + +type PrettifierJSON struct { +} + +func NewPrettifierJSON() *PrettifierJSON { + return &PrettifierJSON{} +} + +func (p PrettifierJSON) Prettify(b []byte) (string, error) { + if json.Valid(b) { + buf := &bytes.Buffer{} + if err := json.Indent(buf, b, "", " "); err != nil { + return "", errors.Wrap(err, "error indenting") + } + return buf.String(), nil + } + return "", errors.New("invalid json") +} diff --git a/display/pretty.go b/display/pretty.go new file mode 100644 index 0000000..c3f3acc --- /dev/null +++ b/display/pretty.go @@ -0,0 +1,63 @@ +package display + +import ( + "github.com/boreq/errors" +) + +type ContentType struct { + s string +} + +var ( + ContentTypeJSON ContentType = ContentType{"json"} + ContentTypeCBOR ContentType = ContentType{"cbor"} + ContentTypeString ContentType = ContentType{"string"} +) + +type Prettifier interface { + Prettify(b []byte) (string, error) +} + +type Prettified struct { + Type ContentType + Value string +} + +type prettifier struct { + Prettifier Prettifier + ContentType ContentType +} + +type Pretty struct { + prettifiers []prettifier +} + +func NewPretty() *Pretty { + return &Pretty{prettifiers: []prettifier{ + { + Prettifier: NewPrettifierCBOR(), + ContentType: ContentTypeCBOR, + }, + { + Prettifier: NewPrettifierJSON(), + ContentType: ContentTypeJSON, + }, + { + Prettifier: NewPrettifierString(), + ContentType: ContentTypeString, + }, + }} +} + +func (p *Pretty) Print(b []byte) (Prettified, error) { + for _, prettifier := range p.prettifiers { + v, err := prettifier.Prettifier.Prettify(b) + if err == nil { + return Prettified{ + Type: prettifier.ContentType, + Value: v, + }, nil + } + } + return Prettified{}, errors.New("no prettifiers completed successfully") +} diff --git a/display/pretty_test.go b/display/pretty_test.go new file mode 100644 index 0000000..480d427 --- /dev/null +++ b/display/pretty_test.go @@ -0,0 +1,61 @@ +package display_test + +import ( + "github.com/boreq/bolt-ui/display" + "github.com/fxamacker/cbor/v2" + "github.com/stretchr/testify/require" + "testing" +) + +func TestPretty(t *testing.T) { + cbor, err := cbor.Marshal(struct { + Field1 string `cbor:"1,keyasint"` + Field2 int `cbor:"2,keyasint"` + }{ + Field1: "string", + Field2: 123, + }) + require.NoError(t, err) + + testCases := []struct { + Name string + Bytes []byte + Result display.Prettified + }{ + { + Name: "json", + Bytes: []byte(`{"some":"json"}`), + Result: display.Prettified{ + Type: display.ContentTypeJSON, + Value: `{ + "some": "json" +}`, + }, + }, + { + Name: "cbor", + Bytes: cbor, + Result: display.Prettified{ + Type: display.ContentTypeCBOR, + Value: "Map {\n\r\t1: \"string\"\n\r\t2: 123\n\r}\n\r", + }, + }, + { + Name: "string", + Bytes: []byte("some_string"), + Result: display.Prettified{ + Type: display.ContentTypeString, + Value: "some_string", + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + p := display.NewPretty() + result, err := p.Print(testCase.Bytes) + require.NoError(t, err) + require.Equal(t, testCase.Result, result) + }) + } +} diff --git a/display/string.go b/display/string.go new file mode 100644 index 0000000..89ad9e3 --- /dev/null +++ b/display/string.go @@ -0,0 +1,29 @@ +package display + +import ( + "github.com/boreq/errors" + "unicode" +) + +type PrettifierString struct { +} + +func NewPrettifierString() *PrettifierString { + return &PrettifierString{} +} + +func (p *PrettifierString) Prettify(b []byte) (string, error) { + if p.canDisplayAsString(b) { + return string(b), nil + } + return "", errors.New("can't display as string") +} + +func (p *PrettifierString) canDisplayAsString(b []byte) bool { + for _, rne := range string(b) { + if !unicode.IsGraphic(rne) && !unicode.IsSpace(rne) { + return false + } + } + return true +} diff --git a/frontend/src/components/Value.scss b/frontend/src/components/Value.scss index f8aea79..55ef09f 100644 --- a/frontend/src/components/Value.scss +++ b/frontend/src/components/Value.scss @@ -38,6 +38,10 @@ font-family: monospace; } + .value-header { + color: $text-color-dimmed; + } + .value-empty { color: $text-color-dimmed; } diff --git a/frontend/src/components/Value.ts b/frontend/src/components/Value.ts index 7a455ec..9a5da0f 100644 --- a/frontend/src/components/Value.ts +++ b/frontend/src/components/Value.ts @@ -19,11 +19,11 @@ export default class Value extends Vue { return 'nil'; } - if (this.entry.value.str) { - return 'string'; + if (this.entry.value.pretty) { + return this.entry.value.pretty.content_type; } - return 'hex'; + return 'unknown'; } get formatTooltip(): string { @@ -31,23 +31,30 @@ export default class Value extends Vue { return 'The value is empty.'; } - if (this.entry.value.str) { - return 'Displaying the value as string.'; + if (this.entry.value.pretty) { + return `Recognized content type ${this.entry.value.pretty.content_type} for pretty printing.`; } - return 'Display the bytes using hexadecimal encoding.'; + return 'Pretty printing is unavailable due to unrecognized content type of this value.'; } - get valueString(): string { + get valuePretty(): string { if (!this.entry.value) { return null; } - if (this.entry.value.str) { - return this.entry.value.str; + if (this.entry.value.pretty) { + return this.entry.value.pretty.value; } - return this.entry.value.hex; + return null; } + get valueHex(): string { + if (!this.entry.value) { + return null; + } + + return this.entry.value.hex; + } } diff --git a/frontend/src/components/Value.vue b/frontend/src/components/Value.vue index 0ae33e9..be041ff 100644 --- a/frontend/src/components/Value.vue +++ b/frontend/src/components/Value.vue @@ -11,7 +11,17 @@
- {{ valueString }} +
+
+ Pretty printed +
+
{{ valuePretty }}
+
+ +
+ Raw value as hex +
+
{{ valueHex }}
diff --git a/frontend/src/dto/Entry.ts b/frontend/src/dto/Entry.ts index 6db6716..c977509 100644 --- a/frontend/src/dto/Entry.ts +++ b/frontend/src/dto/Entry.ts @@ -11,5 +11,10 @@ export class Key { export class Value { hex: string; - str: string; + pretty: Pretty; +} + +export class Pretty { + content_type: string; + value: string; } diff --git a/go.mod b/go.mod index 6905a43..8349a09 100644 --- a/go.mod +++ b/go.mod @@ -2,52 +2,33 @@ module github.com/boreq/bolt-ui require ( github.com/NYTimes/gziphandler v1.1.0 + github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/boreq/errors v0.1.0 github.com/boreq/guinea v0.0.0-20190218203212-75c10cec45e9 github.com/boreq/rest v0.1.0 + github.com/fxamacker/cbor/v2 v2.7.0 github.com/google/wire v0.6.0 github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec github.com/julienschmidt/httprouter v1.2.0 github.com/oklog/ulid/v2 v2.0.2 github.com/pkg/errors v0.8.1 + github.com/polydawn/refmt v0.89.0 github.com/rs/cors v1.6.0 github.com/stretchr/testify v1.7.0 go.etcd.io/bbolt v1.3.3 ) require ( - github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-stack/stack v1.8.0 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/subcommands v1.2.0 // indirect github.com/kr/pretty v0.1.0 // indirect - github.com/kr/pty v1.1.1 // indirect - github.com/kr/text v0.1.0 // indirect github.com/mattn/go-colorable v0.1.2 // indirect github.com/mattn/go-isatty v0.0.8 // indirect - github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/objx v0.1.0 // indirect - github.com/yuin/goldmark v1.4.13 // indirect - golang.org/x/crypto v0.26.0 // indirect - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/exp/typeparams v0.0.0-20240823005443-9b4947da3948 // indirect - golang.org/x/mod v0.20.0 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sync v0.8.0 // indirect + github.com/x448/float16 v0.8.4 // indirect golang.org/x/sys v0.23.0 // indirect - golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 // indirect - golang.org/x/term v0.23.0 // indirect - golang.org/x/text v0.17.0 // indirect - golang.org/x/tools v0.24.0 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect - gopkg.in/yaml.v2 v2.2.2 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - honnef.co/go/tools v0.5.1 // indirect ) -go 1.22.1 - -toolchain go1.22.6 +go 1.23 diff --git a/go.sum b/go.sum index 154c48b..5cdb11a 100644 --- a/go.sum +++ b/go.sum @@ -1,33 +1,33 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/NYTimes/gziphandler v1.1.0 h1:wkMjq4kSz11Zer+ncYWNBQDlj9Y5RLloY/Tb8yOj6gA= github.com/NYTimes/gziphandler v1.1.0/go.mod h1:EwmLXLwj3Rvq6vawd3hKEPUcQRyz2CDE1bov6dy8HNQ= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/boreq/errors v0.1.0 h1:aJIXv9JnyR5KtxFpQ8/AiblH3nfYmr1e1yoTze/5A1k= github.com/boreq/errors v0.1.0/go.mod h1:B3dsXzhYvfgUXp7ViU/moPYM4PojgQ9MiQ21uvY6qqQ= github.com/boreq/guinea v0.0.0-20190218203212-75c10cec45e9 h1:CgYlE4U2Piu/oRDi97UFgjjS7W2ODdPu0BVUV4LJ0sM= github.com/boreq/guinea v0.0.0-20190218203212-75c10cec45e9/go.mod h1:CFnWRfNiBUlwMXBQFpRfWK8FVbXPqGmn1xHgl2d1Aig= github.com/boreq/rest v0.1.0 h1:bAx31Rp1KrXHkCOlzqAtLKdh74xbly2SHkv9k3vX3iA= github.com/boreq/rest v0.1.0/go.mod h1:Ckfx0qLDdPbS081820aWkkqvwhlrbv0SDu8UBDY4k7w= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= -github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec h1:CGkYB1Q7DSsH/ku+to+foV4agt2F2miquaLUgF6L178= github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -46,72 +46,54 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= +github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= +github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= +github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/exp/typeparams v0.0.0-20240823005443-9b4947da3948 h1:mwwJFsdsQzu/zhRdxEXmpMvRMnAR6QpbAXx3cNooEf0= -golang.org/x/exp/typeparams v0.0.0-20240823005443-9b4947da3948/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 h1:5PbJGn5Sp3GEUjJ61aYbUP6RIo3Z3r2E4Tv9y2z8UHo= -golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -120,14 +102,12 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -135,24 +115,14 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -160,7 +130,3 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.2.0 h1:ws8AfbgTX3oIczLPNPCu5166oBg9ST2vNs0rcht+mDE= -honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= -honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= diff --git a/ports/http/dto.go b/ports/http/dto.go index ab00664..48e24b6 100644 --- a/ports/http/dto.go +++ b/ports/http/dto.go @@ -2,7 +2,8 @@ package http import ( "encoding/hex" - "encoding/json" + "github.com/boreq/bolt-ui/display" + "github.com/boreq/errors" "unicode" "github.com/boreq/bolt-ui/application" @@ -13,27 +14,36 @@ type Tree struct { Entries []Entry `json:"entries"` } +type Entry struct { + Bucket bool `json:"bucket"` + Key Key `json:"key"` + Value *Value `json:"value,omitempty"` +} + type Key struct { Hex string `json:"hex"` Str string `json:"str,omitempty"` } type Value struct { - Hex string `json:"hex"` - Str string `json:"str,omitempty"` + Hex string `json:"hex"` + Pretty *Pretty `json:"pretty"` } -type Entry struct { - Bucket bool `json:"bucket"` - Key Key `json:"key"` - Value *Value `json:"value,omitempty"` +type Pretty struct { + ContentType string `json:"content_type"` + Value string `json:"value"` } -func toTree(tree application.Tree) Tree { - return Tree{ - toKeys(tree.Path), - toEntries(tree.Entries), +func toTree(tree application.Tree) (Tree, error) { + entries, err := toEntries(tree.Entries) + if err != nil { + return Tree{}, errors.Wrap(err, "error converting to entries") } + return Tree{ + Path: toKeys(tree.Path), + Entries: entries, + }, nil } func toKeys(keys []application.Key) []Key { @@ -44,20 +54,29 @@ func toKeys(keys []application.Key) []Key { return result } -func toEntries(entries []application.Entry) []Entry { +func toEntries(entries []application.Entry) ([]Entry, error) { result := make([]Entry, 0) for _, entry := range entries { - result = append(result, toEntry(entry)) + v, err := toEntry(entry) + if err != nil { + return nil, errors.Wrap(err, "error converting to an entry") + } + result = append(result, v) } - return result + return result, nil } -func toEntry(entry application.Entry) Entry { +func toEntry(entry application.Entry) (Entry, error) { + value, err := toValue(entry.Value) + if err != nil { + return Entry{}, errors.Wrap(err, "error converting to a value") + } + return Entry{ Bucket: entry.Bucket, Key: toKey(entry.Key), - Value: toValue(entry.Value), - } + Value: value, + }, nil } func toKey(key application.Key) Key { @@ -67,41 +86,67 @@ func toKey(key application.Key) Key { Hex: hex.EncodeToString(b), } - if canDisplayAsString(b) { + if canDisplayKeyAsString(b) { result.Str = string(b) } return result } -func toValue(value application.Value) *Value { +func toValue(value application.Value) (*Value, error) { if value.IsEmpty() { - return nil + return nil, nil } b := value.Bytes() - - result := &Value{ - Hex: hex.EncodeToString(b), + hexB := hex.EncodeToString(b) + pretty, err := toPretty(value) + if err != nil { + return nil, errors.Wrap(err, "error converting to a pretty value") } - if canDisplayAsString(b) { - result.Str = string(b) - } + return &Value{ + Hex: hexB, + Pretty: pretty, + }, nil +} - return result +func toPretty(value application.Value) (*Pretty, error) { + b := value.Bytes() + pretty := display.NewPretty() + prettyPrinted, err := pretty.Print(b) + if err == nil { + encodedContentType, err := encodeContentType(prettyPrinted.Type) + if err != nil { + return nil, errors.New("error encoding content type") + } + + return &Pretty{ + ContentType: encodedContentType, + Value: prettyPrinted.Value, + }, nil + } + return nil, nil } -func canDisplayAsString(b []byte) bool { - if json.Valid(b) { - return true +func encodeContentType(t display.ContentType) (string, error) { + switch t { + case display.ContentTypeJSON: + return "json", nil + case display.ContentTypeString: + return "string", nil + case display.ContentTypeCBOR: + return "cbor", nil + default: + return "", errors.New("unknown content type") } +} +func canDisplayKeyAsString(b []byte) bool { for _, rne := range string(b) { - if !unicode.IsGraphic(rne) { + if !unicode.IsGraphic(rne) || !unicode.IsSpace(rne) { return false } } - return true } diff --git a/ports/http/frontend/css/app.b705d1e3.css b/ports/http/frontend/css/app.b705d1e3.css new file mode 100644 index 0000000..9224206 --- /dev/null +++ b/ports/http/frontend/css/app.b705d1e3.css @@ -0,0 +1 @@ +.notifications[data-v-fa2d66b2]{margin:0;padding:0}.notifications .notification[data-v-fa2d66b2]{list-style-type:none;padding:1em;margin:1em;border-radius:10px;width:250px;color:#fff;box-shadow:0 0 10px rgba(0,0,0,.1);transition:all 0s;overflow:hidden;font-weight:700}.notifications .notification .extra[data-v-fa2d66b2]{background-color:rgba(1,1,1,.2);padding:1em;margin-top:1em;font-weight:400}.notifications .notification.error[data-v-fa2d66b2]{background-color:#ef6155}.notifications .notification.success[data-v-fa2d66b2]{background-color:#2ecc71}.notifications .notification.hide[data-v-fa2d66b2]{-webkit-animation:hide-data-v-fa2d66b2 .5s linear 0s 1 normal forwards;animation:hide-data-v-fa2d66b2 .5s linear 0s 1 normal forwards}@-webkit-keyframes hide-data-v-fa2d66b2{0%{transform-origin:center bottom;transform:translateX(0);opacity:1}to{transform-origin:center bottom;transform:translateX(300px);opacity:0}}@keyframes hide-data-v-fa2d66b2{0%{transform-origin:center bottom;transform:translateX(0);opacity:1}to{transform-origin:center bottom;transform:translateX(300px);opacity:0}}body,html{margin:0;padding:0;width:100%;height:100%;overflow:hidden}html{font-family:Raleway,sans-serif;font-size:12px;background-color:#f5f7fa}a,html{color:#000}a{cursor:pointer}a:hover{color:#16a085}#app{margin:0 auto;max-width:1400px;height:100%}#app .content{height:100%;box-sizing:border-box;padding:100px}#app .content .container{box-sizing:border-box;height:100%;border:1px solid #eee;border-radius:10px;background-color:#fff;box-shadow:0 0 10px rgba(0,0,0,.1);overflow-y:auto}#app>.notifications{position:absolute;bottom:0;right:0}@media(max-width:1400px){#app .content{padding:10px}}@media(max-height:900px){#app .content{padding:10px}}.tooltip{display:block!important;z-index:10000}.tooltip .tooltip-inner{background:#000;color:#fff;padding:5px 10px 4px;border-radius:10px}.tooltip .tooltip-arrow{width:0;height:0;border-style:solid;position:absolute;margin:5px;border-color:#000;z-index:1}.tooltip[x-placement^=top]{margin-bottom:5px}.tooltip[x-placement^=top] .tooltip-arrow{border-width:5px 5px 0 5px;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important;bottom:-5px;left:calc(50% - 5px);margin-top:0;margin-bottom:0}.tooltip[x-placement^=bottom]{margin-top:5px}.tooltip[x-placement^=bottom] .tooltip-arrow{border-width:0 5px 5px 5px;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important;top:-5px;left:calc(50% - 5px);margin-top:0;margin-bottom:0}.tooltip[x-placement^=right]{margin-left:5px}.tooltip[x-placement^=right] .tooltip-arrow{border-width:5px 5px 5px 0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important;left:-5px;top:calc(50% - 5px);margin-left:0;margin-right:0}.tooltip[x-placement^=left]{margin-right:5px}.tooltip[x-placement^=left] .tooltip-arrow{border-width:5px 0 5px 5px;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important;right:-5px;top:calc(50% - 5px);margin-left:0;margin-right:0}.tooltip.popover .popover-inner{background:#fff;color:#000;padding:24px;border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,.1);border:1px solid #eee;border-color:#16a085}.tooltip.popover .popover-arrow{border-color:#eee;border-color:#16a085}.tooltip[aria-hidden=true]{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s}.tooltip[aria-hidden=false]{visibility:visible;opacity:1;transition:opacity .15s}.key>span[data-v-47160388]{font-family:monospace}.key>span .decoration[data-v-47160388]{color:#aaa}.entries ul[data-v-5935002b]{padding:0;margin:0;list-style-type:none}.entries ul li a[data-v-5935002b]{padding:1em;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.entries ul li a .icon[data-v-5935002b],.entries ul li a .key[data-v-5935002b]{display:inline}.entries ul li a .icon[data-v-5935002b]{padding-right:5px;color:#aaa}.entries ul li a.selected[data-v-5935002b],.entries ul li a[data-v-5935002b]:hover{background-color:#16a085;color:#fff}.entries ul li a.selected .icon[data-v-5935002b],.entries ul li a.selected[data-v-5935002b] .key .decoration,.entries ul li a:hover .icon[data-v-5935002b],.entries ul li a[data-v-5935002b]:hover .key .decoration{color:#fff}.entries .empty-message[data-v-5935002b]{padding:2em 1em;text-align:center;color:#aaa}.spinner[data-v-5bbc4aac]{display:block;padding:2em;font-size:25px;text-align:center}.tree[data-v-7d9d6f16]{position:relative}.tree .main-spinner[data-v-7d9d6f16]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.value[data-v-05bf023a]{padding:1em}.value .header[data-v-05bf023a]{display:flex;flex-flow:row nowrap}.value .header>[data-v-05bf023a]{display:inline}.value .header i[data-v-05bf023a]{flex:0 1 0;color:#aaa;padding-right:5px}.value .header .key[data-v-05bf023a]{flex:1 1 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.value .header .format-note[data-v-05bf023a]{flex:0 1 0;color:#aaa}.value .value-empty[data-v-05bf023a],.value .value-string[data-v-05bf023a]{margin-top:1em;overflow-wrap:break-word}.value .value-string[data-v-05bf023a]{font-family:monospace}.value .value-empty[data-v-05bf023a],.value .value-header[data-v-05bf023a]{color:#aaa}.browse[data-v-323876f5]{height:100%;display:flex;flex-flow:column nowrap}.browse .top-bar[data-v-323876f5]{display:flex;flex-flow:row nowrap;padding:1em;border-bottom:1px solid #eee;align-items:center;flex:0}.browse .top-bar .main-header[data-v-323876f5]{display:inline;padding:0;margin:0;font-size:30px}.browse .top-bar ul[data-v-323876f5]{flex:1;margin:0;padding:0 0 0 2em;list-style-type:none;cursor:text;display:block}.browse .top-bar ul li[data-v-323876f5]{display:inline-block;padding:0 5px}.browse .top-bar ul li .key[data-v-323876f5]{display:inline}.browse .top-bar ul li[data-v-323876f5]:after{font-family:Font Awesome\ 5 Free;content:"";font-weight:900;padding-left:10px;color:#aaa}.browse .top-bar ul li[data-v-323876f5]:last-child:after{display:none}.browse .top-bar .edit-path[data-v-323876f5]{flex:1;display:flex;align-items:center}.browse .top-bar .edit-path .path-input[data-v-323876f5]{font-family:monospace;margin-left:2em;flex:1;display:block;border:1px solid #eee;padding:5px}.browse .wrapper[data-v-323876f5]{display:flex;flex-flow:row nowrap;align-items:stretch;flex:1;min-height:0}.browse .wrapper>[data-v-323876f5]{flex:1 1 0;overflow-y:auto;border-right:1px solid #eee}.browse .wrapper>[data-v-323876f5]:last-child{flex:2 1 0;border-right:none} \ No newline at end of file diff --git a/ports/http/frontend/index.html b/ports/http/frontend/index.html index ec5fd42..b7dd061 100644 --- a/ports/http/frontend/index.html +++ b/ports/http/frontend/index.html @@ -10,4 +10,4 @@ font-family: 'Raleway', sans-serif; text-align: center; padding: 5em 1em 1em 1em; - }
\ No newline at end of file + }
\ No newline at end of file diff --git a/ports/http/frontend/js/app.316f3b59.js b/ports/http/frontend/js/app.316f3b59.js new file mode 100644 index 0000000..4178276 --- /dev/null +++ b/ports/http/frontend/js/app.316f3b59.js @@ -0,0 +1 @@ +(function(e){function t(t){for(var i,s,o=t[0],c=t[1],u=t[2],h=0,d=[];hi.visibilityDuration}},{key:"processErrors",value:function(){var e=this;this.notifications=this.notifications.filter((function(t){var n=e.duration(new Date,t.created);return nt-this.loadThresholdInPixels&&this.loadNextIfNeeded()}},{key:"loadPreviousIfNeeded",value:function(){var e=this;if(!this.loadingPrevious&&!this.noMoreBefore){var t=this.firstKey;t&&(this.loadingPrevious=!0,this.apiService.browse(this.stringPath,t.hex,null,null).then((function(n){var i=e.firstKey;i.hex===t.hex&&(0===n.data.entries.length&&(e.noMoreBefore=!0),e.tree.entries=[].concat(Object(T["a"])(e.tree.entries),Object(T["a"])(n.data.entries)))}),(function(t){m.pushError(e,"Could not query the backend.",t)})).finally((function(){e.loadingPrevious=!1,e.loadMoreEntriesIfNeeded()})))}}},{key:"loadNextIfNeeded",value:function(){var e=this;if(!this.loadingNext&&!this.noMoreAfter){var t=this.lastKey;t&&(this.loadingNext=!0,this.apiService.browse(this.stringPath,null,t.hex,null).then((function(n){var i=e.lastKey;i.hex===t.hex&&(0===n.data.entries.length&&(e.noMoreAfter=!0),e.tree.entries=[].concat(Object(T["a"])(e.tree.entries),Object(T["a"])(n.data.entries)))}),(function(t){m.pushError(e,"Could not query the backend.",t)})).finally((function(){e.loadingNext=!1,e.loadMoreEntriesIfNeeded()})))}}},{key:"pathHasPrefix",value:function(e,t){if(t.length>e.length)return!1;for(var n=0;n=this.path.length?this.selected[this.path.length]:null}}]),n}(h["d"]);Object(l["a"])([Object(h["b"])()],Ve.prototype,"path",void 0),Object(l["a"])([Object(h["b"])()],Ve.prototype,"selected",void 0),Object(l["a"])([Object(h["c"])("tree")],Ve.prototype,"domTree",void 0),Object(l["a"])([Object(h["e"])("path")],Ve.prototype,"onPathChanged",null),Object(l["a"])([Object(h["e"])("selected")],Ve.prototype,"onSelectedChanged",null),Ve=Object(l["a"])([Object(h["a"])({components:{Entries:Pe,Spinner:Ke}})],Ve);var Ne=Ve,Me=Ne,Be=(n("293e"),Object(k["a"])(Me,se,oe,!1,null,"7d9d6f16",null)),De=Be.exports,He=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"value"},[n("div",{staticClass:"header"},[n("i",{staticClass:"fas fa-file"}),n("key",{attrs:{k:e.entry.key}}),n("div",{staticClass:"format-note"},[n("span",{directives:[{name:"tooltip",rawName:"v-tooltip",value:e.formatTooltip,expression:"formatTooltip"}]},[e._v("("+e._s(e.format)+")")])])],1),e.entry.value?n("div",{staticClass:"value-string"},[e.valuePretty?n("div",[n("div",{staticClass:"value-header"},[e._v(" Pretty printed ")]),n("pre",{staticClass:"value-string"},[n("code",[e._v(e._s(e.valuePretty))])])]):e._e(),n("div",{staticClass:"value-header"},[e._v(" Raw value as hex ")]),n("pre",{staticClass:"value-string"},[n("code",[e._v(e._s(e.valueHex))])])]):n("div",{staticClass:"value-empty"},[e._v(" This value is not set. ")])])},qe=[],Re=function(e){Object(c["a"])(n,e);var t=Object(u["a"])(n);function n(){return Object(o["a"])(this,n),t.apply(this,arguments)}return Object(v["a"])(n,[{key:"format",get:function(){return this.entry.value?this.entry.value.pretty?this.entry.value.pretty.content_type:"unknown":"nil"}},{key:"formatTooltip",get:function(){return this.entry.value?this.entry.value.pretty?"Recognized content type ".concat(this.entry.value.pretty.content_type," for pretty printing."):"Pretty printing is unavailable due to unrecognized content type of this value.":"The value is empty."}},{key:"valuePretty",get:function(){return this.entry.value&&this.entry.value.pretty?this.entry.value.pretty.value:null}},{key:"valueHex",get:function(){return this.entry.value?this.entry.value.hex:null}}]),n}(h["d"]);Object(l["a"])([Object(h["b"])()],Re.prototype,"entry",void 0),Re=Object(l["a"])([Object(h["a"])({components:{Key:je}})],Re);var Ae=Re,Fe=Ae,Le=(n("9192"),Object(k["a"])(Fe,He,qe,!1,null,"05bf023a",null)),ze=Le.exports,Je=function(e){Object(c["a"])(n,e);var t=Object(u["a"])(n);function n(){var e;return Object(o["a"])(this,n),e=t.apply(this,arguments),e.paths=[],e.selectedValueKey=null,e.selectedValue=null,e.editingSelectedPath=!1,e.editedPath=null,e.navigationService=new V,e.pathService=new M,e.numVisibleTrees=3,e}return Object(v["a"])(n,[{key:"isTreeVisible",value:function(e){var t=this.paths.length-this.numVisibleTrees;return this.selectedValueKey&&t++,e>=t}},{key:"onRouteChanged",value:function(){this.setToken(),this.loadFromRoute()}},{key:"created",value:function(){this.setToken(),this.loadFromRoute(),document.body.addEventListener("click",this.cancelEditing)}},{key:"destroyed",value:function(){document.body.removeEventListener("click",this.cancelEditing)}},{key:"treeKey",value:function(e){return e.map((function(e){return e.hex})).join("-")}},{key:"onHeaderClick",value:function(){this.loadBlank()}},{key:"onEntry",value:function(e,t){var n=this.paths.indexOf(e);if(n>=0&&(this.paths.length=n+1),t.bucket){var i=[].concat(Object(T["a"])(e),[t.key]);this.paths.push(i),this.selectedValueKey=null;var a=this.navigationService.getBrowse(i,null);this.$router.push(a)}else{var r,s,o=(null===(r=this.selectedValueKey)||void 0===r?void 0:r.hex)!==(null===(s=t.key)||void 0===s?void 0:s.hex);if(this.selectedValue=t,this.selectedValueKey=t.key,o){var c=this.navigationService.getBrowse(e,t.key);this.$router.push(c)}}}},{key:"onPath",value:function(e){for(var t=e.length,n=0;n0&&(this.editedPath=this.pathService.marshal(this.paths[this.paths.length-1],this.selectedValueKey)),this.editingSelectedPath=!0}},{key:"finishEditing",value:function(){try{var e=this.pathService.unmarshal(this.editedPath);this.loadBlank();for(var t=1;t<=e.path.length;t++)this.paths.push(e.path.slice(0,t));this.selectedValueKey=e.value,this.editingSelectedPath=!1}catch(n){m.pushError(this,"Invalid path.",n)}}},{key:"cancelEditing",value:function(){this.editingSelectedPath=!1}},{key:"setToken",value:function(){var e=this.$route.query.token;e&&this.$store.commit(O.SetToken,e)}},{key:"loadBlank",value:function(){this.paths=[[]],this.selectedValueKey=null,this.selectedValue=null}},{key:"loadFromRoute",value:function(){this.loadBlank();for(var e=this.$route.params.pathMatch.split("/").filter((function(e){return""!==e})).map((function(e){return{hex:e,str:null}})),t=1;t<=e.length;t++)this.paths.push(e.slice(0,t));this.$route.query.value&&(this.selectedValueKey={hex:this.$route.query.value,str:null})}},{key:"selectedPath",get:function(){if(0===this.paths.length)return null;var e=Object(T["a"])(this.paths[this.paths.length-1]);return this.selectedValueKey&&e.push(this.selectedValueKey),e}}]),n}(h["d"]);Object(l["a"])([Object(h["e"])("$route")],Je.prototype,"onRouteChanged",null),Je=Object(l["a"])([Object(h["a"])({components:{Tree:De,Value:ze,Key:je}})],Je);var Qe=Je,Ue=Qe,Xe=(n("7449"),Object(k["a"])(Ue,E,S,!1,null,"323876f5",null)),Ge=Xe.exports;a["a"].use(C["a"]);var We=new C["a"]({mode:"history",base:"/",routes:[{path:"/*",name:"browse-children",component:Ge},{path:"/",name:"browse",component:Ge},{path:"*",redirect:{name:"browse"}}]}),Ye=n("e37d");a["a"].use(Ye["a"]),a["a"].config.productionTip=!1,new a["a"]({router:We,store:K,render:function(e){return e(P)}}).$mount("#app")},def8:function(e,t,n){},eaaa:function(e,t,n){}}); \ No newline at end of file diff --git a/ports/http/frontend/js/app.9207cec1.js b/ports/http/frontend/js/app.9207cec1.js new file mode 100644 index 0000000..f2725ab --- /dev/null +++ b/ports/http/frontend/js/app.9207cec1.js @@ -0,0 +1 @@ +(function(e){function t(t){for(var i,s,o=t[0],c=t[1],u=t[2],h=0,d=[];hi.visibilityDuration}},{key:"processErrors",value:function(){var e=this;this.notifications=this.notifications.filter((function(t){var n=e.duration(new Date,t.created);return nt-this.loadThresholdInPixels&&this.loadNextIfNeeded()}},{key:"loadPreviousIfNeeded",value:function(){var e=this;if(!this.loadingPrevious&&!this.noMoreBefore){var t=this.firstKey;t&&(this.loadingPrevious=!0,this.apiService.browse(this.stringPath,t.hex,null,null).then((function(n){var i=e.firstKey;i.hex===t.hex&&(0===n.data.entries.length&&(e.noMoreBefore=!0),e.tree.entries=[].concat(Object(T["a"])(e.tree.entries),Object(T["a"])(n.data.entries)))}),(function(t){m.pushError(e,"Could not query the backend.",t)})).finally((function(){e.loadingPrevious=!1,e.loadMoreEntriesIfNeeded()})))}}},{key:"loadNextIfNeeded",value:function(){var e=this;if(!this.loadingNext&&!this.noMoreAfter){var t=this.lastKey;t&&(this.loadingNext=!0,this.apiService.browse(this.stringPath,null,t.hex,null).then((function(n){var i=e.lastKey;i.hex===t.hex&&(0===n.data.entries.length&&(e.noMoreAfter=!0),e.tree.entries=[].concat(Object(T["a"])(e.tree.entries),Object(T["a"])(n.data.entries)))}),(function(t){m.pushError(e,"Could not query the backend.",t)})).finally((function(){e.loadingNext=!1,e.loadMoreEntriesIfNeeded()})))}}},{key:"pathHasPrefix",value:function(e,t){if(t.length>e.length)return!1;for(var n=0;n=this.path.length?this.selected[this.path.length]:null}}]),n}(h["d"]);Object(l["a"])([Object(h["b"])()],Ve.prototype,"path",void 0),Object(l["a"])([Object(h["b"])()],Ve.prototype,"selected",void 0),Object(l["a"])([Object(h["c"])("tree")],Ve.prototype,"domTree",void 0),Object(l["a"])([Object(h["e"])("path")],Ve.prototype,"onPathChanged",null),Object(l["a"])([Object(h["e"])("selected")],Ve.prototype,"onSelectedChanged",null),Ve=Object(l["a"])([Object(h["a"])({components:{Entries:Pe,Spinner:Ke}})],Ve);var Ne=Ve,Me=Ne,Be=(n("293e"),Object(k["a"])(Me,se,oe,!1,null,"7d9d6f16",null)),De=Be.exports,He=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"value"},[n("div",{staticClass:"header"},[n("i",{staticClass:"fas fa-file"}),n("key",{attrs:{k:e.entry.key}}),n("div",{staticClass:"format-note"},[n("span",{directives:[{name:"tooltip",rawName:"v-tooltip",value:e.formatTooltip,expression:"formatTooltip"}]},[e._v("("+e._s(e.format)+")")])])],1),e.entry.value?n("div",{staticClass:"value-string"},[e.valuePretty?n("div",[n("div",{staticClass:"value-header"},[e._v(" Pretty printed ")]),n("pre",{staticClass:"value-string"},[n("code",[e._v(e._s(e.valuePretty))])])]):e._e(),n("div",{staticClass:"value-header"},[e._v(" Raw value as hex ")]),n("pre",{staticClass:"value-string"},[n("code",[e._v(e._s(e.valueHex))])])]):n("div",{staticClass:"value-empty"},[e._v(" This value is not set. ")])])},qe=[],Re=function(e){Object(c["a"])(n,e);var t=Object(u["a"])(n);function n(){return Object(o["a"])(this,n),t.apply(this,arguments)}return Object(v["a"])(n,[{key:"format",get:function(){return this.entry.value?this.entry.value.pretty?this.entry.value.pretty.content_type:"unknown":"nil"}},{key:"formatTooltip",get:function(){return this.entry.value?this.entry.value.pretty?"Recognized content type ".concat(this.entry.value.pretty.content_type," for pretty printing."):"Pretty printing is unavailable due to an unrecognized content type of this value.":"The value is empty."}},{key:"valuePretty",get:function(){return this.entry.value&&this.entry.value.pretty?this.entry.value.pretty.value:null}},{key:"valueHex",get:function(){return this.entry.value?this.entry.value.hex:null}}]),n}(h["d"]);Object(l["a"])([Object(h["b"])()],Re.prototype,"entry",void 0),Re=Object(l["a"])([Object(h["a"])({components:{Key:je}})],Re);var Ae=Re,Fe=Ae,Le=(n("9192"),Object(k["a"])(Fe,He,qe,!1,null,"05bf023a",null)),ze=Le.exports,Je=function(e){Object(c["a"])(n,e);var t=Object(u["a"])(n);function n(){var e;return Object(o["a"])(this,n),e=t.apply(this,arguments),e.paths=[],e.selectedValueKey=null,e.selectedValue=null,e.editingSelectedPath=!1,e.editedPath=null,e.navigationService=new V,e.pathService=new M,e.numVisibleTrees=3,e}return Object(v["a"])(n,[{key:"isTreeVisible",value:function(e){var t=this.paths.length-this.numVisibleTrees;return this.selectedValueKey&&t++,e>=t}},{key:"onRouteChanged",value:function(){this.setToken(),this.loadFromRoute()}},{key:"created",value:function(){this.setToken(),this.loadFromRoute(),document.body.addEventListener("click",this.cancelEditing)}},{key:"destroyed",value:function(){document.body.removeEventListener("click",this.cancelEditing)}},{key:"treeKey",value:function(e){return e.map((function(e){return e.hex})).join("-")}},{key:"onHeaderClick",value:function(){this.loadBlank()}},{key:"onEntry",value:function(e,t){var n=this.paths.indexOf(e);if(n>=0&&(this.paths.length=n+1),t.bucket){var i=[].concat(Object(T["a"])(e),[t.key]);this.paths.push(i),this.selectedValueKey=null;var a=this.navigationService.getBrowse(i,null);this.$router.push(a)}else{var r,s,o=(null===(r=this.selectedValueKey)||void 0===r?void 0:r.hex)!==(null===(s=t.key)||void 0===s?void 0:s.hex);if(this.selectedValue=t,this.selectedValueKey=t.key,o){var c=this.navigationService.getBrowse(e,t.key);this.$router.push(c)}}}},{key:"onPath",value:function(e){for(var t=e.length,n=0;n0&&(this.editedPath=this.pathService.marshal(this.paths[this.paths.length-1],this.selectedValueKey)),this.editingSelectedPath=!0}},{key:"finishEditing",value:function(){try{var e=this.pathService.unmarshal(this.editedPath);this.loadBlank();for(var t=1;t<=e.path.length;t++)this.paths.push(e.path.slice(0,t));this.selectedValueKey=e.value,this.editingSelectedPath=!1}catch(n){m.pushError(this,"Invalid path.",n)}}},{key:"cancelEditing",value:function(){this.editingSelectedPath=!1}},{key:"setToken",value:function(){var e=this.$route.query.token;e&&this.$store.commit(O.SetToken,e)}},{key:"loadBlank",value:function(){this.paths=[[]],this.selectedValueKey=null,this.selectedValue=null}},{key:"loadFromRoute",value:function(){this.loadBlank();for(var e=this.$route.params.pathMatch.split("/").filter((function(e){return""!==e})).map((function(e){return{hex:e,str:null}})),t=1;t<=e.length;t++)this.paths.push(e.slice(0,t));this.$route.query.value&&(this.selectedValueKey={hex:this.$route.query.value,str:null})}},{key:"selectedPath",get:function(){if(0===this.paths.length)return null;var e=Object(T["a"])(this.paths[this.paths.length-1]);return this.selectedValueKey&&e.push(this.selectedValueKey),e}}]),n}(h["d"]);Object(l["a"])([Object(h["e"])("$route")],Je.prototype,"onRouteChanged",null),Je=Object(l["a"])([Object(h["a"])({components:{Tree:De,Value:ze,Key:je}})],Je);var Qe=Je,Ue=Qe,Xe=(n("7449"),Object(k["a"])(Ue,E,S,!1,null,"323876f5",null)),Ge=Xe.exports;a["a"].use(C["a"]);var We=new C["a"]({mode:"history",base:"/",routes:[{path:"/*",name:"browse-children",component:Ge},{path:"/",name:"browse",component:Ge},{path:"*",redirect:{name:"browse"}}]}),Ye=n("e37d");a["a"].use(Ye["a"]),a["a"].config.productionTip=!1,new a["a"]({router:We,store:K,render:function(e){return e(P)}}).$mount("#app")},def8:function(e,t,n){},eaaa:function(e,t,n){}}); \ No newline at end of file diff --git a/ports/http/handler.go b/ports/http/handler.go index 79c695a..1ac8911 100644 --- a/ports/http/handler.go +++ b/ports/http/handler.go @@ -103,9 +103,12 @@ func (h *Handler) browse(r *http.Request) rest.RestResponse { return rest.ErrInternalServerError } - return rest.NewResponse( - toTree(tree), - ) + transportTree, err := toTree(tree) + if err != nil { + h.log.Error("error converting to a tree", "err", err) + return rest.ErrInternalServerError + } + return rest.NewResponse(transportTree) } const sep = "/"