@digigov/text-search 0.1.0-a131264d

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 (56) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +70 -0
  3. package/es/hook.js +54 -0
  4. package/es/hook.spec.js +560 -0
  5. package/es/index.js +3 -0
  6. package/es/search/__tests__/utils.spec.js +81 -0
  7. package/es/search/index.js +2 -0
  8. package/es/search/lang/gr/encoder.js +20 -0
  9. package/es/search/lang/gr/normalization-map.js +100 -0
  10. package/es/search/search-index.js +150 -0
  11. package/es/search/utils.js +88 -0
  12. package/es/test-utils/data.json +552 -0
  13. package/es/types.js +1 -0
  14. package/hook.d.ts +19 -0
  15. package/hook.js +65 -0
  16. package/hook.mjs +54 -0
  17. package/hook.spec.d.ts +1 -0
  18. package/hook.spec.js +568 -0
  19. package/hook.spec.mjs +560 -0
  20. package/index.d.ts +3 -0
  21. package/index.js +27 -0
  22. package/index.mjs +3 -0
  23. package/package.json +22 -0
  24. package/search/__tests__/utils.spec.d.ts +1 -0
  25. package/search/__tests__/utils.spec.js +84 -0
  26. package/search/__tests__/utils.spec.mjs +81 -0
  27. package/search/index.d.ts +2 -0
  28. package/search/index.js +11 -0
  29. package/search/index.mjs +2 -0
  30. package/search/lang/gr/encoder.d.ts +11 -0
  31. package/search/lang/gr/encoder.js +28 -0
  32. package/search/lang/gr/encoder.mjs +20 -0
  33. package/search/lang/gr/normalization-map.d.ts +100 -0
  34. package/search/lang/gr/normalization-map.js +107 -0
  35. package/search/lang/gr/normalization-map.mjs +100 -0
  36. package/search/search-index.d.ts +42 -0
  37. package/search/search-index.js +165 -0
  38. package/search/search-index.mjs +150 -0
  39. package/search/utils.d.ts +25 -0
  40. package/search/utils.js +100 -0
  41. package/search/utils.mjs +88 -0
  42. package/src/hook.spec.ts +289 -0
  43. package/src/hook.ts +50 -0
  44. package/src/index.ts +4 -0
  45. package/src/search/__tests__/utils.spec.ts +73 -0
  46. package/src/search/index.ts +3 -0
  47. package/src/search/lang/gr/encoder.ts +27 -0
  48. package/src/search/lang/gr/normalization-map.ts +100 -0
  49. package/src/search/search-index.ts +103 -0
  50. package/src/search/utils.ts +72 -0
  51. package/src/test-utils/data.json +552 -0
  52. package/src/types.ts +65 -0
  53. package/test-utils/data.json +552 -0
  54. package/types.d.ts +56 -0
  55. package/types.js +5 -0
  56. package/types.mjs +1 -0
@@ -0,0 +1,72 @@
1
+ import { SimpleDocumentSearchResultSetUnit } from 'flexsearch';
2
+
3
+ /**
4
+ * Extracts the unique item IDs from the result set
5
+ *
6
+ * @param result - The result set to extract the IDs from
7
+ */
8
+ export function getResultIds(result: SimpleDocumentSearchResultSetUnit[]) {
9
+ const set = new Set<number | string>();
10
+ result.forEach((item) => {
11
+ item.result.forEach((id) => set.add(id));
12
+ });
13
+ return Array.from(set);
14
+ }
15
+
16
+ /**
17
+ * Get the items from the list that match the given IDs
18
+ *
19
+ * @param items - The list of items to search through
20
+ * @param ids - The list of IDs to search for
21
+ * @param idKey - The key to use to find the IDs in the items
22
+ */
23
+ export function findItemsByIds<T extends Record<string, any>>(
24
+ items: T[],
25
+ ids: (string | number)[],
26
+ idKey: Extract<keyof T, string>
27
+ ) {
28
+ return items.filter(
29
+ (item) => item && ids.includes(getValueFromNestedKey(item, idKey))
30
+ );
31
+ }
32
+
33
+ function getValueFromNestedKey(object: Record<string, any>, nestedKey: string) {
34
+ const keys = nestedKey.split(':');
35
+
36
+ let result = object;
37
+ for (const keySegment of keys) {
38
+ if (result.hasOwnProperty(keySegment)) {
39
+ result = result[keySegment];
40
+ }
41
+ }
42
+ return (result as unknown) as string;
43
+ }
44
+
45
+ /**
46
+ * Recursively get all the keys from an object
47
+ *
48
+ * The keys are returned in the format `parentKey.childKey` for nested objects
49
+ * and `key` for top level objects (objects that are not nested inside another object).
50
+ *
51
+ * @param object - The item to get the keys from
52
+ * @param parentKey - The parent key to which the current key should be appended
53
+ */
54
+ export function getAllItemKeys(
55
+ object: Record<string, any>,
56
+ parentKey: string = ''
57
+ ): string[] {
58
+ let keys: string[] = [];
59
+ for (const key in object) {
60
+ if (object.hasOwnProperty(key)) {
61
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
62
+
63
+ if (typeof object[key] === 'object' && object[key] !== null) {
64
+ keys = keys.concat(getAllItemKeys(object[key], currentKey));
65
+ } else {
66
+ keys.push(currentKey);
67
+ }
68
+ }
69
+ }
70
+
71
+ return keys;
72
+ }
@@ -0,0 +1,552 @@
1
+ [
2
+ {
3
+ "id": 0,
4
+ "firstName": "Jacobson",
5
+ "lastName": "Hale",
6
+ "email": "jacobsonhale@uneeq.com",
7
+ "address": {
8
+ "street": "Revere Place",
9
+ "city": "Belva",
10
+ "state": "Idaho"
11
+ }
12
+ },
13
+ {
14
+ "id": 1,
15
+ "firstName": "Anastasia",
16
+ "lastName": "Rocha",
17
+ "email": "anastasiarocha@uneeq.com",
18
+ "address": {
19
+ "street": "Wilson Street",
20
+ "city": "Titanic",
21
+ "state": "Alaska"
22
+ }
23
+ },
24
+ {
25
+ "id": 2,
26
+ "firstName": "Μάρκος",
27
+ "lastName": "Richmond",
28
+ "email": "stacierichmond@uneeq.com",
29
+ "address": {
30
+ "street": "Regent Place",
31
+ "city": "Knowlton",
32
+ "state": "West Virginia"
33
+ }
34
+ },
35
+ {
36
+ "id": 3,
37
+ "firstName": "Herring",
38
+ "lastName": "Vazquez",
39
+ "email": "herringvazquez@uneeq.com",
40
+ "address": {
41
+ "street": "Cadman Plaza",
42
+ "city": "Echo",
43
+ "state": "Maryland"
44
+ }
45
+ },
46
+ {
47
+ "id": 4,
48
+ "firstName": "Strickland",
49
+ "lastName": "Butler",
50
+ "email": "stricklandbutler@uneeq.com",
51
+ "address": {
52
+ "street": "Farragut Place",
53
+ "city": "Why",
54
+ "state": "Virgin Islands"
55
+ }
56
+ },
57
+ {
58
+ "id": 5,
59
+ "firstName": "Francine",
60
+ "lastName": "Ball",
61
+ "email": "francineball@uneeq.com",
62
+ "address": {
63
+ "street": "Hope Street",
64
+ "city": "Glendale",
65
+ "state": "Pennsylvania"
66
+ }
67
+ },
68
+ {
69
+ "id": 6,
70
+ "firstName": "Noreen",
71
+ "lastName": "Harris",
72
+ "email": "noreenharris@uneeq.com",
73
+ "address": {
74
+ "street": "Noble Street",
75
+ "city": "Fontanelle",
76
+ "state": "Palau"
77
+ }
78
+ },
79
+ {
80
+ "id": 7,
81
+ "firstName": "Claire",
82
+ "lastName": "Hill",
83
+ "email": "clairehill@uneeq.com",
84
+ "address": {
85
+ "street": "Sandford Street",
86
+ "city": "Fresno",
87
+ "state": "Federated States Of Micronesia"
88
+ }
89
+ },
90
+ {
91
+ "id": 8,
92
+ "firstName": "Rosalie",
93
+ "lastName": "Matthews",
94
+ "email": "rosaliematthews@uneeq.com",
95
+ "address": {
96
+ "street": "Bergen Place",
97
+ "city": "Cloverdale",
98
+ "state": "Minnesota"
99
+ }
100
+ },
101
+ {
102
+ "id": 9,
103
+ "firstName": "Cara",
104
+ "lastName": "Heath",
105
+ "email": "caraheath@uneeq.com",
106
+ "address": {
107
+ "street": "Seigel Street",
108
+ "city": "Sedley",
109
+ "state": "North Dakota"
110
+ }
111
+ },
112
+ {
113
+ "id": 10,
114
+ "firstName": "Blair",
115
+ "lastName": "Delgado",
116
+ "email": "blairdelgado@uneeq.com",
117
+ "address": {
118
+ "street": "Turner Place",
119
+ "city": "Walker",
120
+ "state": "California"
121
+ }
122
+ },
123
+ {
124
+ "id": 11,
125
+ "firstName": "Clark",
126
+ "lastName": "Evans",
127
+ "email": "clarkevans@uneeq.com",
128
+ "address": {
129
+ "street": "Chase Court",
130
+ "city": "Wyano",
131
+ "state": "Mississippi"
132
+ }
133
+ },
134
+ {
135
+ "id": 12,
136
+ "firstName": "Johns",
137
+ "lastName": "Wilkinson",
138
+ "email": "johnswilkinson@uneeq.com",
139
+ "address": {
140
+ "street": "Wyckoff Avenue",
141
+ "city": "Cavalero",
142
+ "state": "Vermont"
143
+ }
144
+ },
145
+ {
146
+ "id": 13,
147
+ "firstName": "Rosanna",
148
+ "lastName": "Poole",
149
+ "email": "rosannapoole@uneeq.com",
150
+ "address": {
151
+ "street": "Stuart Street",
152
+ "city": "Elfrida",
153
+ "state": "Tennessee"
154
+ }
155
+ },
156
+ {
157
+ "id": 14,
158
+ "firstName": "Nicholson",
159
+ "lastName": "Guthrie",
160
+ "email": "nicholsonguthrie@uneeq.com",
161
+ "address": {
162
+ "street": "Erskine Loop",
163
+ "city": "Genoa",
164
+ "state": "Wisconsin"
165
+ }
166
+ },
167
+ {
168
+ "id": 15,
169
+ "firstName": "Lessie",
170
+ "lastName": "Stephenson",
171
+ "email": "lessiestephenson@uneeq.com",
172
+ "address": {
173
+ "street": "Glendale Court",
174
+ "city": "Brecon",
175
+ "state": "Nebraska"
176
+ }
177
+ },
178
+ {
179
+ "id": 16,
180
+ "firstName": "Schneider",
181
+ "lastName": "Preston",
182
+ "email": "schneiderpreston@uneeq.com",
183
+ "address": {
184
+ "street": "Clara Street",
185
+ "city": "Driftwood",
186
+ "state": "American Samoa"
187
+ }
188
+ },
189
+ {
190
+ "id": 17,
191
+ "firstName": "Bobbi",
192
+ "lastName": "Robinson",
193
+ "email": "bobbirobinson@uneeq.com",
194
+ "address": {
195
+ "street": "Cox Place",
196
+ "city": "Wauhillau",
197
+ "state": "Ohio"
198
+ }
199
+ },
200
+ {
201
+ "id": 18,
202
+ "firstName": "Clarissa",
203
+ "lastName": "Schroeder",
204
+ "email": "clarissaschroeder@uneeq.com",
205
+ "address": {
206
+ "street": "Hanover Place",
207
+ "city": "Robbins",
208
+ "state": "New Hampshire"
209
+ }
210
+ },
211
+ {
212
+ "id": 19,
213
+ "firstName": "Alicia",
214
+ "lastName": "Mays",
215
+ "email": "aliciamays@uneeq.com",
216
+ "address": {
217
+ "street": "Reed Street",
218
+ "city": "Clinton",
219
+ "state": "Massachusetts"
220
+ }
221
+ },
222
+ {
223
+ "id": 20,
224
+ "firstName": "Shauna",
225
+ "lastName": "Reeves",
226
+ "email": "shaunareeves@uneeq.com",
227
+ "address": {
228
+ "street": "Hausman Street",
229
+ "city": "Indio",
230
+ "state": "Oregon"
231
+ }
232
+ },
233
+ {
234
+ "id": 21,
235
+ "firstName": "Brewer",
236
+ "lastName": "Holmes",
237
+ "email": "brewerholmes@uneeq.com",
238
+ "address": {
239
+ "street": "Irwin Street",
240
+ "city": "Iberia",
241
+ "state": "Hawaii"
242
+ }
243
+ },
244
+ {
245
+ "id": 22,
246
+ "firstName": "Meadows",
247
+ "lastName": "Weber",
248
+ "email": "meadowsweber@uneeq.com",
249
+ "address": {
250
+ "street": "Rogers Avenue",
251
+ "city": "Fairmount",
252
+ "state": "Kansas"
253
+ }
254
+ },
255
+ {
256
+ "id": 23,
257
+ "firstName": "Valencia",
258
+ "lastName": "Patterson",
259
+ "email": "valenciapatterson@uneeq.com",
260
+ "address": {
261
+ "street": "Metropolitan Avenue",
262
+ "city": "Rosewood",
263
+ "state": "Oklahoma"
264
+ }
265
+ },
266
+ {
267
+ "id": 24,
268
+ "firstName": "Trina",
269
+ "lastName": "Kemp",
270
+ "email": "trinakemp@uneeq.com",
271
+ "address": {
272
+ "street": "Village Road",
273
+ "city": "Fairhaven",
274
+ "state": "New York"
275
+ }
276
+ },
277
+ {
278
+ "id": 25,
279
+ "firstName": "Lynnette",
280
+ "lastName": "Glass",
281
+ "email": "lynnetteglass@uneeq.com",
282
+ "address": {
283
+ "street": "Grand Avenue",
284
+ "city": "Robinette",
285
+ "state": "Nevada"
286
+ }
287
+ },
288
+ {
289
+ "id": 26,
290
+ "firstName": "Pace",
291
+ "lastName": "Austin",
292
+ "email": "paceaustin@uneeq.com",
293
+ "address": {
294
+ "street": "Kimball Street",
295
+ "city": "Chumuckla",
296
+ "state": "Marshall Islands"
297
+ }
298
+ },
299
+ {
300
+ "id": 27,
301
+ "firstName": "Vicky",
302
+ "lastName": "Cardenas",
303
+ "email": "vickycardenas@uneeq.com",
304
+ "address": {
305
+ "street": "Coyle Street",
306
+ "city": "Hendersonville",
307
+ "state": "Guam"
308
+ }
309
+ },
310
+ {
311
+ "id": 28,
312
+ "firstName": "Robyn",
313
+ "lastName": "Luna",
314
+ "email": "robynluna@uneeq.com",
315
+ "address": {
316
+ "street": "Billings Place",
317
+ "city": "Fostoria",
318
+ "state": "Wyoming"
319
+ }
320
+ },
321
+ {
322
+ "id": 29,
323
+ "firstName": "Stafford",
324
+ "lastName": "Simmons",
325
+ "email": "staffordsimmons@uneeq.com",
326
+ "address": {
327
+ "street": "Raleigh Place",
328
+ "city": "Whitewater",
329
+ "state": "New Jersey"
330
+ }
331
+ },
332
+ {
333
+ "id": 30,
334
+ "firstName": "Fisher",
335
+ "lastName": "Cook",
336
+ "email": "fishercook@uneeq.com",
337
+ "address": {
338
+ "street": "Lexington Avenue",
339
+ "city": "Waiohinu",
340
+ "state": "Delaware"
341
+ }
342
+ },
343
+ {
344
+ "id": 31,
345
+ "firstName": "Nanette",
346
+ "lastName": "Velazquez",
347
+ "email": "nanettevelazquez@uneeq.com",
348
+ "address": {
349
+ "street": "Gerry Street",
350
+ "city": "Coleville",
351
+ "state": "Texas"
352
+ }
353
+ },
354
+ {
355
+ "id": 32,
356
+ "firstName": "Crosby",
357
+ "lastName": "Rhodes",
358
+ "email": "crosbyrhodes@uneeq.com",
359
+ "address": {
360
+ "street": "Gelston Avenue",
361
+ "city": "Wadsworth",
362
+ "state": "Louisiana"
363
+ }
364
+ },
365
+ {
366
+ "id": 33,
367
+ "firstName": "Becky",
368
+ "lastName": "James",
369
+ "email": "beckyjames@uneeq.com",
370
+ "address": {
371
+ "street": "Goodwin Place",
372
+ "city": "Yonah",
373
+ "state": "Rhode Island"
374
+ }
375
+ },
376
+ {
377
+ "id": 34,
378
+ "firstName": "Jolene",
379
+ "lastName": "Marshall",
380
+ "email": "jolenemarshall@uneeq.com",
381
+ "address": {
382
+ "street": "Berkeley Place",
383
+ "city": "Bourg",
384
+ "state": "Florida"
385
+ }
386
+ },
387
+ {
388
+ "id": 35,
389
+ "firstName": "Levine",
390
+ "lastName": "Clay",
391
+ "email": "levineclay@uneeq.com",
392
+ "address": {
393
+ "street": "Gerald Court",
394
+ "city": "Detroit",
395
+ "state": "Virginia"
396
+ }
397
+ },
398
+ {
399
+ "id": 36,
400
+ "firstName": "Carey",
401
+ "lastName": "Sherman",
402
+ "email": "careysherman@uneeq.com",
403
+ "address": {
404
+ "street": "Stuyvesant Avenue",
405
+ "city": "Garnet",
406
+ "state": "Indiana"
407
+ }
408
+ },
409
+ {
410
+ "id": 37,
411
+ "firstName": "Sheppard",
412
+ "lastName": "Foley",
413
+ "email": "sheppardfoley@uneeq.com",
414
+ "address": {
415
+ "street": "Rodney Street",
416
+ "city": "Whipholt",
417
+ "state": "Northern Mariana Islands"
418
+ }
419
+ },
420
+ {
421
+ "id": 38,
422
+ "firstName": "Lamb",
423
+ "lastName": "Flowers",
424
+ "email": "lambflowers@uneeq.com",
425
+ "address": {
426
+ "street": "Woodpoint Road",
427
+ "city": "Craig",
428
+ "state": "Iowa"
429
+ }
430
+ },
431
+ {
432
+ "id": 39,
433
+ "firstName": "Snow",
434
+ "lastName": "Whitley",
435
+ "email": "snowwhitley@uneeq.com",
436
+ "address": {
437
+ "street": "Sackman Street",
438
+ "city": "Whitehaven",
439
+ "state": "Georgia"
440
+ }
441
+ },
442
+ {
443
+ "id": 40,
444
+ "firstName": "Koch",
445
+ "lastName": "Moreno",
446
+ "email": "kochmoreno@uneeq.com",
447
+ "address": {
448
+ "street": "Colby Court",
449
+ "city": "Konterra",
450
+ "state": "Alabama"
451
+ }
452
+ },
453
+ {
454
+ "id": 41,
455
+ "firstName": "Berry",
456
+ "lastName": "Mccoy",
457
+ "email": "berrymccoy@uneeq.com",
458
+ "address": {
459
+ "street": "Provost Street",
460
+ "city": "Balm",
461
+ "state": "Colorado"
462
+ }
463
+ },
464
+ {
465
+ "id": 42,
466
+ "firstName": "Lara",
467
+ "lastName": "Mcfarland",
468
+ "email": "laramcfarland@uneeq.com",
469
+ "address": {
470
+ "street": "Brigham Street",
471
+ "city": "Mammoth",
472
+ "state": "Missouri"
473
+ }
474
+ },
475
+ {
476
+ "id": 43,
477
+ "firstName": "Russell",
478
+ "lastName": "Mayo",
479
+ "email": "russellmayo@uneeq.com",
480
+ "address": {
481
+ "street": "Kiely Place",
482
+ "city": "Soudan",
483
+ "state": "Utah"
484
+ }
485
+ },
486
+ {
487
+ "id": 44,
488
+ "firstName": "Lorna",
489
+ "lastName": "Dejesus",
490
+ "email": "lornadejesus@uneeq.com",
491
+ "address": {
492
+ "street": "Bushwick Place",
493
+ "city": "Concho",
494
+ "state": "New Mexico"
495
+ }
496
+ },
497
+ {
498
+ "id": 45,
499
+ "firstName": "Tiffany",
500
+ "lastName": "Goodwin",
501
+ "email": "tiffanygoodwin@uneeq.com",
502
+ "address": {
503
+ "street": "Kane Street",
504
+ "city": "Dargan",
505
+ "state": "Arkansas"
506
+ }
507
+ },
508
+ {
509
+ "id": 46,
510
+ "firstName": "Todd",
511
+ "lastName": "Carson",
512
+ "email": "toddcarson@uneeq.com",
513
+ "address": {
514
+ "street": "Fleet Place",
515
+ "city": "Beechmont",
516
+ "state": "Puerto Rico"
517
+ }
518
+ },
519
+ {
520
+ "id": 47,
521
+ "firstName": "Elsa",
522
+ "lastName": "Meyer",
523
+ "email": "elsameyer@uneeq.com",
524
+ "address": {
525
+ "street": "Varanda Place",
526
+ "city": "Dotsero",
527
+ "state": "Montana"
528
+ }
529
+ },
530
+ {
531
+ "id": 48,
532
+ "firstName": "Kari",
533
+ "lastName": "Dorsey",
534
+ "email": "karidorsey@uneeq.com",
535
+ "address": {
536
+ "street": "Pilling Street",
537
+ "city": "Geyserville",
538
+ "state": "Connecticut"
539
+ }
540
+ },
541
+ {
542
+ "id": 49,
543
+ "firstName": "Kari",
544
+ "lastName": "Kari",
545
+ "email": "karivillarreal@uneeq.com",
546
+ "address": {
547
+ "street": "Vermont Street",
548
+ "city": "Gardners",
549
+ "state": "Washington"
550
+ }
551
+ }
552
+ ]
package/src/types.ts ADDED
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Options for configuring the useSearch hook
3
+ */
4
+ export interface UseSearchOptions<T extends Record<string, any>> {
5
+ indexing: SearchIndexOptions<T>;
6
+ }
7
+
8
+ /**
9
+ * Options for configuring the search index
10
+ *
11
+ * @typeParam T - The type of the data that will be indexed
12
+ */
13
+ export interface SearchIndexOptions<T> {
14
+ /**
15
+ * Describes where to find the unique ID for each item in the data
16
+ *
17
+ * This can also be a nested key, e.g. `address.street`. If not specified, the search index will
18
+ * create an 'id' field on each item, with the value being the index of the item in the array.
19
+ */
20
+ idKey?: NestedKeyOf<T>;
21
+ /**
22
+ * List of fields to index
23
+ *
24
+ * Contains a list of fields from the document, that should be indexed. The fields can be nested.
25
+ *
26
+ * @example Using nested keys
27
+ * ```
28
+ * {
29
+ * id: 1,
30
+ * name: 'John',
31
+ * address: {
32
+ * street: '123 Main St',
33
+ * city: 'New York'
34
+ * }
35
+ * }
36
+ * ```
37
+ * To search against the `street` key, add `address.street` to the fields array.
38
+ */
39
+ fields?: NestedKeyOf<T>[];
40
+ /**
41
+ * Whether to use a web worker for indexing
42
+ */
43
+ enableWorker?: boolean;
44
+ }
45
+
46
+ /**
47
+ * Any key of an object that has nested objects.
48
+ *
49
+ * This utility type is used to get all the primitive keys of an object, including the keys of any nested objects.
50
+ *
51
+ * @typeParam ObjectType - The type of the object to get the keys of
52
+ */
53
+ export type NestedKeyOf<T> = T extends Primitive
54
+ ? never
55
+ :
56
+ | (keyof T & string)
57
+ | { [P in keyof T & string]: DeepSubKeys<T, P> }[keyof T & string];
58
+
59
+ type DeepSubKeys<T, P extends keyof T & string> = T[P] extends (infer Inner)[]
60
+ ? `${P}.${NestedKeyOf<Inner>}`
61
+ : T[P] extends object
62
+ ? `${P}.${NestedKeyOf<T[P]>}`
63
+ : never;
64
+
65
+ type Primitive = null | undefined | string | number | boolean | symbol | bigint;