1 import FuseJs from 'fuse.js'
2 import debounce from 'lodash.debounce'
3
4 class Fuse {
5 constructor() {
6 this.allItems = null
7 this.cliVersion = null
8 this.instances = new Map()
9 // [MKT]: I landed on the debouce wait value of 50 based mostly on
10 // experimentation. With both `leading` and `trailing` set to `true`, this
11 // feels pretty snappy.
12 //
13 // From https://lodash.com/docs/#debounce:
14 //
15 // > Note: If `leading` and `trailing` options are `true`, `func` is invoked
16 // > on the trailing edge of the timeout only if the debounced function is
17 // > invoked more than once during the wait timeout.
18 this.search = debounce(this.search, 50, {leading: true, trailing: true})
19 }
20
21 search(query) {
22 postMessage({
23 query,
24 results: this.instances
25 .get(this.cliVersion.current)
26 .search(query)
27 .slice(0, 20)
28 .map(i => i.item),
29 })
30 }
31
32 createInstance() {
33 if (!this.allItems || !this.cliVersion) {
34 return
35 }
36 const items = this.allItems.filter(item =>
37 item.path.startsWith(this.cliVersion.root) ? item.path.startsWith(this.cliVersion.current) : true,
38 )
39 this.instances.set(this.cliVersion.current, new FuseJs(items, {threshold: 0.2, keys: ['title', 'body']}))
40 }
41
42 setItems(items) {
43 this.allItems = items
44 this.createInstance()
45 }
46
47 setCliVersion({root, current}) {
48 this.cliVersion = {root, current}
49 if (this.instances.has(this.cliVersion.current)) {
50 return
51 }
52 this.createInstance()
53 }
54 }
55
56 const fuse = new Fuse()
57
58 onmessage = function ({data: {items, query, cli}}) {
59 if (items) {
60 fuse.setItems(items)
61 }
62
63 if (cli) {
64 fuse.setCliVersion(cli)
65 }
66
67 if (query) {
68 fuse.search(query)
69 }
70 }