search-gold 0.9.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +21 -11
  2. package/package.json +1 -1
  3. package/src/search.ts +17 -4
package/README.md CHANGED
@@ -40,7 +40,7 @@ import {
40
40
 
41
41
  This wrapper method only needs to be called in the following two cases:
42
42
 
43
- * when component is initialized and when data is ready.
43
+ * when component is initialized and when data is ready
44
44
  * when data changes (record has been created, edited, deleted)
45
45
 
46
46
  You can name this wrapper method anything you want.
@@ -52,7 +52,7 @@ const initSearchConfig = () => {
52
52
  // objects.
53
53
  //
54
54
  // 'search-gold' package only reads this data.
55
- // Results are returned in a separate array.
55
+ // Search results are returned in a separate array.
56
56
  items: MyData,
57
57
 
58
58
  // required: keys are the object properties you
@@ -62,7 +62,14 @@ const initSearchConfig = () => {
62
62
 
63
63
  // optional: default is false
64
64
  caseSensitive: true,
65
- },
65
+
66
+ // optional: default is true
67
+ //
68
+ // You should only ever consider disabling
69
+ // memoization if you observe browser memory
70
+ // limitations with cached search results.
71
+ enableMemoize: false,
72
+ }
66
73
 
67
74
  // Call the imported method with config arg.
68
75
  searchSetConfig(config)
@@ -71,12 +78,14 @@ const initSearchConfig = () => {
71
78
  // as many times as necessary without having to set the
72
79
  // config again.
73
80
  //
74
- // Passing an empty string effectively returns the
75
- // the unfiltered set of records, the same as MyData.
81
+ // Your template would be iterating over myFilteredData
82
+ // in this example.
76
83
  //
77
84
  // How you set up your component to display the filtered
78
85
  // data is up to you and how your component is structured.
79
- // This is just an example.
86
+ //
87
+ // Passing an empty string effectively returns the
88
+ // the unfiltered set of records, the same as MyData.
80
89
  myFilteredData = <ItemRecord[]>searchHandler('')
81
90
  }
82
91
  ````
@@ -87,7 +96,7 @@ This method (from Step 2.) should be called when your component has been
87
96
  initialized and your data is ready.
88
97
 
89
98
  Also, this `initSearchConfig()` method should be called whenever your
90
- data changes via a record create, edit, or delete.
99
+ data changes after a record has been created, edited, or deleted.
91
100
 
92
101
  ```javascript
93
102
  // For this example we chose this method name; you
@@ -98,9 +107,9 @@ initSearchConfig()
98
107
  ### 4. Execute search queries and get results.
99
108
 
100
109
  Presumably, a method is binded to the UI's search field (in this example it's called
101
- `searchMyData`) and is called on every keystroke.
102
-
103
- (You can optionally add a debounce mechanism in your component if need be.)
110
+ `searchMyData`) and is called on every keystroke, debounced keystrokes, or an explicit
111
+ and separate submit event. Ultimately, the UX behavior is left up to the front end
112
+ engineer / design team.
104
113
  ```javascript
105
114
  const searchMyData = (query: string) => {
106
115
  // Call the imported method and get results.
@@ -111,10 +120,11 @@ const searchMyData = (query: string) => {
111
120
  ## Author's Development
112
121
 
113
122
  During development of the `search-gold` package, I integrated it
114
- into a couple of apps I had built with Vue using its Composition API.
123
+ into several apps I had previously created with Vue using its Composition API.
115
124
 
116
125
  In this documentation I tried to keep the Usage code snippets framework neutral.
117
126
 
127
+ `search-gold` itself is framework neutral and should work in any TS codebase.
118
128
  # Credits
119
129
 
120
130
  G. Gold
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "search-gold",
3
3
  "private": false,
4
- "version": "0.9.1",
4
+ "version": "1.0.1",
5
5
  "description": "speedy search engine targeting an array of objects",
6
6
  "author": "gold",
7
7
  "main": "./src/search.ts",
package/src/search.ts CHANGED
@@ -4,13 +4,14 @@ export interface ConfigParams {
4
4
  items: ItemRecord[]
5
5
  keys: string[]
6
6
  caseSensitive?: boolean
7
+ enableMemoize?: boolean
7
8
  }
8
9
 
9
10
  interface Config {
10
11
  Items: ItemRecord[]
11
12
  Keys: string[]
12
- CaseSensitive: boolean
13
13
  RegexFlag: 'i' | undefined
14
+ EnableMemoize: boolean
14
15
  }
15
16
 
16
17
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
@@ -21,18 +22,22 @@ const escapeRegExp = (str: string): string => {
21
22
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
22
23
  }
23
24
 
25
+ const cache = new Map()
26
+
24
27
  const Conf: Config = {
25
28
  Items: [],
26
29
  Keys: [],
27
- CaseSensitive: false,
28
30
  RegexFlag: 'i',
31
+ EnableMemoize: true,
29
32
  }
30
33
  export const searchSetConfig = (params: ConfigParams): void => {
31
- const { items, keys, caseSensitive = false } = params
34
+ const { items, keys, caseSensitive = false, enableMemoize = true } = params
32
35
  Conf.Items = items
33
36
  Conf.Keys = keys
34
- Conf.CaseSensitive = caseSensitive
35
37
  Conf.RegexFlag = caseSensitive ? undefined : 'i'
38
+ Conf.EnableMemoize = enableMemoize
39
+
40
+ cache.clear()
36
41
  }
37
42
 
38
43
  // Since (if no debounce) every search input keystroke calls this
@@ -52,6 +57,10 @@ export const searchHandler = (query: string): ItemRecord[] => {
52
57
  return Conf.Items
53
58
  }
54
59
 
60
+ if (Conf.EnableMemoize && cache.has(qTrimmed)) {
61
+ return cache.get(qTrimmed)
62
+ }
63
+
55
64
  const rx = new RegExp(qTrimmed, Conf.RegexFlag)
56
65
 
57
66
  // All the dirty work is done here...
@@ -62,5 +71,9 @@ export const searchHandler = (query: string): ItemRecord[] => {
62
71
  }
63
72
  }
64
73
 
74
+ if (Conf.EnableMemoize && qTrimmed.length >= 3) {
75
+ cache.set(qTrimmed, results)
76
+ }
77
+
65
78
  return results
66
79
  }