diff options
author | Alan Pearce | 2024-05-07 17:33:06 +0200 |
---|---|---|
committer | Alan Pearce | 2024-05-07 17:36:06 +0200 |
commit | c15b142b18dcdc7f5ab6d5f1afca8ae1696692cc (patch) | |
tree | 6bda157426a7eb79e3299839eeb43230db99f206 | |
parent | 6c8c36b2c34bc375859230ddc13c5071274f60b4 (diff) | |
download | searchix-c15b142b18dcdc7f5ab6d5f1afca8ae1696692cc.tar.lz searchix-c15b142b18dcdc7f5ab6d5f1afca8ae1696692cc.tar.zst searchix-c15b142b18dcdc7f5ab6d5f1afca8ae1696692cc.zip |
feat: search one set of options
-rw-r--r-- | .golangci.yaml | 13 | ||||
-rw-r--r-- | frontend/static/search.js | 7 | ||||
-rw-r--r-- | frontend/static/style.css | 4 | ||||
-rw-r--r-- | frontend/templates/blocks/options.gotmpl | 98 | ||||
-rw-r--r-- | go.mod | 31 | ||||
-rw-r--r-- | go.sum | 70 | ||||
-rw-r--r-- | gomod2nix.toml | 91 | ||||
-rw-r--r-- | internal/search/search.go | 123 | ||||
-rw-r--r-- | internal/server/server.go | 43 |
9 files changed, 409 insertions, 71 deletions
diff --git a/.golangci.yaml b/.golangci.yaml index 4567686..0a6dbdd 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -21,3 +21,16 @@ linters: - sloglint - unconvert - wrapcheck +linters-settings: + wrapcheck: + ignoreSigs: + - .Errorf( + - errors.New( + - errors.Unwrap( + - errors.Join( + - .Wrap( + - .Wrapf( + - .WithMessage( + - .WithMessagef( + - .WithStack( + - (context.Context).Err( diff --git a/frontend/static/search.js b/frontend/static/search.js index 0388942..f034fe1 100644 --- a/frontend/static/search.js +++ b/frontend/static/search.js @@ -38,14 +38,14 @@ search.addEventListener("submit", function (ev) { fetch: "true", }, }) - .then(function (res) { + .then(async function (res) { state.url = url.toJSON(); state.opened = []; - history.pushState(state, null, url); if (res.ok) { + history.pushState(state, null, url); return res.text(); } else { - throw new Error(res.statusText); + throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`); } }) .then(function (html) { @@ -54,6 +54,7 @@ search.addEventListener("submit", function (ev) { addToggleEventListeners(); }) .catch(function (error) { + results.innerText = error.message; console.error("fetch failed", error); }); ev.preventDefault(); diff --git a/frontend/static/style.css b/frontend/static/style.css index 45cff6a..fd096b0 100644 --- a/frontend/static/style.css +++ b/frontend/static/style.css @@ -21,6 +21,10 @@ dd { margin-inline-start: 1rem; } +dd > p { + margin: unset; +} + dl { display: grid; align-items: baseline; diff --git a/frontend/templates/blocks/options.gotmpl b/frontend/templates/blocks/options.gotmpl index f89a83d..2f9d88a 100644 --- a/frontend/templates/blocks/options.gotmpl +++ b/frontend/templates/blocks/options.gotmpl @@ -1,53 +1,59 @@ {{ template "results" . }} {{ define "results" }} - {{- range .Results }} - <details id="{{ .Option }}"> - <summary> - {{ .Option }} - </summary> - <p> - {{ markdown .Description }} - </p> - <dl> - {{- with .Type }} - <dt>Type</dt> - <dd><code>{{ . }}</code></dd> - {{- end }} - {{- with .Default }} - <dt>Default</dt> - <dd> - {{- if .Markdown }} - {{ .Markdown }} - {{- else }} - <pre><code>{{ .Text }}</code></pre> + {{- with .Results }} + {{- range .Results }} + <details id="{{ .Option }}"> + <summary> + {{ .Option }} + </summary> + <p> + {{ markdown .Description }} + </p> + <dl> + {{- with .Type }} + <dt>Type</dt> + <dd><code>{{ . }}</code></dd> + {{- end }} + {{- with .Default }} + {{- if or .Text .Markdown }} + <dt>Default</dt> + <dd> + {{- if .Markdown }} + {{ markdown .Markdown }} + {{- else }} + <pre><code>{{ .Text }}</code></pre> + {{- end }} + </dd> + {{- end }} + {{- end }} + {{- with .Example }} + {{- if or .Text .Markdown }} + <dt>Example</dt> + <dd> + {{- if .Markdown }} + {{ markdown .Markdown }} + {{- else }} + <pre><code>{{ .Text }}</code></pre> + {{- end }} + </dd> {{- end }} - </dd> - {{- end }} - {{- with .Example }} - {{- if or .Text .Markdown }} - <dt>Example</dt> - <dd> - {{- if .Markdown }} - {{ .Markdown }} - {{- else }} - <pre><code>{{ .Text }}</code></pre> - {{- end }} - </dd> {{- end }} - {{- end }} - {{- with .RelatedPackages }} - <dt>Related Packages</dt> - <dd>{{ . }}</dd> - {{- end }} - {{- with .Declarations }} - <dt>Declared</dt> - {{- range . }} - <dd> - <a href="{{ .URL }}">{{ .Name }}</a> - </dd> + {{- with .RelatedPackages }} + <dt>Related Packages</dt> + <dd>{{ . }}</dd> + {{- end }} + {{- with .Declarations }} + <dt>Declared</dt> + {{- range . }} + <dd> + <a href="{{ .URL }}">{{ .Name }}</a> + </dd> + {{- end }} {{- end }} - {{- end }} - </dl> - </details> + </dl> + </details> + {{- else }} + Nothing found + {{- end }} {{- end }} {{ end }} diff --git a/go.mod b/go.mod index 664c1a1..19543b8 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.22.2 require ( github.com/ardanlabs/conf/v3 v3.1.7 github.com/bcicen/jstream v1.0.1 + github.com/blevesearch/bleve/v2 v2.4.0 github.com/crewjam/csp v0.0.2 github.com/fsnotify/fsnotify v1.7.0 github.com/getsentry/sentry-go v0.27.0 @@ -17,7 +18,35 @@ require ( ) require ( + github.com/RoaringBitmap/roaring v1.9.3 // indirect + github.com/bits-and-blooms/bitset v1.13.0 // indirect + github.com/blevesearch/bleve_index_api v1.1.6 // indirect + github.com/blevesearch/geo v0.1.20 // indirect + github.com/blevesearch/go-faiss v1.0.15 // indirect + github.com/blevesearch/go-porterstemmer v1.0.3 // indirect + github.com/blevesearch/gtreap v0.1.1 // indirect + github.com/blevesearch/mmap-go v1.0.4 // indirect + github.com/blevesearch/scorch_segment_api/v2 v2.2.11 // indirect + github.com/blevesearch/segment v0.9.1 // indirect + github.com/blevesearch/snowballstem v0.9.0 // indirect + github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect + github.com/blevesearch/vellum v1.0.10 // indirect + github.com/blevesearch/zapx/v11 v11.3.10 // indirect + github.com/blevesearch/zapx/v12 v12.3.10 // indirect + github.com/blevesearch/zapx/v13 v13.3.10 // indirect + github.com/blevesearch/zapx/v14 v14.3.10 // indirect + github.com/blevesearch/zapx/v15 v15.3.13 // indirect + github.com/blevesearch/zapx/v16 v16.0.12 // indirect + github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.6.0 // indirect - golang.org/x/sys v0.19.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mschoch/smat v0.2.0 // indirect + go.etcd.io/bbolt v1.3.10 // indirect + golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.14.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect ) diff --git a/go.sum b/go.sum index 2e315cc..9f5792f 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,48 @@ +github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM= +github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90= github.com/ardanlabs/conf/v3 v3.1.7 h1:p232cF68TafoA5U9ZlbxUIhGJtGNdKHBXF80Fdqb5t0= github.com/ardanlabs/conf/v3 v3.1.7/go.mod h1:zclexWKe0NVj6LHQ8NgDDZ7bQ1spE0KeKPFficdtAjU= github.com/bcicen/jstream v1.0.1 h1:BXY7Cu4rdmc0rhyTVyT3UkxAiX3bnLpKLas9btbH5ck= github.com/bcicen/jstream v1.0.1/go.mod h1:9ielPxqFry7Y4Tg3j4BfjPocfJ3TbsRtXOAYXYmRuAQ= +github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/blevesearch/bleve/v2 v2.4.0 h1:2xyg+Wv60CFHYccXc+moGxbL+8QKT/dZK09AewHgKsg= +github.com/blevesearch/bleve/v2 v2.4.0/go.mod h1:IhQHoFAbHgWKYavb9rQgQEJJVMuY99cKdQ0wPpst2aY= +github.com/blevesearch/bleve_index_api v1.1.6 h1:orkqDFCBuNU2oHW9hN2YEJmet+TE9orml3FCGbl1cKk= +github.com/blevesearch/bleve_index_api v1.1.6/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8= +github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM= +github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w= +github.com/blevesearch/go-faiss v1.0.15 h1:aBrj6fwLuY8CkhECFbvkc4qhLTkrYI84QoEaw9z1jMI= +github.com/blevesearch/go-faiss v1.0.15/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8= +github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= +github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= +github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y= +github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk= +github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc= +github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= +github.com/blevesearch/scorch_segment_api/v2 v2.2.11 h1:nb5KTeIhDUu+Ka6He7xXvOXcJOt9Db7c3Vy2ptqJQRs= +github.com/blevesearch/scorch_segment_api/v2 v2.2.11/go.mod h1:QVakeAECt+Fxe+zu0A4V1bgPdqNeC93wQvzaXDF3NPo= +github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= +github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= +github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s= +github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs= +github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A= +github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ= +github.com/blevesearch/vellum v1.0.10 h1:HGPJDT2bTva12hrHepVT3rOyIKFFF4t7Gf6yMxyMIPI= +github.com/blevesearch/vellum v1.0.10/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k= +github.com/blevesearch/zapx/v11 v11.3.10 h1:hvjgj9tZ9DeIqBCxKhi70TtSZYMdcFn7gDb71Xo/fvk= +github.com/blevesearch/zapx/v11 v11.3.10/go.mod h1:0+gW+FaE48fNxoVtMY5ugtNHHof/PxCqh7CnhYdnMzQ= +github.com/blevesearch/zapx/v12 v12.3.10 h1:yHfj3vXLSYmmsBleJFROXuO08mS3L1qDCdDK81jDl8s= +github.com/blevesearch/zapx/v12 v12.3.10/go.mod h1:0yeZg6JhaGxITlsS5co73aqPtM04+ycnI6D1v0mhbCs= +github.com/blevesearch/zapx/v13 v13.3.10 h1:0KY9tuxg06rXxOZHg3DwPJBjniSlqEgVpxIqMGahDE8= +github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk= +github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU= +github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns= +github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ= +github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg= +github.com/blevesearch/zapx/v16 v16.0.12 h1:Uccxvjmn+hQ6ywQP+wIiTpdq9LnAviGoryJOmGwAo/I= +github.com/blevesearch/zapx/v16 v16.0.12/go.mod h1:MYnOshRfSm4C4drxx1LGRI+MVFByykJ2anDY1fxdk9Q= github.com/crewjam/csp v0.0.2 h1:fIq6o0Z6bkABlvLT3kB0XgPnVX9iNXSAGMILs6AqHVw= github.com/crewjam/csp v0.0.2/go.mod h1:0tirp4wHwMLZZtV+HXRqGFkUO7uD2ux+1ECvK+7/xFI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -14,11 +55,27 @@ github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I= +github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= +github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/osdevisnot/sorvor v0.4.4 h1:hcMWsWOKpUtDUE3F7dra1Jf12ftLHfgDcxlyPeVlz0Y= github.com/osdevisnot/sorvor v0.4.4/go.mod h1:D/j+vvJEmjIXndJf37uwFWD0Hjcq9DiGojyt4yMo7H0= github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= @@ -35,6 +92,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -42,12 +101,19 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/gomod2nix.toml b/gomod2nix.toml index 8d7d130..6378cab 100644 --- a/gomod2nix.toml +++ b/gomod2nix.toml @@ -1,12 +1,72 @@ schema = 3 [mod] + [mod."github.com/RoaringBitmap/roaring"] + version = "v1.9.3" + hash = "sha256-LZfRufkU4UhuEcgxuCPd6divX2KIdcHp1FOt79mQV7Q=" [mod."github.com/ardanlabs/conf/v3"] version = "v3.1.7" hash = "sha256-7H53l0JN5Q6hkAgBivVQ8lFd03oNmP1IG8ihzLKm2CQ=" [mod."github.com/bcicen/jstream"] version = "v1.0.1" hash = "sha256-mm+/BuIEYYj6XOHCCJLxVMKd1XcBXCiRCWA+aTvr1sE=" + [mod."github.com/bits-and-blooms/bitset"] + version = "v1.13.0" + hash = "sha256-1jccFEH9In72Jt3wSn4vi4/MJd/UDfDrC9DlmsGVc9o=" + [mod."github.com/blevesearch/bleve/v2"] + version = "v2.4.0" + hash = "sha256-5J+rFoUdZmWY/XwV9wHB/gQAYnVqzX8jHtJikUHmieU=" + [mod."github.com/blevesearch/bleve_index_api"] + version = "v1.1.6" + hash = "sha256-e1cmYgaKP/11hPpDGU2GV1cRwMx85+yJZSr2TuwvnHc=" + [mod."github.com/blevesearch/geo"] + version = "v0.1.20" + hash = "sha256-0Of4hjPdbOwdOOHjQ1BOBgr46XQN0MNBtqklu96lWXs=" + [mod."github.com/blevesearch/go-faiss"] + version = "v1.0.15" + hash = "sha256-SXeHdFvDXRePjmnStcuc7HZMLTSljr6DV7CrWhhglXM=" + [mod."github.com/blevesearch/go-porterstemmer"] + version = "v1.0.3" + hash = "sha256-hUjo6g1ehUD1awBmta0ji/xoooD2qG7O22HIeSQiRFo=" + [mod."github.com/blevesearch/gtreap"] + version = "v0.1.1" + hash = "sha256-B4p/5RnECRfV4yOiSQDLMHb23uI7lsQDePhNK+zjbF4=" + [mod."github.com/blevesearch/mmap-go"] + version = "v1.0.4" + hash = "sha256-8y0nMAE9goKjYhR/FFEvtbP7cvM46xneE461L1Jn2Pg=" + [mod."github.com/blevesearch/scorch_segment_api/v2"] + version = "v2.2.11" + hash = "sha256-m0vbpW6iTIkgA7+wsMuE8vOJNOE8+AhOdHkuVeV4MnA=" + [mod."github.com/blevesearch/segment"] + version = "v0.9.1" + hash = "sha256-0EAT737kNxl8IJFGl2SD9mOzxolONGgpfaYEGr7JXkQ=" + [mod."github.com/blevesearch/snowballstem"] + version = "v0.9.0" + hash = "sha256-NQsXrhXcYXn4jQcvwjwLc96SGMRcqVlrR6hYKWGk7/s=" + [mod."github.com/blevesearch/upsidedown_store_api"] + version = "v1.0.2" + hash = "sha256-P69Mnh6YR5RI73bD6L7BYDxkVmaqPMNUrjbfSJoKWuo=" + [mod."github.com/blevesearch/vellum"] + version = "v1.0.10" + hash = "sha256-dXIzFaw03zMeDu5GlTrw1pw5i9hCsUJL92aWoKsR8so=" + [mod."github.com/blevesearch/zapx/v11"] + version = "v11.3.10" + hash = "sha256-GYoW7BOZW+0vMBTIGZfV7+0ve2qxGu9sw3K6cPlh5Oc=" + [mod."github.com/blevesearch/zapx/v12"] + version = "v12.3.10" + hash = "sha256-n1HZB4w6id/CFjYlM+89O8US33SEc3Q6mz4mtUHWriY=" + [mod."github.com/blevesearch/zapx/v13"] + version = "v13.3.10" + hash = "sha256-Wy/MJLhxtKFc+583MZBmKb8dahyIjN8iHYOm20W/3kM=" + [mod."github.com/blevesearch/zapx/v14"] + version = "v14.3.10" + hash = "sha256-pZl5dcmDbiuC8uyOVF8MnEx5bzQFZ1KW6JXVNkPINPs=" + [mod."github.com/blevesearch/zapx/v15"] + version = "v15.3.13" + hash = "sha256-mAft3Nv7VvzVQIFc4AJKNf2sW9zf2gX/ISgIshrPXfM=" + [mod."github.com/blevesearch/zapx/v16"] + version = "v16.0.12" + hash = "sha256-lOzoml+DdHCxzpOBeTBtqY6xE3VBrYQ25ycaf6MR1qU=" [mod."github.com/crewjam/csp"] version = "v0.0.2" hash = "sha256-4vlGmDdQjPiXmueCV51fJH/hRcG8eqhCi9TENCXjzfA=" @@ -16,12 +76,33 @@ schema = 3 [mod."github.com/getsentry/sentry-go"] version = "v0.27.0" hash = "sha256-PTkTzVNogqFA/5rc6INLY6RxK5uR1AoJFOO+pOPdE7Q=" + [mod."github.com/golang/geo"] + version = "v0.0.0-20230421003525-6adc56603217" + hash = "sha256-j4EFdpNjnCIRM9fFx4zUUipzSdvdAHnC/wmevliJirU=" + [mod."github.com/golang/protobuf"] + version = "v1.5.4" + hash = "sha256-N3+Lv9lEZjrdOWdQhFj6Y3Iap4rVLEQeI8/eFFyAMZ0=" + [mod."github.com/golang/snappy"] + version = "v0.0.4" + hash = "sha256-Umx+5xHAQCN/Gi4HbtMhnDCSPFAXSsjVbXd8n5LhjAA=" [mod."github.com/google/go-cmp"] version = "v0.6.0" hash = "sha256-qgra5jze4iPGP0JSTVeY5qV5AvEnEu39LYAuUCIkMtg=" + [mod."github.com/json-iterator/go"] + version = "v1.1.12" + hash = "sha256-To8A0h+lbfZ/6zM+2PpRpY3+L6725OPC66lffq6fUoM=" [mod."github.com/mitchellh/mapstructure"] version = "v1.5.0" hash = "sha256-ztVhGQXs67MF8UadVvG72G3ly0ypQW0IRDdOOkjYwoE=" + [mod."github.com/modern-go/concurrent"] + version = "v0.0.0-20180306012644-bacd9c7ef1dd" + hash = "sha256-OTySieAgPWR4oJnlohaFTeK1tRaVp/b0d1rYY8xKMzo=" + [mod."github.com/modern-go/reflect2"] + version = "v1.0.2" + hash = "sha256-+W9EIW7okXIXjWEgOaMh58eLvBZ7OshW2EhaIpNLSBU=" + [mod."github.com/mschoch/smat"] + version = "v0.2.0" + hash = "sha256-DZvUJXjIcta3U+zxzgU3wpoGn/V4lpBY7Xme8aQUi+E=" [mod."github.com/osdevisnot/sorvor"] version = "v0.4.4" hash = "sha256-BhyO7bvwxIdEV+c6Eo1uqahhcgsHiS8nJpg2aT8t+8s=" @@ -37,9 +118,15 @@ schema = 3 [mod."github.com/yuin/goldmark"] version = "v1.7.1" hash = "sha256-3EUgwoZRRs2jNBWSbB0DGNmfBvx7CeAgEwyUdaRaeR4=" + [mod."go.etcd.io/bbolt"] + version = "v1.3.10" + hash = "sha256-uEnz6jmmgT+hlwdZ8ns5NCJSbZcB4i123FF2cn2CbQA=" [mod."golang.org/x/sys"] - version = "v0.19.0" - hash = "sha256-cmuL31TYLJmDm/fDnI2Sn0wB88cpdOHV1+urorsJWx4=" + version = "v0.20.0" + hash = "sha256-mowlaoG2k4n1c1rApWef5EMiXd3I77CsUi8jPh6pTYA=" [mod."golang.org/x/text"] version = "v0.14.0" hash = "sha256-yh3B0tom1RfzQBf1RNmfdNWF1PtiqxV41jW1GVS6JAg=" + [mod."google.golang.org/protobuf"] + version = "v1.34.1" + hash = "sha256-qnHqY6KLZiZDbTVTN6uzF4jedxROYlPCYHoiv6XI0sc=" diff --git a/internal/search/search.go b/internal/search/search.go new file mode 100644 index 0000000..fc53ad0 --- /dev/null +++ b/internal/search/search.go @@ -0,0 +1,123 @@ +package search + +import ( + "context" + "log" + "os" + "path" + "sync" + + "searchix/internal/options" + + "github.com/bcicen/jstream" + "github.com/blevesearch/bleve/v2" + "github.com/mitchellh/mapstructure" + "github.com/pkg/errors" +) + +const maxResults = 10 + +var index bleve.Index +var docs sync.Map + +type Result[T options.NixOption] struct { + *bleve.SearchResult + Results []T +} + +func Index() error { + bleve.SetLog(log.Default()) + textFieldMapping := bleve.NewTextFieldMapping() + nameMapping := bleve.NewTextFieldMapping() + // something special for tokenisation? + // nameMapping. + optionMapping := bleve.NewDocumentStaticMapping() + + optionMapping.AddFieldMappingsAt("Option", nameMapping) + optionMapping.AddFieldMappingsAt("RelatedPackages", textFieldMapping) + optionMapping.AddFieldMappingsAt("Description", textFieldMapping) + + indexMapping := bleve.NewIndexMapping() + indexMapping.AddDocumentMapping("option", optionMapping) + + var err error + index, err = bleve.NewMemOnly(indexMapping) + // index, err = bleve.New(path.Join(cfg.DataPath, const indexFilename = "index.bleve"), indexMapping) + + if err != nil { + return errors.WithMessage(err, "error opening index") + } + batch := index.NewBatch() + _ = batch + + jsonFile, err := os.Open(path.Join("data", "processed", "darwin-options.json")) + if err != nil { + return errors.WithMessage(err, "error opening json file") + } + + dec := jstream.NewDecoder(jsonFile, 1) + var opt options.NixOption + ms, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + ErrorUnused: true, + ZeroFields: true, + Result: &opt, + }) + if err != nil { + return errors.WithMessage(err, "could not create struct decoder") + } + for mv := range dec.Stream() { + err := ms.Decode(mv.Value) // stores in opt + + if err != nil { + return errors.WithMessagef(err, "could not decode object into option, object: %#v", mv.Value) + } + + docs.Store(opt.Option, opt) + + err = batch.Index(opt.Option, opt) + if err != nil { + return errors.WithMessagef(err, "could not index option %s", opt.Option) + } + } + err = index.Batch(batch) + if err != nil { + return errors.WithMessage(err, "failed to run batch index operation") + } + + return nil +} + +func Search[T options.NixOption](ctx context.Context, keyword string) (*Result[T], error) { + query := bleve.NewMatchQuery(keyword) + search := bleve.NewSearchRequest(query) + + bleveResult, err := index.SearchInContext(ctx, search) + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + if err != nil { + return nil, errors.WithMessage(err, "failed to execute search query") + } + + results := make([]T, min(maxResults, bleveResult.Total)) + for i, result := range bleveResult.Hits { + doc, _ := docs.Load(result.ID) + results[i] = doc.(T) + if i > maxResults { + break + } + } + + return &Result[T]{ + bleveResult, + results, + }, nil + } +} + +func Load(name string) any { + doc, _ := docs.Load(name) + + return doc +} diff --git a/internal/server/server.go b/internal/server/server.go index a6f22e2..3f87b9d 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -2,7 +2,6 @@ package server import ( "context" - "encoding/json" "fmt" "html/template" "io" @@ -17,6 +16,7 @@ import ( cfg "searchix/internal/config" "searchix/internal/options" + "searchix/internal/search" "github.com/getsentry/sentry-go" sentryhttp "github.com/getsentry/sentry-go/http" @@ -59,10 +59,10 @@ type TemplateData struct { Query string } -type OptionResultData struct { +type ResultData[T options.NixOption] struct { TemplateData Query string - Results options.NixOptions + Results *search.Result[T] } func applyDevModeOverrides(config *cfg.Config) { @@ -70,6 +70,13 @@ func applyDevModeOverrides(config *cfg.Config) { config.CSP.ConnectSrc = slices.Insert(config.CSP.ConnectSrc, 0, "'self'") } +func init() { + err := search.Index() + if err != nil { + log.Fatalf("could not build search index, error: %#v", err) + } +} + func New(runtimeConfig *Config) (*Server, error) { var err error config, err = cfg.GetConfig() @@ -113,23 +120,25 @@ func New(runtimeConfig *Config) (*Server, error) { } }) - var nixosOptions = options.NixOptions{} - jsonFile, err := os.ReadFile(path.Join(config.DataPath, "test.json")) - if err != nil { - slog.Error(fmt.Sprintf("error reading json file: %v", err)) - } - err = json.Unmarshal(jsonFile, &nixosOptions) - if err != nil { - slog.Error(fmt.Sprintf("error parsing json file: %v", err)) - } - + timeout := 1 * time.Second mux.HandleFunc("/options/results", func(w http.ResponseWriter, r *http.Request) { - tdata := OptionResultData{ + ctx, cancel := context.WithTimeoutCause(r.Context(), timeout, errors.New("timeout")) + defer cancel() + results, err := search.Search(ctx, r.URL.Query().Get("query")) + if err != nil { + if err == context.DeadlineExceeded { + http.Error(w, "Search timed out", http.StatusInternalServerError) + + return + } + slog.Error("search error", "error", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + } + tdata := ResultData[options.NixOption]{ TemplateData: indexData, Query: r.URL.Query().Get("query"), - Results: nixosOptions, + Results: results, } - var err error if r.Header.Get("Fetch") == "true" { w.Header().Add("Content-Type", "text/html; charset=utf-8") err = templates["options"].Execute(w, tdata) @@ -137,7 +146,7 @@ func New(runtimeConfig *Config) (*Server, error) { err = templates["options"].ExecuteTemplate(w, "index.gotmpl", tdata) } if err != nil { - slog.Error(fmt.Sprintf("template error: %v", err)) + slog.Error("template error", "template", "options", "error", err) http.Error(w, err.Error(), http.StatusInternalServerError) } }) |