@digigov/text-search 1.2.0-85c27c19 → 1.2.0-8bbad051

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.
package/cjs/hook/index.js CHANGED
@@ -32,19 +32,19 @@ __export(hook_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(hook_exports);
34
34
  var import_react = require("react");
35
- var import_search = __toESM(require("./search"));
35
+ var import_search = __toESM(require("@digigov/text-search/search"));
36
36
  function useSearch(documents, query, options) {
37
37
  const [loading, setLoading] = (0, import_react.useState)(false);
38
38
  const [data, setData] = (0, import_react.useState)(documents);
39
39
  const indexing = options?.indexing;
40
- const index = (0, import_react.useMemo)(() => new import_search.default(documents, indexing), [
41
- documents,
42
- indexing
43
- ]);
40
+ const index = (0, import_react.useMemo)(
41
+ () => new import_search.default(documents, indexing),
42
+ [documents, indexing]
43
+ );
44
44
  const search = (0, import_react.useCallback)(() => {
45
45
  if (query) {
46
46
  setLoading(true);
47
- index.searchAsync(documents, query).then((data2) => setData(data2)).finally(() => setLoading(false));
47
+ index.searchAsync(documents, query).then((data2) => setData(data2)).catch(() => setData([])).finally(() => setLoading(false));
48
48
  } else {
49
49
  setData(documents);
50
50
  }
package/cjs/hook.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/hook.ts"],
4
- "sourcesContent": ["import { useCallback, useMemo, useState } from 'react';\nimport SearchIndex from './search';\nimport { UseSearchOptions } from './types';\n\n/**\n * Hook for searching through a list of documents\n *\n * Returns a list of documents that match the search query.\n * If no query is provided, it returns the original list of documents.\n *\n * @param documents - The list of documents to search through\n * @param options - Options for configuring the search index\n * @param query - The search query\n *\n * @typeParam T - The type of the data in the documents list\n */\nexport default function useSearch<T extends Record<string, any>>(\n documents: T[],\n query?: string,\n options?: UseSearchOptions<T>\n) {\n const [loading, setLoading] = useState(false);\n const [data, setData] = useState(documents);\n\n const indexing = options?.indexing;\n\n const index = useMemo(() => new SearchIndex(documents, indexing), [\n documents,\n indexing,\n ]);\n\n const search = useCallback(() => {\n if (query) {\n setLoading(true);\n index\n .searchAsync(documents, query)\n .then((data) => setData(data))\n .finally(() => setLoading(false));\n } else {\n setData(documents);\n }\n }, [query, index, documents]);\n\n const reset = useCallback(() => {\n setData(documents);\n setLoading(false);\n }, [documents]);\n\n return { data, loading, search, reset };\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+C;AAC/C,oBAAwB;AAeT,SAAR,UACL,WACA,OACA,SACA;AACA,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,KAAK;AAC5C,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,SAAS;AAE1C,QAAM,WAAW,SAAS;AAE1B,QAAM,YAAQ,sBAAQ,MAAM,IAAI,cAAAA,QAAY,WAAW,QAAQ,GAAG;AAAA,IAChE;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,aAAS,0BAAY,MAAM;AAC/B,QAAI,OAAO;AACT,iBAAW,IAAI;AACf,YACG,YAAY,WAAW,KAAK,EAC5B,KAAK,CAACC,UAAS,QAAQA,KAAI,CAAC,EAC5B,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,IACpC,OAAO;AACL,cAAQ,SAAS;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,OAAO,OAAO,SAAS,CAAC;AAE5B,QAAM,YAAQ,0BAAY,MAAM;AAC9B,YAAQ,SAAS;AACjB,eAAW,KAAK;AAAA,EAClB,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO,EAAE,MAAM,SAAS,QAAQ,MAAM;AACxC;",
4
+ "sourcesContent": ["import { useCallback, useMemo, useState } from 'react';\nimport SearchIndex from '@digigov/text-search/search';\nimport { UseSearchOptions } from '@digigov/text-search/types';\n\n/**\n * Hook for searching through a list of documents\n *\n * Returns a list of documents that match the search query.\n * If no query is provided, it returns the original list of documents.\n *\n * @param documents - The list of documents to search through\n * @param options - Options for configuring the search index\n * @param query - The search query\n *\n * @typeParam T - The type of the data in the documents list\n */\nexport default function useSearch<T extends Record<string, any>>(\n documents: T[],\n query?: string,\n options?: UseSearchOptions<T>\n) {\n const [loading, setLoading] = useState(false);\n const [data, setData] = useState(documents);\n\n const indexing = options?.indexing;\n\n const index = useMemo(\n () => new SearchIndex(documents, indexing),\n [documents, indexing]\n );\n\n const search = useCallback(() => {\n if (query) {\n setLoading(true);\n index\n .searchAsync(documents, query)\n .then((data) => setData(data))\n .catch(() => setData([]))\n .finally(() => setLoading(false));\n } else {\n setData(documents);\n }\n }, [query, index, documents]);\n\n const reset = useCallback(() => {\n setData(documents);\n setLoading(false);\n }, [documents]);\n\n return { data, loading, search, reset };\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+C;AAC/C,oBAAwB;AAeT,SAAR,UACL,WACA,OACA,SACA;AACA,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,KAAK;AAC5C,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,SAAS;AAE1C,QAAM,WAAW,SAAS;AAE1B,QAAM,YAAQ;AAAA,IACZ,MAAM,IAAI,cAAAA,QAAY,WAAW,QAAQ;AAAA,IACzC,CAAC,WAAW,QAAQ;AAAA,EACtB;AAEA,QAAM,aAAS,0BAAY,MAAM;AAC/B,QAAI,OAAO;AACT,iBAAW,IAAI;AACf,YACG,YAAY,WAAW,KAAK,EAC5B,KAAK,CAACC,UAAS,QAAQA,KAAI,CAAC,EAC5B,MAAM,MAAM,QAAQ,CAAC,CAAC,CAAC,EACvB,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,IACpC,OAAO;AACL,cAAQ,SAAS;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,OAAO,OAAO,SAAS,CAAC;AAE5B,QAAM,YAAQ,0BAAY,MAAM;AAC9B,YAAQ,SAAS;AACjB,eAAW,KAAK;AAAA,EAClB,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO,EAAE,MAAM,SAAS,QAAQ,MAAM;AACxC;",
6
6
  "names": ["SearchIndex", "data"]
7
7
  }
package/cjs/index.js CHANGED
@@ -32,11 +32,11 @@ __export(src_exports, {
32
32
  default: () => src_default
33
33
  });
34
34
  module.exports = __toCommonJS(src_exports);
35
- var import_hook = __toESM(require("./hook"));
36
- __reExport(src_exports, require("./search"), module.exports);
35
+ var import_hook = __toESM(require("@digigov/text-search/hook"));
36
+ __reExport(src_exports, require("@digigov/text-search/search"), module.exports);
37
37
  var src_default = import_hook.default;
38
38
  // Annotate the CommonJS export names for ESM import in node:
39
39
  0 && (module.exports = {
40
- ...require("./search")
40
+ ...require("@digigov/text-search/search")
41
41
  });
42
42
  //# sourceMappingURL=index.js.map
package/cjs/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["import useSearch from './hook';\n\nexport default useSearch;\nexport * from './search';\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsB;AAGtB,wBAAc,qBAHd;AAEA,IAAO,cAAQ,YAAAA;",
4
+ "sourcesContent": ["import useSearch from '@digigov/text-search/hook';\n\nexport default useSearch;\nexport * from '@digigov/text-search/search';\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsB;AAGtB,wBAAc,wCAHd;AAEA,IAAO,cAAQ,YAAAA;",
6
6
  "names": ["useSearch"]
7
7
  }
@@ -21,6 +21,6 @@ __export(search_exports, {
21
21
  default: () => search_default
22
22
  });
23
23
  module.exports = __toCommonJS(search_exports);
24
- var import_search_index = require("./search-index");
24
+ var import_search_index = require("@digigov/text-search/search/search-index");
25
25
  var search_default = import_search_index.SearchIndex;
26
26
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/search/index.ts"],
4
- "sourcesContent": ["import { SearchIndex } from './search-index';\n\nexport default SearchIndex;\n"],
4
+ "sourcesContent": ["import { SearchIndex } from '@digigov/text-search/search/search-index';\n\nexport default SearchIndex;\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA4B;AAE5B,IAAO,iBAAQ;",
6
6
  "names": []
7
7
  }
@@ -21,15 +21,18 @@ __export(encoder_exports, {
21
21
  encodeGreek: () => encodeGreek
22
22
  });
23
23
  module.exports = __toCommonJS(encoder_exports);
24
- var import_normalization_map = require("./normalization-map");
25
- const whitespaceRegex = /[\p{Z}\p{S}\p{P}\p{C}]+/u;
26
- const diacriticsRegex = /[\u0300-\u036f]/g;
24
+ var import_normalization_map = require("@digigov/text-search/search/lang/gr/normalization-map");
25
+ const whitespaceRegex = new RegExp("[p{Z}p{S}p{P}p{C}]+", "u");
26
+ const diacriticsRegex = new RegExp("[\u0300-\u036F]", "g");
27
27
  const greekCharsRegex = new RegExp(
28
28
  Object.keys(import_normalization_map.greekToGreeklishMap).join("|"),
29
29
  "igu"
30
30
  );
31
31
  function encodeGreek(str) {
32
- return ("" + str).toLowerCase().normalize("NFD").replace(diacriticsRegex, "").replace(greekCharsRegex, (match) => import_normalization_map.greekToGreeklishMap[match]).split(whitespaceRegex);
32
+ return ("" + str).toLowerCase().normalize("NFD").replace(diacriticsRegex, "").replace(
33
+ greekCharsRegex,
34
+ (match) => match in import_normalization_map.greekToGreeklishMap ? import_normalization_map.greekToGreeklishMap[match] : match
35
+ ).split(whitespaceRegex);
33
36
  }
34
37
  // Annotate the CommonJS export names for ESM import in node:
35
38
  0 && (module.exports = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/search/lang/gr/encoder.ts"],
4
- "sourcesContent": ["import { greekToGreeklishMap } from './normalization-map';\n\nconst whitespaceRegex = /[\\p{Z}\\p{S}\\p{P}\\p{C}]+/u;\nconst diacriticsRegex = /[\\u0300-\\u036f]/g;\nconst greekCharsRegex = new RegExp(\n Object.keys(greekToGreeklishMap).join('|'),\n 'igu'\n);\n\n/**\n * Encode a string containing greek characters to greeklish\n *\n * This function is used to encode and tokenize a string containing greek characters.\n * It replaces greek characters with their latin counterparts, while also removing\n * any diacritics.\n *\n * @param str - The string to encode\n * @returns An array of encoded words\n */\nexport function encodeGreek(str: string) {\n return ('' + str)\n .toLowerCase()\n .normalize('NFD')\n .replace(diacriticsRegex, '')\n .replace(greekCharsRegex, (match) => (greekToGreeklishMap as any)[match])\n .split(whitespaceRegex);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAAoC;AAEpC,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,kBAAkB,IAAI;AAAA,EAC1B,OAAO,KAAK,4CAAmB,EAAE,KAAK,GAAG;AAAA,EACzC;AACF;AAYO,SAAS,YAAY,KAAa;AACvC,UAAQ,KAAK,KACV,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,iBAAiB,CAAC,UAAW,6CAA4B,KAAK,CAAC,EACvE,MAAM,eAAe;AAC1B;",
4
+ "sourcesContent": ["import { greekToGreeklishMap } from '@digigov/text-search/search/lang/gr/normalization-map';\n\nconst whitespaceRegex = new RegExp('[p{Z}p{S}p{P}p{C}]+', 'u');\nconst diacriticsRegex = new RegExp('[\\u0300-\\u036f]', 'g');\nconst greekCharsRegex = new RegExp(\n Object.keys(greekToGreeklishMap).join('|'),\n 'igu'\n);\n\n/**\n * Encode a string containing greek characters to greeklish\n *\n * This function is used to encode and tokenize a string containing greek characters.\n * It replaces greek characters with their latin counterparts, while also removing\n * any diacritics.\n *\n * @param str - The string to encode\n * @returns An array of encoded words\n */\nexport function encodeGreek(str: string) {\n return ('' + str)\n .toLowerCase()\n .normalize('NFD')\n .replace(diacriticsRegex, '')\n .replace(greekCharsRegex, (match) =>\n match in greekToGreeklishMap\n ? greekToGreeklishMap[match as keyof typeof greekToGreeklishMap]\n : match\n )\n .split(whitespaceRegex);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAAoC;AAEpC,MAAM,kBAAkB,IAAI,OAAO,uBAAuB,GAAG;AAC7D,MAAM,kBAAkB,IAAI,OAAO,mBAAmB,GAAG;AACzD,MAAM,kBAAkB,IAAI;AAAA,EAC1B,OAAO,KAAK,4CAAmB,EAAE,KAAK,GAAG;AAAA,EACzC;AACF;AAYO,SAAS,YAAY,KAAa;AACvC,UAAQ,KAAK,KACV,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,iBAAiB,EAAE,EAC3B;AAAA,IAAQ;AAAA,IAAiB,CAAC,UACzB,SAAS,+CACL,6CAAoB,KAAyC,IAC7D;AAAA,EACN,EACC,MAAM,eAAe;AAC1B;",
6
6
  "names": []
7
7
  }
@@ -22,8 +22,8 @@ __export(search_index_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(search_index_exports);
24
24
  var import_flexsearch = require("flexsearch");
25
- var import_encoder = require("./lang/gr/encoder");
26
- var import_utils = require("./utils");
25
+ var import_encoder = require("@digigov/text-search/search/lang/gr/encoder");
26
+ var import_utils = require("@digigov/text-search/search/utils");
27
27
  class SearchIndex {
28
28
  constructor(items, options) {
29
29
  this.idKey = "id";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/search/search-index.ts"],
4
- "sourcesContent": ["import { Document } from 'flexsearch';\nimport type { SearchIndexOptions } from '../types';\nimport { encodeGreek } from './lang/gr/encoder';\nimport { findItemsByIds, getAllItemKeys, getResultIds } from './utils';\n\n/**\n * Wrapper class around third party index and search library\n *\n * @typeParam T - The type of the data that will be indexed\n */\nexport class SearchIndex<T extends Record<string, any>> {\n /**\n * Instance of the third party library's index\n */\n private index: Document<T>;\n private idKey: string;\n\n constructor(items: T[], options?: SearchIndexOptions<T>) {\n this.idKey = 'id';\n if (options && options.idKey) {\n this.idKey = options.idKey.replace('.', ':');\n } else if (!(items[0] && 'id' in items[0])) {\n items = items.map((item, index) => ({ ...item, id: index }));\n }\n\n let fields: string[] = [];\n if (options && options.fields) {\n fields = options.fields;\n } else if (items[0]) {\n fields = getAllItemKeys(items[0]);\n }\n fields = fields\n .filter((field) => field !== this.idKey)\n .map((field) => field.replace('.', ':'));\n\n this.index = new Document<T>({\n document: {\n id: this.idKey,\n index: fields,\n },\n tokenize: 'forward',\n worker: options?.enableWorker,\n encode: encodeGreek,\n });\n\n this.addAll(items);\n }\n\n /**\n * Add an item to the index\n *\n * @param item - The item to add to the index\n */\n public add(item: T) {\n this.index.add(item);\n return this;\n }\n\n /**\n * Add multiple items to the index\n *\n * @param items - The list of items to add to the index\n */\n public addAll(items: T[]) {\n items.forEach((item) => this.index.add(item));\n return this;\n }\n\n /**\n * Search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public search(documents: T[], searchTerm: string) {\n const res = this.index.search(searchTerm);\n const ids = getResultIds(res);\n return findItemsByIds(\n documents,\n ids,\n this.idKey as Extract<keyof T, string>\n );\n }\n\n /**\n * Asynchronously search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public async searchAsync(documents: T[], searchTerm: string) {\n return this.index\n .searchAsync(searchTerm)\n .then((res) => {\n return getResultIds(res);\n })\n .then((res) =>\n findItemsByIds(documents, res, this.idKey as Extract<keyof T, string>)\n );\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAyB;AAEzB,qBAA4B;AAC5B,mBAA6D;AAOtD,MAAM,YAA2C;AAAA,EAOtD,YAAY,OAAY,SAAiC;AACvD,SAAK,QAAQ;AACb,QAAI,WAAW,QAAQ,OAAO;AAC5B,WAAK,QAAQ,QAAQ,MAAM,QAAQ,KAAK,GAAG;AAAA,IAC7C,WAAW,EAAE,MAAM,CAAC,KAAK,QAAQ,MAAM,CAAC,IAAI;AAC1C,cAAQ,MAAM,IAAI,CAAC,MAAM,WAAW,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE;AAAA,IAC7D;AAEA,QAAI,SAAmB,CAAC;AACxB,QAAI,WAAW,QAAQ,QAAQ;AAC7B,eAAS,QAAQ;AAAA,IACnB,WAAW,MAAM,CAAC,GAAG;AACnB,mBAAS,6BAAe,MAAM,CAAC,CAAC;AAAA,IAClC;AACA,aAAS,OACN,OAAO,CAAC,UAAU,UAAU,KAAK,KAAK,EACtC,IAAI,CAAC,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AAEzC,SAAK,QAAQ,IAAI,2BAAY;AAAA,MAC3B,UAAU;AAAA,QACR,IAAI,KAAK;AAAA,QACT,OAAO;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,QAAQ;AAAA,IACV,CAAC;AAED,SAAK,OAAO,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,IAAI,MAAS;AAClB,SAAK,MAAM,IAAI,IAAI;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAO,OAAY;AACxB,UAAM,QAAQ,CAAC,SAAS,KAAK,MAAM,IAAI,IAAI,CAAC;AAC5C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,OAAO,WAAgB,YAAoB;AAChD,UAAM,MAAM,KAAK,MAAM,OAAO,UAAU;AACxC,UAAM,UAAM,2BAAa,GAAG;AAC5B,eAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,YAAY,WAAgB,YAAoB;AAC3D,WAAO,KAAK,MACT,YAAY,UAAU,EACtB,KAAK,CAAC,QAAQ;AACb,iBAAO,2BAAa,GAAG;AAAA,IACzB,CAAC,EACA;AAAA,MAAK,CAAC,YACL,6BAAe,WAAW,KAAK,KAAK,KAAiC;AAAA,IACvE;AAAA,EACJ;AACF;",
4
+ "sourcesContent": ["import { Document } from 'flexsearch';\nimport { encodeGreek } from '@digigov/text-search/search/lang/gr/encoder';\nimport {\n findItemsByIds,\n getAllItemKeys,\n getResultIds,\n} from '@digigov/text-search/search/utils';\nimport type { SearchIndexOptions } from '@digigov/text-search/types';\n\n/**\n * Wrapper class around third party index and search library\n *\n * @typeParam T - The type of the data that will be indexed\n */\nexport class SearchIndex<T extends Record<string, any>> {\n /**\n * Instance of the third party library's index\n */\n private index: Document<T>;\n private idKey: string;\n\n constructor(items: T[], options?: SearchIndexOptions<T>) {\n this.idKey = 'id';\n if (options && options.idKey) {\n this.idKey = options.idKey.replace('.', ':');\n } else if (!(items[0] && 'id' in items[0])) {\n items = items.map((item, index) => ({ ...item, id: index }));\n }\n\n let fields: string[] = [];\n if (options && options.fields) {\n fields = options.fields;\n } else if (items[0]) {\n fields = getAllItemKeys(items[0]);\n }\n fields = fields\n .filter((field) => field !== this.idKey)\n .map((field) => field.replace('.', ':'));\n\n this.index = new Document<T>({\n document: {\n id: this.idKey,\n index: fields,\n },\n tokenize: 'forward',\n worker: options?.enableWorker,\n encode: encodeGreek,\n });\n\n this.addAll(items);\n }\n\n /**\n * Add an item to the index\n *\n * @param item - The item to add to the index\n */\n public add(item: T) {\n this.index.add(item);\n return this;\n }\n\n /**\n * Add multiple items to the index\n *\n * @param items - The list of items to add to the index\n */\n public addAll(items: T[]) {\n items.forEach((item) => this.index.add(item));\n return this;\n }\n\n /**\n * Search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public search(documents: T[], searchTerm: string) {\n const res = this.index.search(searchTerm);\n const ids = getResultIds(res);\n return findItemsByIds(\n documents,\n ids,\n this.idKey as Extract<keyof T, string>\n );\n }\n\n /**\n * Asynchronously search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public async searchAsync(documents: T[], searchTerm: string) {\n return this.index\n .searchAsync(searchTerm)\n .then((res) => {\n return getResultIds(res);\n })\n .then((res) =>\n findItemsByIds(documents, res, this.idKey as Extract<keyof T, string>)\n );\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAyB;AACzB,qBAA4B;AAC5B,mBAIO;AAQA,MAAM,YAA2C;AAAA,EAOtD,YAAY,OAAY,SAAiC;AACvD,SAAK,QAAQ;AACb,QAAI,WAAW,QAAQ,OAAO;AAC5B,WAAK,QAAQ,QAAQ,MAAM,QAAQ,KAAK,GAAG;AAAA,IAC7C,WAAW,EAAE,MAAM,CAAC,KAAK,QAAQ,MAAM,CAAC,IAAI;AAC1C,cAAQ,MAAM,IAAI,CAAC,MAAM,WAAW,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE;AAAA,IAC7D;AAEA,QAAI,SAAmB,CAAC;AACxB,QAAI,WAAW,QAAQ,QAAQ;AAC7B,eAAS,QAAQ;AAAA,IACnB,WAAW,MAAM,CAAC,GAAG;AACnB,mBAAS,6BAAe,MAAM,CAAC,CAAC;AAAA,IAClC;AACA,aAAS,OACN,OAAO,CAAC,UAAU,UAAU,KAAK,KAAK,EACtC,IAAI,CAAC,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AAEzC,SAAK,QAAQ,IAAI,2BAAY;AAAA,MAC3B,UAAU;AAAA,QACR,IAAI,KAAK;AAAA,QACT,OAAO;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,QAAQ;AAAA,IACV,CAAC;AAED,SAAK,OAAO,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,IAAI,MAAS;AAClB,SAAK,MAAM,IAAI,IAAI;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAO,OAAY;AACxB,UAAM,QAAQ,CAAC,SAAS,KAAK,MAAM,IAAI,IAAI,CAAC;AAC5C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,OAAO,WAAgB,YAAoB;AAChD,UAAM,MAAM,KAAK,MAAM,OAAO,UAAU;AACxC,UAAM,UAAM,2BAAa,GAAG;AAC5B,eAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,YAAY,WAAgB,YAAoB;AAC3D,WAAO,KAAK,MACT,YAAY,UAAU,EACtB,KAAK,CAAC,QAAQ;AACb,iBAAO,2BAAa,GAAG;AAAA,IACzB,CAAC,EACA;AAAA,MAAK,CAAC,YACL,6BAAe,WAAW,KAAK,KAAK,KAAiC;AAAA,IACvE;AAAA,EACJ;AACF;",
6
6
  "names": []
7
7
  }
@@ -39,7 +39,7 @@ function getValueFromNestedKey(object, nestedKey) {
39
39
  const keys = nestedKey.split(":");
40
40
  let result = object;
41
41
  for (const keySegment of keys) {
42
- if (result.hasOwnProperty(keySegment)) {
42
+ if (Object.prototype.hasOwnProperty.call(result, keySegment)) {
43
43
  result = result[keySegment];
44
44
  }
45
45
  }
@@ -48,7 +48,7 @@ function getValueFromNestedKey(object, nestedKey) {
48
48
  function getAllItemKeys(object, parentKey = "") {
49
49
  let keys = [];
50
50
  for (const key in object) {
51
- if (object.hasOwnProperty(key)) {
51
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
52
52
  const currentKey = parentKey ? `${parentKey}.${key}` : key;
53
53
  if (typeof object[key] === "object" && object[key] !== null) {
54
54
  keys = keys.concat(getAllItemKeys(object[key], currentKey));
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/search/utils.ts"],
4
- "sourcesContent": ["import { SimpleDocumentSearchResultSetUnit } from 'flexsearch';\n\n/**\n * Extracts the unique item IDs from the result set\n *\n * @param result - The result set to extract the IDs from\n */\nexport function getResultIds(result: SimpleDocumentSearchResultSetUnit[]) {\n const set = new Set<number | string>();\n result.forEach((item) => {\n item.result.forEach((id) => set.add(id));\n });\n return Array.from(set);\n}\n\n/**\n * Get the items from the list that match the given IDs\n *\n * @param items - The list of items to search through\n * @param ids - The list of IDs to search for\n * @param idKey - The key to use to find the IDs in the items\n */\nexport function findItemsByIds<T extends Record<string, any>>(\n items: T[],\n ids: (string | number)[],\n idKey: Extract<keyof T, string>\n) {\n return items.filter(\n (item) => item && ids.includes(getValueFromNestedKey(item, idKey))\n );\n}\n\nfunction getValueFromNestedKey(object: Record<string, any>, nestedKey: string) {\n const keys = nestedKey.split(':');\n\n let result = object;\n for (const keySegment of keys) {\n if (result.hasOwnProperty(keySegment)) {\n result = result[keySegment];\n }\n }\n return (result as unknown) as string;\n}\n\n/**\n * Recursively get all the keys from an object\n *\n * The keys are returned in the format `parentKey.childKey` for nested objects\n * and `key` for top level objects (objects that are not nested inside another object).\n *\n * @param object - The item to get the keys from\n * @param parentKey - The parent key to which the current key should be appended\n */\nexport function getAllItemKeys(\n object: Record<string, any>,\n parentKey: string = ''\n): string[] {\n let keys: string[] = [];\n for (const key in object) {\n if (object.hasOwnProperty(key)) {\n const currentKey = parentKey ? `${parentKey}.${key}` : key;\n\n if (typeof object[key] === 'object' && object[key] !== null) {\n keys = keys.concat(getAllItemKeys(object[key], currentKey));\n } else {\n keys.push(currentKey);\n }\n }\n }\n\n return keys;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,aAAa,QAA6C;AACxE,QAAM,MAAM,oBAAI,IAAqB;AACrC,SAAO,QAAQ,CAAC,SAAS;AACvB,SAAK,OAAO,QAAQ,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;AAAA,EACzC,CAAC;AACD,SAAO,MAAM,KAAK,GAAG;AACvB;AASO,SAAS,eACd,OACA,KACA,OACA;AACA,SAAO,MAAM;AAAA,IACX,CAAC,SAAS,QAAQ,IAAI,SAAS,sBAAsB,MAAM,KAAK,CAAC;AAAA,EACnE;AACF;AAEA,SAAS,sBAAsB,QAA6B,WAAmB;AAC7E,QAAM,OAAO,UAAU,MAAM,GAAG;AAEhC,MAAI,SAAS;AACb,aAAW,cAAc,MAAM;AAC7B,QAAI,OAAO,eAAe,UAAU,GAAG;AACrC,eAAS,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AACA,SAAQ;AACV;AAWO,SAAS,eACd,QACA,YAAoB,IACV;AACV,MAAI,OAAiB,CAAC;AACtB,aAAW,OAAO,QAAQ;AACxB,QAAI,OAAO,eAAe,GAAG,GAAG;AAC9B,YAAM,aAAa,YAAY,GAAG,SAAS,IAAI,GAAG,KAAK;AAEvD,UAAI,OAAO,OAAO,GAAG,MAAM,YAAY,OAAO,GAAG,MAAM,MAAM;AAC3D,eAAO,KAAK,OAAO,eAAe,OAAO,GAAG,GAAG,UAAU,CAAC;AAAA,MAC5D,OAAO;AACL,aAAK,KAAK,UAAU;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["import { SimpleDocumentSearchResultSetUnit } from 'flexsearch';\n\n/**\n * Extracts the unique item IDs from the result set\n *\n * @param result - The result set to extract the IDs from\n */\nexport function getResultIds(result: SimpleDocumentSearchResultSetUnit[]) {\n const set = new Set<number | string>();\n result.forEach((item) => {\n item.result.forEach((id) => set.add(id));\n });\n return Array.from(set);\n}\n\n/**\n * Get the items from the list that match the given IDs\n *\n * @param items - The list of items to search through\n * @param ids - The list of IDs to search for\n * @param idKey - The key to use to find the IDs in the items\n */\nexport function findItemsByIds<T extends Record<string, any>>(\n items: T[],\n ids: (string | number)[],\n idKey: Extract<keyof T, string>\n) {\n return items.filter(\n (item) => item && ids.includes(getValueFromNestedKey(item, idKey))\n );\n}\n\nfunction getValueFromNestedKey(object: Record<string, any>, nestedKey: string) {\n const keys = nestedKey.split(':');\n\n let result = object;\n for (const keySegment of keys) {\n if (Object.prototype.hasOwnProperty.call(result, keySegment)) {\n result = result[keySegment];\n }\n }\n return result as unknown as string;\n}\n\n/**\n * Recursively get all the keys from an object\n *\n * The keys are returned in the format `parentKey.childKey` for nested objects\n * and `key` for top level objects (objects that are not nested inside another object).\n *\n * @param object - The item to get the keys from\n * @param parentKey - The parent key to which the current key should be appended\n */\nexport function getAllItemKeys(\n object: Record<string, any>,\n parentKey = ''\n): string[] {\n let keys: string[] = [];\n for (const key in object) {\n if (Object.prototype.hasOwnProperty.call(object, key)) {\n const currentKey = parentKey ? `${parentKey}.${key}` : key;\n\n if (typeof object[key] === 'object' && object[key] !== null) {\n keys = keys.concat(getAllItemKeys(object[key], currentKey));\n } else {\n keys.push(currentKey);\n }\n }\n }\n\n return keys;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,aAAa,QAA6C;AACxE,QAAM,MAAM,oBAAI,IAAqB;AACrC,SAAO,QAAQ,CAAC,SAAS;AACvB,SAAK,OAAO,QAAQ,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;AAAA,EACzC,CAAC;AACD,SAAO,MAAM,KAAK,GAAG;AACvB;AASO,SAAS,eACd,OACA,KACA,OACA;AACA,SAAO,MAAM;AAAA,IACX,CAAC,SAAS,QAAQ,IAAI,SAAS,sBAAsB,MAAM,KAAK,CAAC;AAAA,EACnE;AACF;AAEA,SAAS,sBAAsB,QAA6B,WAAmB;AAC7E,QAAM,OAAO,UAAU,MAAM,GAAG;AAEhC,MAAI,SAAS;AACb,aAAW,cAAc,MAAM;AAC7B,QAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,UAAU,GAAG;AAC5D,eAAS,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,eACd,QACA,YAAY,IACF;AACV,MAAI,OAAiB,CAAC;AACtB,aAAW,OAAO,QAAQ;AACxB,QAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AACrD,YAAM,aAAa,YAAY,GAAG,SAAS,IAAI,GAAG,KAAK;AAEvD,UAAI,OAAO,OAAO,GAAG,MAAM,YAAY,OAAO,GAAG,MAAM,MAAM;AAC3D,eAAO,KAAK,OAAO,eAAe,OAAO,GAAG,GAAG,UAAU,CAAC;AAAA,MAC5D,OAAO;AACL,aAAK,KAAK,UAAU;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
package/cjs/types.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/types.ts"],
4
- "sourcesContent": ["/**\n * Options for configuring the useSearch hook\n */\nexport interface UseSearchOptions<T extends Record<string, any>> {\n indexing: SearchIndexOptions<T>;\n}\n\n/**\n * Options for configuring the search index\n *\n * @typeParam T - The type of the data that will be indexed\n */\nexport interface SearchIndexOptions<T> {\n /**\n * Describes where to find the unique ID for each item in the data\n *\n * This can also be a nested key, e.g. `address.street`. If not specified, the search index will\n * create an 'id' field on each item, with the value being the index of the item in the array.\n */\n idKey?: NestedKeyOf<T>;\n /**\n * List of fields to index\n *\n * Contains a list of fields from the document, that should be indexed. The fields can be nested.\n *\n * @example Using nested keys\n * ```\n * {\n * id: 1,\n * name: 'John',\n * address: {\n * street: '123 Main St',\n * city: 'New York'\n * }\n * }\n * ```\n * To search against the `street` key, add `address.street` to the fields array.\n */\n fields?: NestedKeyOf<T>[];\n /**\n * Whether to use a web worker for indexing\n */\n enableWorker?: boolean;\n}\n\n/**\n * Any key of an object that has nested objects.\n *\n * This utility type is used to get all the primitive keys of an object, including the keys of any nested objects.\n *\n * @typeParam ObjectType - The type of the object to get the keys of\n */\nexport type NestedKeyOf<T> = T extends Primitive\n ? never\n :\n | (keyof T & string)\n | { [P in keyof T & string]: DeepSubKeys<T, P> }[keyof T & string];\n\ntype DeepSubKeys<T, P extends keyof T & string> = T[P] extends (infer Inner)[]\n ? `${P}.${NestedKeyOf<Inner>}`\n : T[P] extends object\n ? `${P}.${NestedKeyOf<T[P]>}`\n : never;\n\ntype Primitive = null | undefined | string | number | boolean | symbol | bigint;\n"],
4
+ "sourcesContent": ["/**\n * Options for configuring the useSearch hook\n */\nexport interface UseSearchOptions<T extends Record<string, any>> {\n indexing: SearchIndexOptions<T>;\n}\n\n/**\n * Options for configuring the search index\n *\n * @typeParam T - The type of the data that will be indexed\n */\nexport interface SearchIndexOptions<T> {\n /**\n * Describes where to find the unique ID for each item in the data\n *\n * This can also be a nested key, e.g. `address.street`. If not specified, the search index will\n * create an 'id' field on each item, with the value being the index of the item in the array.\n */\n idKey?: NestedKeyOf<T>;\n /**\n * List of fields to index\n *\n * Contains a list of fields from the document, that should be indexed. The fields can be nested.\n *\n * @example Using nested keys\n * ```\n * {\n * id: 1,\n * name: 'John',\n * address: {\n * street: '123 Main St',\n * city: 'New York'\n * }\n * }\n * ```\n * To search against the `street` key, add `address.street` to the fields array.\n */\n fields?: NestedKeyOf<T>[];\n /**\n * Whether to use a web worker for indexing\n */\n enableWorker?: boolean;\n}\n\n/**\n * Any key of an object that has nested objects.\n *\n * This utility type is used to get all the primitive keys of an object, including the keys of any nested objects.\n *\n * @typeParam ObjectType - The type of the object to get the keys of\n */\nexport type NestedKeyOf<T> = T extends Primitive\n ? never\n :\n | (keyof T & string)\n | { [P in keyof T & string]: DeepSubKeys<T, P> }[keyof T & string];\n\ntype DeepSubKeys<T, P extends keyof T & string> = T[P] extends (infer Inner)[]\n ? `${P}.${NestedKeyOf<Inner>}`\n : T[P] extends object\n ? `${P}.${NestedKeyOf<T[P]>}`\n : never;\n\ntype Primitive = null | undefined | string | number | boolean | symbol | bigint;\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
package/hook/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  import { useCallback, useMemo, useState } from "react";
2
- import SearchIndex from "./search";
2
+ import SearchIndex from "@digigov/text-search/search";
3
3
  function useSearch(documents, query, options) {
4
4
  const [loading, setLoading] = useState(false);
5
5
  const [data, setData] = useState(documents);
6
6
  const indexing = options?.indexing;
7
- const index = useMemo(() => new SearchIndex(documents, indexing), [
8
- documents,
9
- indexing
10
- ]);
7
+ const index = useMemo(
8
+ () => new SearchIndex(documents, indexing),
9
+ [documents, indexing]
10
+ );
11
11
  const search = useCallback(() => {
12
12
  if (query) {
13
13
  setLoading(true);
14
- index.searchAsync(documents, query).then((data2) => setData(data2)).finally(() => setLoading(false));
14
+ index.searchAsync(documents, query).then((data2) => setData(data2)).catch(() => setData([])).finally(() => setLoading(false));
15
15
  } else {
16
16
  setData(documents);
17
17
  }
package/hook.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { UseSearchOptions } from './types';
1
+ import { UseSearchOptions } from '@digigov/text-search/types';
2
2
  /**
3
3
  * Hook for searching through a list of documents
4
4
  *
package/hook.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/hook.ts"],
4
- "sourcesContent": ["import { useCallback, useMemo, useState } from 'react';\nimport SearchIndex from './search';\nimport { UseSearchOptions } from './types';\n\n/**\n * Hook for searching through a list of documents\n *\n * Returns a list of documents that match the search query.\n * If no query is provided, it returns the original list of documents.\n *\n * @param documents - The list of documents to search through\n * @param options - Options for configuring the search index\n * @param query - The search query\n *\n * @typeParam T - The type of the data in the documents list\n */\nexport default function useSearch<T extends Record<string, any>>(\n documents: T[],\n query?: string,\n options?: UseSearchOptions<T>\n) {\n const [loading, setLoading] = useState(false);\n const [data, setData] = useState(documents);\n\n const indexing = options?.indexing;\n\n const index = useMemo(() => new SearchIndex(documents, indexing), [\n documents,\n indexing,\n ]);\n\n const search = useCallback(() => {\n if (query) {\n setLoading(true);\n index\n .searchAsync(documents, query)\n .then((data) => setData(data))\n .finally(() => setLoading(false));\n } else {\n setData(documents);\n }\n }, [query, index, documents]);\n\n const reset = useCallback(() => {\n setData(documents);\n setLoading(false);\n }, [documents]);\n\n return { data, loading, search, reset };\n}\n"],
5
- "mappings": "AAAA,SAAS,aAAa,SAAS,gBAAgB;AAC/C,OAAO,iBAAiB;AAeT,SAAR,UACL,WACA,OACA,SACA;AACA,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,SAAS;AAE1C,QAAM,WAAW,SAAS;AAE1B,QAAM,QAAQ,QAAQ,MAAM,IAAI,YAAY,WAAW,QAAQ,GAAG;AAAA,IAChE;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,SAAS,YAAY,MAAM;AAC/B,QAAI,OAAO;AACT,iBAAW,IAAI;AACf,YACG,YAAY,WAAW,KAAK,EAC5B,KAAK,CAACA,UAAS,QAAQA,KAAI,CAAC,EAC5B,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,IACpC,OAAO;AACL,cAAQ,SAAS;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,OAAO,OAAO,SAAS,CAAC;AAE5B,QAAM,QAAQ,YAAY,MAAM;AAC9B,YAAQ,SAAS;AACjB,eAAW,KAAK;AAAA,EAClB,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO,EAAE,MAAM,SAAS,QAAQ,MAAM;AACxC;",
4
+ "sourcesContent": ["import { useCallback, useMemo, useState } from 'react';\nimport SearchIndex from '@digigov/text-search/search';\nimport { UseSearchOptions } from '@digigov/text-search/types';\n\n/**\n * Hook for searching through a list of documents\n *\n * Returns a list of documents that match the search query.\n * If no query is provided, it returns the original list of documents.\n *\n * @param documents - The list of documents to search through\n * @param options - Options for configuring the search index\n * @param query - The search query\n *\n * @typeParam T - The type of the data in the documents list\n */\nexport default function useSearch<T extends Record<string, any>>(\n documents: T[],\n query?: string,\n options?: UseSearchOptions<T>\n) {\n const [loading, setLoading] = useState(false);\n const [data, setData] = useState(documents);\n\n const indexing = options?.indexing;\n\n const index = useMemo(\n () => new SearchIndex(documents, indexing),\n [documents, indexing]\n );\n\n const search = useCallback(() => {\n if (query) {\n setLoading(true);\n index\n .searchAsync(documents, query)\n .then((data) => setData(data))\n .catch(() => setData([]))\n .finally(() => setLoading(false));\n } else {\n setData(documents);\n }\n }, [query, index, documents]);\n\n const reset = useCallback(() => {\n setData(documents);\n setLoading(false);\n }, [documents]);\n\n return { data, loading, search, reset };\n}\n"],
5
+ "mappings": "AAAA,SAAS,aAAa,SAAS,gBAAgB;AAC/C,OAAO,iBAAiB;AAeT,SAAR,UACL,WACA,OACA,SACA;AACA,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,SAAS;AAE1C,QAAM,WAAW,SAAS;AAE1B,QAAM,QAAQ;AAAA,IACZ,MAAM,IAAI,YAAY,WAAW,QAAQ;AAAA,IACzC,CAAC,WAAW,QAAQ;AAAA,EACtB;AAEA,QAAM,SAAS,YAAY,MAAM;AAC/B,QAAI,OAAO;AACT,iBAAW,IAAI;AACf,YACG,YAAY,WAAW,KAAK,EAC5B,KAAK,CAACA,UAAS,QAAQA,KAAI,CAAC,EAC5B,MAAM,MAAM,QAAQ,CAAC,CAAC,CAAC,EACvB,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,IACpC,OAAO;AACL,cAAQ,SAAS;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,OAAO,OAAO,SAAS,CAAC;AAE5B,QAAM,QAAQ,YAAY,MAAM;AAC9B,YAAQ,SAAS;AACjB,eAAW,KAAK;AAAA,EAClB,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO,EAAE,MAAM,SAAS,QAAQ,MAAM;AACxC;",
6
6
  "names": ["data"]
7
7
  }
package/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import useSearch from './hook';
1
+ import useSearch from '@digigov/text-search/hook';
2
2
  export default useSearch;
3
- export * from './search';
3
+ export * from '@digigov/text-search/search';
package/index.js CHANGED
@@ -1,11 +1,11 @@
1
- /** @license Digigov v1.2.0-85c27c19
1
+ /** @license Digigov v1.2.0-8bbad051
2
2
  *
3
3
  * This source code is licensed under the BSD-2-Clause license found in the
4
4
  * LICENSE file in the root directory of this source tree.
5
5
  */
6
- import useSearch from "./hook";
6
+ import useSearch from "@digigov/text-search/hook";
7
7
  var src_default = useSearch;
8
- export * from "./search";
8
+ export * from "@digigov/text-search/search";
9
9
  export {
10
10
  src_default as default
11
11
  };
package/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import useSearch from './hook';\n\nexport default useSearch;\nexport * from './search';\n"],
4
+ "sourcesContent": ["import useSearch from '@digigov/text-search/hook';\n\nexport default useSearch;\nexport * from '@digigov/text-search/search';\n"],
5
5
  "mappings": "AAAA,OAAO,eAAe;AAEtB,IAAO,cAAQ;AACf,cAAc;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digigov/text-search",
3
- "version": "1.2.0-85c27c19",
3
+ "version": "1.2.0-8bbad051",
4
4
  "description": "@digigov text-search",
5
5
  "author": "GRNET Developers <devs@lists.grnet.gr>",
6
6
  "license": "BSD-2-Clause",
@@ -14,8 +14,8 @@
14
14
  "flexsearch": "0.7.31"
15
15
  },
16
16
  "peerDependencies": {
17
- "react": ">=16.8.0 <19.0.0",
18
- "react-dom": ">=16.8.0 <19.0.0"
17
+ "react": "^18.3.0 || ^19.1.0",
18
+ "react-dom": "^18.3.0 || ^19.1.0"
19
19
  },
20
20
  "typings": "./index.d.ts"
21
21
  }
package/search/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { SearchIndex } from './search-index';
1
+ import { SearchIndex } from '@digigov/text-search/search/search-index';
2
2
  export default SearchIndex;
package/search/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { SearchIndex } from "./search-index";
1
+ import { SearchIndex } from "@digigov/text-search/search/search-index";
2
2
  var search_default = SearchIndex;
3
3
  export {
4
4
  search_default as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/search/index.ts"],
4
- "sourcesContent": ["import { SearchIndex } from './search-index';\n\nexport default SearchIndex;\n"],
4
+ "sourcesContent": ["import { SearchIndex } from '@digigov/text-search/search/search-index';\n\nexport default SearchIndex;\n"],
5
5
  "mappings": "AAAA,SAAS,mBAAmB;AAE5B,IAAO,iBAAQ;",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,15 @@
1
- import { greekToGreeklishMap } from "./normalization-map";
2
- const whitespaceRegex = /[\p{Z}\p{S}\p{P}\p{C}]+/u;
3
- const diacriticsRegex = /[\u0300-\u036f]/g;
1
+ import { greekToGreeklishMap } from "@digigov/text-search/search/lang/gr/normalization-map";
2
+ const whitespaceRegex = new RegExp("[p{Z}p{S}p{P}p{C}]+", "u");
3
+ const diacriticsRegex = new RegExp("[\u0300-\u036F]", "g");
4
4
  const greekCharsRegex = new RegExp(
5
5
  Object.keys(greekToGreeklishMap).join("|"),
6
6
  "igu"
7
7
  );
8
8
  function encodeGreek(str) {
9
- return ("" + str).toLowerCase().normalize("NFD").replace(diacriticsRegex, "").replace(greekCharsRegex, (match) => greekToGreeklishMap[match]).split(whitespaceRegex);
9
+ return ("" + str).toLowerCase().normalize("NFD").replace(diacriticsRegex, "").replace(
10
+ greekCharsRegex,
11
+ (match) => match in greekToGreeklishMap ? greekToGreeklishMap[match] : match
12
+ ).split(whitespaceRegex);
10
13
  }
11
14
  export {
12
15
  encodeGreek
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/search/lang/gr/encoder.ts"],
4
- "sourcesContent": ["import { greekToGreeklishMap } from './normalization-map';\n\nconst whitespaceRegex = /[\\p{Z}\\p{S}\\p{P}\\p{C}]+/u;\nconst diacriticsRegex = /[\\u0300-\\u036f]/g;\nconst greekCharsRegex = new RegExp(\n Object.keys(greekToGreeklishMap).join('|'),\n 'igu'\n);\n\n/**\n * Encode a string containing greek characters to greeklish\n *\n * This function is used to encode and tokenize a string containing greek characters.\n * It replaces greek characters with their latin counterparts, while also removing\n * any diacritics.\n *\n * @param str - The string to encode\n * @returns An array of encoded words\n */\nexport function encodeGreek(str: string) {\n return ('' + str)\n .toLowerCase()\n .normalize('NFD')\n .replace(diacriticsRegex, '')\n .replace(greekCharsRegex, (match) => (greekToGreeklishMap as any)[match])\n .split(whitespaceRegex);\n}\n"],
5
- "mappings": "AAAA,SAAS,2BAA2B;AAEpC,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,kBAAkB,IAAI;AAAA,EAC1B,OAAO,KAAK,mBAAmB,EAAE,KAAK,GAAG;AAAA,EACzC;AACF;AAYO,SAAS,YAAY,KAAa;AACvC,UAAQ,KAAK,KACV,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,iBAAiB,CAAC,UAAW,oBAA4B,KAAK,CAAC,EACvE,MAAM,eAAe;AAC1B;",
4
+ "sourcesContent": ["import { greekToGreeklishMap } from '@digigov/text-search/search/lang/gr/normalization-map';\n\nconst whitespaceRegex = new RegExp('[p{Z}p{S}p{P}p{C}]+', 'u');\nconst diacriticsRegex = new RegExp('[\\u0300-\\u036f]', 'g');\nconst greekCharsRegex = new RegExp(\n Object.keys(greekToGreeklishMap).join('|'),\n 'igu'\n);\n\n/**\n * Encode a string containing greek characters to greeklish\n *\n * This function is used to encode and tokenize a string containing greek characters.\n * It replaces greek characters with their latin counterparts, while also removing\n * any diacritics.\n *\n * @param str - The string to encode\n * @returns An array of encoded words\n */\nexport function encodeGreek(str: string) {\n return ('' + str)\n .toLowerCase()\n .normalize('NFD')\n .replace(diacriticsRegex, '')\n .replace(greekCharsRegex, (match) =>\n match in greekToGreeklishMap\n ? greekToGreeklishMap[match as keyof typeof greekToGreeklishMap]\n : match\n )\n .split(whitespaceRegex);\n}\n"],
5
+ "mappings": "AAAA,SAAS,2BAA2B;AAEpC,MAAM,kBAAkB,IAAI,OAAO,uBAAuB,GAAG;AAC7D,MAAM,kBAAkB,IAAI,OAAO,mBAAmB,GAAG;AACzD,MAAM,kBAAkB,IAAI;AAAA,EAC1B,OAAO,KAAK,mBAAmB,EAAE,KAAK,GAAG;AAAA,EACzC;AACF;AAYO,SAAS,YAAY,KAAa;AACvC,UAAQ,KAAK,KACV,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,iBAAiB,EAAE,EAC3B;AAAA,IAAQ;AAAA,IAAiB,CAAC,UACzB,SAAS,sBACL,oBAAoB,KAAyC,IAC7D;AAAA,EACN,EACC,MAAM,eAAe;AAC1B;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,10 @@
1
1
  import { Document } from "flexsearch";
2
- import { encodeGreek } from "./lang/gr/encoder";
3
- import { findItemsByIds, getAllItemKeys, getResultIds } from "./utils";
2
+ import { encodeGreek } from "@digigov/text-search/search/lang/gr/encoder";
3
+ import {
4
+ findItemsByIds,
5
+ getAllItemKeys,
6
+ getResultIds
7
+ } from "@digigov/text-search/search/utils";
4
8
  class SearchIndex {
5
9
  constructor(items, options) {
6
10
  this.idKey = "id";
@@ -1,4 +1,4 @@
1
- import type { SearchIndexOptions } from '../types';
1
+ import type { SearchIndexOptions } from '@digigov/text-search/types';
2
2
  /**
3
3
  * Wrapper class around third party index and search library
4
4
  *
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/search/search-index.ts"],
4
- "sourcesContent": ["import { Document } from 'flexsearch';\nimport type { SearchIndexOptions } from '../types';\nimport { encodeGreek } from './lang/gr/encoder';\nimport { findItemsByIds, getAllItemKeys, getResultIds } from './utils';\n\n/**\n * Wrapper class around third party index and search library\n *\n * @typeParam T - The type of the data that will be indexed\n */\nexport class SearchIndex<T extends Record<string, any>> {\n /**\n * Instance of the third party library's index\n */\n private index: Document<T>;\n private idKey: string;\n\n constructor(items: T[], options?: SearchIndexOptions<T>) {\n this.idKey = 'id';\n if (options && options.idKey) {\n this.idKey = options.idKey.replace('.', ':');\n } else if (!(items[0] && 'id' in items[0])) {\n items = items.map((item, index) => ({ ...item, id: index }));\n }\n\n let fields: string[] = [];\n if (options && options.fields) {\n fields = options.fields;\n } else if (items[0]) {\n fields = getAllItemKeys(items[0]);\n }\n fields = fields\n .filter((field) => field !== this.idKey)\n .map((field) => field.replace('.', ':'));\n\n this.index = new Document<T>({\n document: {\n id: this.idKey,\n index: fields,\n },\n tokenize: 'forward',\n worker: options?.enableWorker,\n encode: encodeGreek,\n });\n\n this.addAll(items);\n }\n\n /**\n * Add an item to the index\n *\n * @param item - The item to add to the index\n */\n public add(item: T) {\n this.index.add(item);\n return this;\n }\n\n /**\n * Add multiple items to the index\n *\n * @param items - The list of items to add to the index\n */\n public addAll(items: T[]) {\n items.forEach((item) => this.index.add(item));\n return this;\n }\n\n /**\n * Search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public search(documents: T[], searchTerm: string) {\n const res = this.index.search(searchTerm);\n const ids = getResultIds(res);\n return findItemsByIds(\n documents,\n ids,\n this.idKey as Extract<keyof T, string>\n );\n }\n\n /**\n * Asynchronously search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public async searchAsync(documents: T[], searchTerm: string) {\n return this.index\n .searchAsync(searchTerm)\n .then((res) => {\n return getResultIds(res);\n })\n .then((res) =>\n findItemsByIds(documents, res, this.idKey as Extract<keyof T, string>)\n );\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,gBAAgB;AAEzB,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB,gBAAgB,oBAAoB;AAOtD,MAAM,YAA2C;AAAA,EAOtD,YAAY,OAAY,SAAiC;AACvD,SAAK,QAAQ;AACb,QAAI,WAAW,QAAQ,OAAO;AAC5B,WAAK,QAAQ,QAAQ,MAAM,QAAQ,KAAK,GAAG;AAAA,IAC7C,WAAW,EAAE,MAAM,CAAC,KAAK,QAAQ,MAAM,CAAC,IAAI;AAC1C,cAAQ,MAAM,IAAI,CAAC,MAAM,WAAW,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE;AAAA,IAC7D;AAEA,QAAI,SAAmB,CAAC;AACxB,QAAI,WAAW,QAAQ,QAAQ;AAC7B,eAAS,QAAQ;AAAA,IACnB,WAAW,MAAM,CAAC,GAAG;AACnB,eAAS,eAAe,MAAM,CAAC,CAAC;AAAA,IAClC;AACA,aAAS,OACN,OAAO,CAAC,UAAU,UAAU,KAAK,KAAK,EACtC,IAAI,CAAC,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AAEzC,SAAK,QAAQ,IAAI,SAAY;AAAA,MAC3B,UAAU;AAAA,QACR,IAAI,KAAK;AAAA,QACT,OAAO;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,QAAQ;AAAA,IACV,CAAC;AAED,SAAK,OAAO,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,IAAI,MAAS;AAClB,SAAK,MAAM,IAAI,IAAI;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAO,OAAY;AACxB,UAAM,QAAQ,CAAC,SAAS,KAAK,MAAM,IAAI,IAAI,CAAC;AAC5C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,OAAO,WAAgB,YAAoB;AAChD,UAAM,MAAM,KAAK,MAAM,OAAO,UAAU;AACxC,UAAM,MAAM,aAAa,GAAG;AAC5B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,YAAY,WAAgB,YAAoB;AAC3D,WAAO,KAAK,MACT,YAAY,UAAU,EACtB,KAAK,CAAC,QAAQ;AACb,aAAO,aAAa,GAAG;AAAA,IACzB,CAAC,EACA;AAAA,MAAK,CAAC,QACL,eAAe,WAAW,KAAK,KAAK,KAAiC;AAAA,IACvE;AAAA,EACJ;AACF;",
4
+ "sourcesContent": ["import { Document } from 'flexsearch';\nimport { encodeGreek } from '@digigov/text-search/search/lang/gr/encoder';\nimport {\n findItemsByIds,\n getAllItemKeys,\n getResultIds,\n} from '@digigov/text-search/search/utils';\nimport type { SearchIndexOptions } from '@digigov/text-search/types';\n\n/**\n * Wrapper class around third party index and search library\n *\n * @typeParam T - The type of the data that will be indexed\n */\nexport class SearchIndex<T extends Record<string, any>> {\n /**\n * Instance of the third party library's index\n */\n private index: Document<T>;\n private idKey: string;\n\n constructor(items: T[], options?: SearchIndexOptions<T>) {\n this.idKey = 'id';\n if (options && options.idKey) {\n this.idKey = options.idKey.replace('.', ':');\n } else if (!(items[0] && 'id' in items[0])) {\n items = items.map((item, index) => ({ ...item, id: index }));\n }\n\n let fields: string[] = [];\n if (options && options.fields) {\n fields = options.fields;\n } else if (items[0]) {\n fields = getAllItemKeys(items[0]);\n }\n fields = fields\n .filter((field) => field !== this.idKey)\n .map((field) => field.replace('.', ':'));\n\n this.index = new Document<T>({\n document: {\n id: this.idKey,\n index: fields,\n },\n tokenize: 'forward',\n worker: options?.enableWorker,\n encode: encodeGreek,\n });\n\n this.addAll(items);\n }\n\n /**\n * Add an item to the index\n *\n * @param item - The item to add to the index\n */\n public add(item: T) {\n this.index.add(item);\n return this;\n }\n\n /**\n * Add multiple items to the index\n *\n * @param items - The list of items to add to the index\n */\n public addAll(items: T[]) {\n items.forEach((item) => this.index.add(item));\n return this;\n }\n\n /**\n * Search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public search(documents: T[], searchTerm: string) {\n const res = this.index.search(searchTerm);\n const ids = getResultIds(res);\n return findItemsByIds(\n documents,\n ids,\n this.idKey as Extract<keyof T, string>\n );\n }\n\n /**\n * Asynchronously search the index for the given term\n *\n * @param documents - The list of documents to search\n * @param searchTerm - The term to search for\n * @returns The list of items that match the search term\n */\n public async searchAsync(documents: T[], searchTerm: string) {\n return this.index\n .searchAsync(searchTerm)\n .then((res) => {\n return getResultIds(res);\n })\n .then((res) =>\n findItemsByIds(documents, res, this.idKey as Extract<keyof T, string>)\n );\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAQA,MAAM,YAA2C;AAAA,EAOtD,YAAY,OAAY,SAAiC;AACvD,SAAK,QAAQ;AACb,QAAI,WAAW,QAAQ,OAAO;AAC5B,WAAK,QAAQ,QAAQ,MAAM,QAAQ,KAAK,GAAG;AAAA,IAC7C,WAAW,EAAE,MAAM,CAAC,KAAK,QAAQ,MAAM,CAAC,IAAI;AAC1C,cAAQ,MAAM,IAAI,CAAC,MAAM,WAAW,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE;AAAA,IAC7D;AAEA,QAAI,SAAmB,CAAC;AACxB,QAAI,WAAW,QAAQ,QAAQ;AAC7B,eAAS,QAAQ;AAAA,IACnB,WAAW,MAAM,CAAC,GAAG;AACnB,eAAS,eAAe,MAAM,CAAC,CAAC;AAAA,IAClC;AACA,aAAS,OACN,OAAO,CAAC,UAAU,UAAU,KAAK,KAAK,EACtC,IAAI,CAAC,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AAEzC,SAAK,QAAQ,IAAI,SAAY;AAAA,MAC3B,UAAU;AAAA,QACR,IAAI,KAAK;AAAA,QACT,OAAO;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,QAAQ,SAAS;AAAA,MACjB,QAAQ;AAAA,IACV,CAAC;AAED,SAAK,OAAO,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,IAAI,MAAS;AAClB,SAAK,MAAM,IAAI,IAAI;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAO,OAAY;AACxB,UAAM,QAAQ,CAAC,SAAS,KAAK,MAAM,IAAI,IAAI,CAAC;AAC5C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,OAAO,WAAgB,YAAoB;AAChD,UAAM,MAAM,KAAK,MAAM,OAAO,UAAU;AACxC,UAAM,MAAM,aAAa,GAAG;AAC5B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,YAAY,WAAgB,YAAoB;AAC3D,WAAO,KAAK,MACT,YAAY,UAAU,EACtB,KAAK,CAAC,QAAQ;AACb,aAAO,aAAa,GAAG;AAAA,IACzB,CAAC,EACA;AAAA,MAAK,CAAC,QACL,eAAe,WAAW,KAAK,KAAK,KAAiC;AAAA,IACvE;AAAA,EACJ;AACF;",
6
6
  "names": []
7
7
  }
@@ -14,7 +14,7 @@ function getValueFromNestedKey(object, nestedKey) {
14
14
  const keys = nestedKey.split(":");
15
15
  let result = object;
16
16
  for (const keySegment of keys) {
17
- if (result.hasOwnProperty(keySegment)) {
17
+ if (Object.prototype.hasOwnProperty.call(result, keySegment)) {
18
18
  result = result[keySegment];
19
19
  }
20
20
  }
@@ -23,7 +23,7 @@ function getValueFromNestedKey(object, nestedKey) {
23
23
  function getAllItemKeys(object, parentKey = "") {
24
24
  let keys = [];
25
25
  for (const key in object) {
26
- if (object.hasOwnProperty(key)) {
26
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
27
27
  const currentKey = parentKey ? `${parentKey}.${key}` : key;
28
28
  if (typeof object[key] === "object" && object[key] !== null) {
29
29
  keys = keys.concat(getAllItemKeys(object[key], currentKey));
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/search/utils.ts"],
4
- "sourcesContent": ["import { SimpleDocumentSearchResultSetUnit } from 'flexsearch';\n\n/**\n * Extracts the unique item IDs from the result set\n *\n * @param result - The result set to extract the IDs from\n */\nexport function getResultIds(result: SimpleDocumentSearchResultSetUnit[]) {\n const set = new Set<number | string>();\n result.forEach((item) => {\n item.result.forEach((id) => set.add(id));\n });\n return Array.from(set);\n}\n\n/**\n * Get the items from the list that match the given IDs\n *\n * @param items - The list of items to search through\n * @param ids - The list of IDs to search for\n * @param idKey - The key to use to find the IDs in the items\n */\nexport function findItemsByIds<T extends Record<string, any>>(\n items: T[],\n ids: (string | number)[],\n idKey: Extract<keyof T, string>\n) {\n return items.filter(\n (item) => item && ids.includes(getValueFromNestedKey(item, idKey))\n );\n}\n\nfunction getValueFromNestedKey(object: Record<string, any>, nestedKey: string) {\n const keys = nestedKey.split(':');\n\n let result = object;\n for (const keySegment of keys) {\n if (result.hasOwnProperty(keySegment)) {\n result = result[keySegment];\n }\n }\n return (result as unknown) as string;\n}\n\n/**\n * Recursively get all the keys from an object\n *\n * The keys are returned in the format `parentKey.childKey` for nested objects\n * and `key` for top level objects (objects that are not nested inside another object).\n *\n * @param object - The item to get the keys from\n * @param parentKey - The parent key to which the current key should be appended\n */\nexport function getAllItemKeys(\n object: Record<string, any>,\n parentKey: string = ''\n): string[] {\n let keys: string[] = [];\n for (const key in object) {\n if (object.hasOwnProperty(key)) {\n const currentKey = parentKey ? `${parentKey}.${key}` : key;\n\n if (typeof object[key] === 'object' && object[key] !== null) {\n keys = keys.concat(getAllItemKeys(object[key], currentKey));\n } else {\n keys.push(currentKey);\n }\n }\n }\n\n return keys;\n}\n"],
5
- "mappings": "AAOO,SAAS,aAAa,QAA6C;AACxE,QAAM,MAAM,oBAAI,IAAqB;AACrC,SAAO,QAAQ,CAAC,SAAS;AACvB,SAAK,OAAO,QAAQ,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;AAAA,EACzC,CAAC;AACD,SAAO,MAAM,KAAK,GAAG;AACvB;AASO,SAAS,eACd,OACA,KACA,OACA;AACA,SAAO,MAAM;AAAA,IACX,CAAC,SAAS,QAAQ,IAAI,SAAS,sBAAsB,MAAM,KAAK,CAAC;AAAA,EACnE;AACF;AAEA,SAAS,sBAAsB,QAA6B,WAAmB;AAC7E,QAAM,OAAO,UAAU,MAAM,GAAG;AAEhC,MAAI,SAAS;AACb,aAAW,cAAc,MAAM;AAC7B,QAAI,OAAO,eAAe,UAAU,GAAG;AACrC,eAAS,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AACA,SAAQ;AACV;AAWO,SAAS,eACd,QACA,YAAoB,IACV;AACV,MAAI,OAAiB,CAAC;AACtB,aAAW,OAAO,QAAQ;AACxB,QAAI,OAAO,eAAe,GAAG,GAAG;AAC9B,YAAM,aAAa,YAAY,GAAG,SAAS,IAAI,GAAG,KAAK;AAEvD,UAAI,OAAO,OAAO,GAAG,MAAM,YAAY,OAAO,GAAG,MAAM,MAAM;AAC3D,eAAO,KAAK,OAAO,eAAe,OAAO,GAAG,GAAG,UAAU,CAAC;AAAA,MAC5D,OAAO;AACL,aAAK,KAAK,UAAU;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["import { SimpleDocumentSearchResultSetUnit } from 'flexsearch';\n\n/**\n * Extracts the unique item IDs from the result set\n *\n * @param result - The result set to extract the IDs from\n */\nexport function getResultIds(result: SimpleDocumentSearchResultSetUnit[]) {\n const set = new Set<number | string>();\n result.forEach((item) => {\n item.result.forEach((id) => set.add(id));\n });\n return Array.from(set);\n}\n\n/**\n * Get the items from the list that match the given IDs\n *\n * @param items - The list of items to search through\n * @param ids - The list of IDs to search for\n * @param idKey - The key to use to find the IDs in the items\n */\nexport function findItemsByIds<T extends Record<string, any>>(\n items: T[],\n ids: (string | number)[],\n idKey: Extract<keyof T, string>\n) {\n return items.filter(\n (item) => item && ids.includes(getValueFromNestedKey(item, idKey))\n );\n}\n\nfunction getValueFromNestedKey(object: Record<string, any>, nestedKey: string) {\n const keys = nestedKey.split(':');\n\n let result = object;\n for (const keySegment of keys) {\n if (Object.prototype.hasOwnProperty.call(result, keySegment)) {\n result = result[keySegment];\n }\n }\n return result as unknown as string;\n}\n\n/**\n * Recursively get all the keys from an object\n *\n * The keys are returned in the format `parentKey.childKey` for nested objects\n * and `key` for top level objects (objects that are not nested inside another object).\n *\n * @param object - The item to get the keys from\n * @param parentKey - The parent key to which the current key should be appended\n */\nexport function getAllItemKeys(\n object: Record<string, any>,\n parentKey = ''\n): string[] {\n let keys: string[] = [];\n for (const key in object) {\n if (Object.prototype.hasOwnProperty.call(object, key)) {\n const currentKey = parentKey ? `${parentKey}.${key}` : key;\n\n if (typeof object[key] === 'object' && object[key] !== null) {\n keys = keys.concat(getAllItemKeys(object[key], currentKey));\n } else {\n keys.push(currentKey);\n }\n }\n }\n\n return keys;\n}\n"],
5
+ "mappings": "AAOO,SAAS,aAAa,QAA6C;AACxE,QAAM,MAAM,oBAAI,IAAqB;AACrC,SAAO,QAAQ,CAAC,SAAS;AACvB,SAAK,OAAO,QAAQ,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;AAAA,EACzC,CAAC;AACD,SAAO,MAAM,KAAK,GAAG;AACvB;AASO,SAAS,eACd,OACA,KACA,OACA;AACA,SAAO,MAAM;AAAA,IACX,CAAC,SAAS,QAAQ,IAAI,SAAS,sBAAsB,MAAM,KAAK,CAAC;AAAA,EACnE;AACF;AAEA,SAAS,sBAAsB,QAA6B,WAAmB;AAC7E,QAAM,OAAO,UAAU,MAAM,GAAG;AAEhC,MAAI,SAAS;AACb,aAAW,cAAc,MAAM;AAC7B,QAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,UAAU,GAAG;AAC5D,eAAS,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,eACd,QACA,YAAY,IACF;AACV,MAAI,OAAiB,CAAC;AACtB,aAAW,OAAO,QAAQ;AACxB,QAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AACrD,YAAM,aAAa,YAAY,GAAG,SAAS,IAAI,GAAG,KAAK;AAEvD,UAAI,OAAO,OAAO,GAAG,MAAM,YAAY,OAAO,GAAG,MAAM,MAAM;AAC3D,eAAO,KAAK,OAAO,eAAe,OAAO,GAAG,GAAG,UAAU,CAAC;AAAA,MAC5D,OAAO;AACL,aAAK,KAAK,UAAU;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
package/src/hook.spec.ts CHANGED
@@ -1,6 +1,8 @@
1
- import { act, renderHook } from '@testing-library/react-hooks';
2
- import useSearch from './hook';
3
- import documents from './test-utils/data.json';
1
+ import { act, renderHook, waitFor } from '@testing-library/react';
2
+ import useSearch from '@digigov/text-search/hook';
3
+ import documents from '@digigov/text-search/test-utils/data.json';
4
+
5
+ // TODO: This test file is currently being ignored. Fix flexsearch types issue
4
6
 
5
7
  describe('loading', () => {
6
8
  it('should start when searching', async () => {
@@ -10,33 +12,27 @@ describe('loading', () => {
10
12
  expect(result.current.loading).toBe(true);
11
13
  });
12
14
  it('should stop after search is completed', async () => {
13
- const { result, waitForNextUpdate } = renderHook(() =>
14
- useSearch(documents, 'Anastasia')
15
- );
15
+ const { result } = renderHook(() => useSearch(documents, 'Anastasia'));
16
16
  expect(result.current.loading).toBe(false);
17
17
  act(() => result.current.search());
18
18
  expect(result.current.loading).toBe(true);
19
- await waitForNextUpdate();
20
- expect(result.current.loading).toBe(false);
19
+ await waitFor(() => expect(result.current.loading).toBe(false));
21
20
  });
22
21
  });
23
22
 
24
23
  describe('reset', () => {
25
24
  it('should change the returned result back to the initial data', async () => {
26
- const { result, waitForNextUpdate } = renderHook(() =>
27
- useSearch(documents, 'Anastasia')
28
- );
25
+ const { result } = renderHook(() => useSearch(documents, 'Anastasia'));
29
26
  expect(result.current.loading).toBe(false);
30
27
  act(() => result.current.search());
31
28
  expect(result.current.loading).toBe(true);
32
29
  expect(result.current.data).toEqual(documents);
33
- await waitForNextUpdate();
34
- expect(result.current.loading).toBe(false);
30
+ await waitFor(() => expect(result.current.loading).toBe(false));
35
31
  expect(result.current.data.length).toBe(1);
36
32
 
37
33
  act(() => result.current.reset());
38
34
  expect(result.current.data).toEqual(documents);
39
- expect(result.current.loading).toBe(false);
35
+ await waitFor(() => expect(result.current.loading).toBe(false));
40
36
  });
41
37
  });
42
38
 
@@ -45,23 +41,20 @@ describe('search', () => {
45
41
  const { result } = renderHook(() => useSearch(documents));
46
42
  expect(result.current.loading).toBe(false);
47
43
  act(() => result.current.search());
48
- expect(result.current.loading).toBe(false);
44
+ await waitFor(() => expect(result.current.loading).toBe(false));
49
45
  expect(result.current.data).toEqual(documents);
50
46
  });
51
47
  it('should return an empty array when there are no relevant items', async () => {
52
- const { result, waitForNextUpdate } = renderHook(() =>
53
- useSearch(documents, 'fajsgsdgsdgsd')
54
- );
48
+ const { result } = renderHook(() => useSearch(documents, 'fajsgsdgsdgsd'));
55
49
  expect(result.current.loading).toBe(false);
56
50
  act(() => result.current.search());
57
51
  expect(result.current.loading).toBe(true);
58
52
  expect(result.current.data).toEqual(documents);
59
- await waitForNextUpdate();
60
- expect(result.current.loading).toBe(false);
53
+ await waitFor(() => expect(result.current.loading).toBe(false));
61
54
  expect(result.current.data).toEqual([]);
62
55
  });
63
56
  it('should return an empty array when relevant field is not indexed', async () => {
64
- const { result, waitForNextUpdate } = renderHook(() =>
57
+ const { result } = renderHook(() =>
65
58
  useSearch(documents, 'Anastasia', {
66
59
  indexing: {
67
60
  fields: ['lastName'], // missing 'firstName'
@@ -72,38 +65,31 @@ describe('search', () => {
72
65
  act(() => result.current.search());
73
66
  expect(result.current.loading).toBe(true);
74
67
  expect(result.current.data).toEqual(documents);
75
- await waitForNextUpdate();
76
- expect(result.current.loading).toBe(false);
68
+ await waitFor(() => expect(result.current.loading).toBe(false));
77
69
  expect(result.current.data).toEqual([]);
78
70
  });
79
71
  it('should return a single result when there is only one relevant item', async () => {
80
- const { result, waitForNextUpdate } = renderHook(() =>
81
- useSearch(documents, 'Anastasia')
82
- );
72
+ const { result } = renderHook(() => useSearch(documents, 'Anastasia'));
83
73
  expect(result.current.loading).toBe(false);
84
74
  act(() => result.current.search());
85
75
  expect(result.current.loading).toBe(true);
86
76
  expect(result.current.data).toEqual(documents);
87
- await waitForNextUpdate();
88
- expect(result.current.loading).toBe(false);
77
+ await waitFor(() => expect(result.current.loading).toBe(false));
89
78
  expect(result.current.data.length).toBe(1);
90
79
 
91
80
  const firstResult = result.current.data[0] as NonNullable<
92
- typeof result.current.data[0]
81
+ (typeof result.current.data)[0]
93
82
  >;
94
83
  expect(firstResult).toBeDefined();
95
84
  expect(Object.values(firstResult).values()).toContain('Anastasia');
96
85
  });
97
86
  it('should return multiple results when there are multiple relevant items', async () => {
98
- const { result, waitForNextUpdate } = renderHook(() =>
99
- useSearch(documents, 'Kari')
100
- );
87
+ const { result } = renderHook(() => useSearch(documents, 'Kari'));
101
88
  expect(result.current.loading).toBe(false);
102
89
  act(() => result.current.search());
103
90
  expect(result.current.loading).toBe(true);
104
91
  expect(result.current.data).toEqual(documents);
105
- await waitForNextUpdate();
106
- expect(result.current.loading).toBe(false);
92
+ await waitFor(() => expect(result.current.loading).toBe(false));
107
93
  expect(result.current.data.length).toBeGreaterThanOrEqual(2);
108
94
 
109
95
  result.current.data.forEach((item) => {
@@ -112,43 +98,37 @@ describe('search', () => {
112
98
  });
113
99
  });
114
100
  it('should work with a partial query', async () => {
115
- const { result, waitForNextUpdate } = renderHook(() =>
116
- useSearch(documents, 'anast')
117
- );
101
+ const { result } = renderHook(() => useSearch(documents, 'anast'));
118
102
  expect(result.current.loading).toBe(false);
119
103
  act(() => result.current.search());
120
104
  expect(result.current.loading).toBe(true);
121
105
  expect(result.current.data).toEqual(documents);
122
- await waitForNextUpdate();
123
- expect(result.current.loading).toBe(false);
106
+ await waitFor(() => expect(result.current.loading).toBe(false));
124
107
  expect(result.current.data.length).toBe(1);
125
108
 
126
109
  const firstResult = result.current.data[0] as NonNullable<
127
- typeof result.current.data[0]
110
+ (typeof result.current.data)[0]
128
111
  >;
129
112
  expect(firstResult).toBeDefined();
130
113
  expect(Object.values(firstResult).values()).toContain('Anastasia');
131
114
  });
132
115
  it('should work with nested field if not explicitly stated', async () => {
133
- const { result, waitForNextUpdate } = renderHook(() =>
134
- useSearch(documents, 'Titanic')
135
- );
116
+ const { result } = renderHook(() => useSearch(documents, 'Titanic'));
136
117
  expect(result.current.loading).toBe(false);
137
118
  act(() => result.current.search());
138
119
  expect(result.current.loading).toBe(true);
139
120
  expect(result.current.data).toEqual(documents);
140
- await waitForNextUpdate();
141
- expect(result.current.loading).toBe(false);
121
+ await waitFor(() => expect(result.current.loading).toBe(false));
142
122
  expect(result.current.data.length).toBe(1);
143
123
 
144
124
  const firstResult = result.current.data[0] as NonNullable<
145
- typeof result.current.data[0]
125
+ (typeof result.current.data)[0]
146
126
  >;
147
127
  expect(firstResult).toBeDefined();
148
128
  expect(Object.values(firstResult.address).values()).toContain('Titanic');
149
129
  });
150
130
  it('should work with nested field if explicitly stated', async () => {
151
- const { result, waitForNextUpdate } = renderHook(() =>
131
+ const { result } = renderHook(() =>
152
132
  useSearch(documents, 'Titanic', {
153
133
  indexing: {
154
134
  fields: ['address.city'],
@@ -159,18 +139,17 @@ describe('search', () => {
159
139
  act(() => result.current.search());
160
140
  expect(result.current.loading).toBe(true);
161
141
  expect(result.current.data).toEqual(documents);
162
- await waitForNextUpdate();
163
- expect(result.current.loading).toBe(false);
142
+ await waitFor(() => expect(result.current.loading).toBe(false));
164
143
  expect(result.current.data.length).toBe(1);
165
144
 
166
145
  const firstResult = result.current.data[0] as NonNullable<
167
- typeof result.current.data[0]
146
+ (typeof result.current.data)[0]
168
147
  >;
169
148
  expect(firstResult).toBeDefined();
170
149
  expect(Object.values(firstResult.address).values()).toContain('Titanic');
171
150
  });
172
151
  it('should work with nested ID', async () => {
173
- const { result, waitForNextUpdate } = renderHook(() =>
152
+ const { result } = renderHook(() =>
174
153
  useSearch(documents, 'Titanic', {
175
154
  indexing: {
176
155
  idKey: 'address.street',
@@ -181,55 +160,48 @@ describe('search', () => {
181
160
  act(() => result.current.search());
182
161
  expect(result.current.loading).toBe(true);
183
162
  expect(result.current.data).toEqual(documents);
184
- await waitForNextUpdate();
185
- expect(result.current.loading).toBe(false);
163
+ await waitFor(() => expect(result.current.loading).toBe(false));
186
164
  expect(result.current.data.length).toBe(1);
187
165
 
188
166
  const firstResult = result.current.data[0] as NonNullable<
189
- typeof result.current.data[0]
167
+ (typeof result.current.data)[0]
190
168
  >;
191
169
  expect(firstResult).toBeDefined();
192
170
  expect(Object.values(firstResult.address).values()).toContain('Titanic');
193
171
  });
194
172
  it('should work with indexed Greek characters and Latin query', async () => {
195
- const { result, waitForNextUpdate } = renderHook(() =>
196
- useSearch(documents, 'Markos')
197
- );
173
+ const { result } = renderHook(() => useSearch(documents, 'Markos'));
198
174
  expect(result.current.loading).toBe(false);
199
175
  act(() => result.current.search());
200
176
  expect(result.current.loading).toBe(true);
201
177
  expect(result.current.data).toEqual(documents);
202
- await waitForNextUpdate();
203
- expect(result.current.loading).toBe(false);
178
+ await waitFor(() => expect(result.current.loading).toBe(false));
204
179
  expect(result.current.data.length).toBe(1);
205
180
 
206
181
  const firstResult = result.current.data[0] as NonNullable<
207
- typeof result.current.data[0]
182
+ (typeof result.current.data)[0]
208
183
  >;
209
184
  expect(firstResult).toBeDefined();
210
185
  expect(Object.values(firstResult).values()).toContain('Μάρκος');
211
186
  });
212
187
  it('should work with indexed Greek characters and Greek query', async () => {
213
- const { result, waitForNextUpdate } = renderHook(() =>
214
- useSearch(documents, 'Μάρκος')
215
- );
188
+ const { result } = renderHook(() => useSearch(documents, 'Μάρκος'));
216
189
  expect(result.current.loading).toBe(false);
217
190
  act(() => result.current.search());
218
191
  expect(result.current.loading).toBe(true);
219
192
  expect(result.current.data).toEqual(documents);
220
- await waitForNextUpdate();
221
- expect(result.current.loading).toBe(false);
193
+ await waitFor(() => expect(result.current.loading).toBe(false));
222
194
  expect(result.current.data.length).toBe(1);
223
195
 
224
196
  const firstResult = result.current.data[0] as NonNullable<
225
- typeof result.current.data[0]
197
+ (typeof result.current.data)[0]
226
198
  >;
227
199
  expect(firstResult).toBeDefined();
228
200
  expect(Object.values(firstResult).values()).toContain('Μάρκος');
229
201
  });
230
202
  it('should react to changes in the documents list', async () => {
231
203
  const emptyDocuments: typeof documents = [];
232
- const { result, rerender, waitForNextUpdate } = renderHook(
204
+ const { result, rerender } = renderHook(
233
205
  ({ documents }) => useSearch(documents, 'Anastasia'),
234
206
  {
235
207
  initialProps: { documents: emptyDocuments },
@@ -238,8 +210,7 @@ describe('search', () => {
238
210
  expect(result.current.loading).toBe(false);
239
211
  act(() => result.current.search());
240
212
  expect(result.current.loading).toBe(true);
241
- await waitForNextUpdate();
242
- expect(result.current.loading).toBe(false);
213
+ await waitFor(() => expect(result.current.loading).toBe(false));
243
214
  expect(result.current.data).toEqual([]);
244
215
 
245
216
  rerender({ documents });
@@ -249,18 +220,17 @@ describe('search', () => {
249
220
  act(() => result.current.search());
250
221
  expect(result.current.loading).toBe(true);
251
222
  expect(result.current.data).toEqual([]);
252
- await waitForNextUpdate();
253
- expect(result.current.loading).toBe(false);
223
+ await waitFor(() => expect(result.current.loading).toBe(false));
254
224
  expect(result.current.data.length).toBe(1);
255
225
 
256
226
  const firstResult = result.current.data[0] as NonNullable<
257
- typeof result.current.data[0]
227
+ (typeof result.current.data)[0]
258
228
  >;
259
229
  expect(firstResult).toBeDefined();
260
230
  expect(Object.values(firstResult).values()).toContain('Anastasia');
261
231
  });
262
232
  it('should react to changes in the search query', async () => {
263
- const { result, rerender, waitForNextUpdate } = renderHook(
233
+ const { result, rerender } = renderHook(
264
234
  ({ query }) => useSearch(documents, query),
265
235
  {
266
236
  initialProps: { query: '' },
@@ -276,12 +246,11 @@ describe('search', () => {
276
246
  act(() => result.current.search());
277
247
  expect(result.current.loading).toBe(true);
278
248
  expect(result.current.data).toEqual(documents);
279
- await waitForNextUpdate();
280
- expect(result.current.loading).toBe(false);
249
+ await waitFor(() => expect(result.current.loading).toBe(false));
281
250
  expect(result.current.data.length).toBe(1);
282
251
 
283
252
  const firstResult = result.current.data[0] as NonNullable<
284
- typeof result.current.data[0]
253
+ (typeof result.current.data)[0]
285
254
  >;
286
255
  expect(firstResult).toBeDefined();
287
256
  expect(Object.values(firstResult).values()).toContain('Anastasia');
package/src/hook.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useCallback, useMemo, useState } from 'react';
2
- import SearchIndex from './search';
3
- import { UseSearchOptions } from './types';
2
+ import SearchIndex from '@digigov/text-search/search';
3
+ import { UseSearchOptions } from '@digigov/text-search/types';
4
4
 
5
5
  /**
6
6
  * Hook for searching through a list of documents
@@ -24,10 +24,10 @@ export default function useSearch<T extends Record<string, any>>(
24
24
 
25
25
  const indexing = options?.indexing;
26
26
 
27
- const index = useMemo(() => new SearchIndex(documents, indexing), [
28
- documents,
29
- indexing,
30
- ]);
27
+ const index = useMemo(
28
+ () => new SearchIndex(documents, indexing),
29
+ [documents, indexing]
30
+ );
31
31
 
32
32
  const search = useCallback(() => {
33
33
  if (query) {
@@ -35,6 +35,7 @@ export default function useSearch<T extends Record<string, any>>(
35
35
  index
36
36
  .searchAsync(documents, query)
37
37
  .then((data) => setData(data))
38
+ .catch(() => setData([]))
38
39
  .finally(() => setLoading(false));
39
40
  } else {
40
41
  setData(documents);
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import useSearch from './hook';
1
+ import useSearch from '@digigov/text-search/hook';
2
2
 
3
3
  export default useSearch;
4
- export * from './search';
4
+ export * from '@digigov/text-search/search';
@@ -1,5 +1,9 @@
1
1
  import type { SimpleDocumentSearchResultSetUnit as ResultType } from 'flexsearch';
2
- import { findItemsByIds, getAllItemKeys, getResultIds } from '../utils';
2
+ import {
3
+ findItemsByIds,
4
+ getAllItemKeys,
5
+ getResultIds,
6
+ } from '@digigov/text-search/search/utils';
3
7
 
4
8
  describe('utils', () => {
5
9
  describe('getResultIds', () => {
@@ -1,3 +1,3 @@
1
- import { SearchIndex } from './search-index';
1
+ import { SearchIndex } from '@digigov/text-search/search/search-index';
2
2
 
3
3
  export default SearchIndex;
@@ -1,7 +1,7 @@
1
- import { greekToGreeklishMap } from './normalization-map';
1
+ import { greekToGreeklishMap } from '@digigov/text-search/search/lang/gr/normalization-map';
2
2
 
3
- const whitespaceRegex = /[\p{Z}\p{S}\p{P}\p{C}]+/u;
4
- const diacriticsRegex = /[\u0300-\u036f]/g;
3
+ const whitespaceRegex = new RegExp('[p{Z}p{S}p{P}p{C}]+', 'u');
4
+ const diacriticsRegex = new RegExp('[\u0300-\u036f]', 'g');
5
5
  const greekCharsRegex = new RegExp(
6
6
  Object.keys(greekToGreeklishMap).join('|'),
7
7
  'igu'
@@ -22,6 +22,10 @@ export function encodeGreek(str: string) {
22
22
  .toLowerCase()
23
23
  .normalize('NFD')
24
24
  .replace(diacriticsRegex, '')
25
- .replace(greekCharsRegex, (match) => (greekToGreeklishMap as any)[match])
25
+ .replace(greekCharsRegex, (match) =>
26
+ match in greekToGreeklishMap
27
+ ? greekToGreeklishMap[match as keyof typeof greekToGreeklishMap]
28
+ : match
29
+ )
26
30
  .split(whitespaceRegex);
27
31
  }
@@ -1,7 +1,11 @@
1
1
  import { Document } from 'flexsearch';
2
- import type { SearchIndexOptions } from '../types';
3
- import { encodeGreek } from './lang/gr/encoder';
4
- import { findItemsByIds, getAllItemKeys, getResultIds } from './utils';
2
+ import { encodeGreek } from '@digigov/text-search/search/lang/gr/encoder';
3
+ import {
4
+ findItemsByIds,
5
+ getAllItemKeys,
6
+ getResultIds,
7
+ } from '@digigov/text-search/search/utils';
8
+ import type { SearchIndexOptions } from '@digigov/text-search/types';
5
9
 
6
10
  /**
7
11
  * Wrapper class around third party index and search library
@@ -35,11 +35,11 @@ function getValueFromNestedKey(object: Record<string, any>, nestedKey: string) {
35
35
 
36
36
  let result = object;
37
37
  for (const keySegment of keys) {
38
- if (result.hasOwnProperty(keySegment)) {
38
+ if (Object.prototype.hasOwnProperty.call(result, keySegment)) {
39
39
  result = result[keySegment];
40
40
  }
41
41
  }
42
- return (result as unknown) as string;
42
+ return result as unknown as string;
43
43
  }
44
44
 
45
45
  /**
@@ -53,11 +53,11 @@ function getValueFromNestedKey(object: Record<string, any>, nestedKey: string) {
53
53
  */
54
54
  export function getAllItemKeys(
55
55
  object: Record<string, any>,
56
- parentKey: string = ''
56
+ parentKey = ''
57
57
  ): string[] {
58
58
  let keys: string[] = [];
59
59
  for (const key in object) {
60
- if (object.hasOwnProperty(key)) {
60
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
61
61
  const currentKey = parentKey ? `${parentKey}.${key}` : key;
62
62
 
63
63
  if (typeof object[key] === 'object' && object[key] !== null) {
package/src/types.ts CHANGED
@@ -59,7 +59,7 @@ export type NestedKeyOf<T> = T extends Primitive
59
59
  type DeepSubKeys<T, P extends keyof T & string> = T[P] extends (infer Inner)[]
60
60
  ? `${P}.${NestedKeyOf<Inner>}`
61
61
  : T[P] extends object
62
- ? `${P}.${NestedKeyOf<T[P]>}`
63
- : never;
62
+ ? `${P}.${NestedKeyOf<T[P]>}`
63
+ : never;
64
64
 
65
65
  type Primitive = null | undefined | string | number | boolean | symbol | bigint;