@tinacms/search 0.0.0-c1132cd-20241024060747 → 0.0.0-c19d29e-20251224001156

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/README.md CHANGED
@@ -0,0 +1,55 @@
1
+ # @tinacms/search
2
+
3
+ Full-text search for TinaCMS powered by [search-index](https://github.com/fergiemcdowall/search-index).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @tinacms/search
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { LocalSearchIndexClient } from "@tinacms/search";
15
+
16
+ const client = new LocalSearchIndexClient({
17
+ stopwordLanguages: ["eng"],
18
+ });
19
+
20
+ await client.onStartIndexing();
21
+
22
+ await client.put([
23
+ {
24
+ _id: "1",
25
+ title: "Getting Started",
26
+ body: "TinaCMS is a Git-backed headless CMS",
27
+ },
28
+ {
29
+ _id: "2",
30
+ title: "React Tutorial",
31
+ body: "Learn how to build React applications",
32
+ },
33
+ ]);
34
+
35
+ // Basic search
36
+ const results = await client.query("TinaCMS", { limit: 10 });
37
+
38
+ // Fuzzy search (handles typos)
39
+ const fuzzyResults = await client.query("TinCMS tutrial", {
40
+ fuzzy: true,
41
+ limit: 10,
42
+ });
43
+ ```
44
+
45
+ ## API
46
+
47
+ - `client.onStartIndexing()` - Initialize the index
48
+ - `client.put(documents)` - Index documents
49
+ - `client.query(query, options)` - Search the index
50
+ - `client.del(ids)` - Delete documents
51
+ - `client.export(filename)` - Export index to SQLite
52
+
53
+ ## License
54
+
55
+ Apache 2.0
@@ -1,5 +1,6 @@
1
- import type { SearchClient } from '../types';
1
+ import type { SearchClient, SearchOptions, SearchQueryResponse, IndexableDocument, SearchIndex } from '../types';
2
2
  import { MemoryLevel } from 'memory-level';
3
+ import { FuzzySearchWrapper } from '../fuzzy-search-wrapper';
3
4
  type TinaSearchIndexerClientOptions = {
4
5
  stopwordLanguages?: string[];
5
6
  tokenSplitRegex?: string;
@@ -10,23 +11,16 @@ type TinaCloudSearchIndexerClientOptions = {
10
11
  indexerToken: string;
11
12
  } & TinaSearchIndexerClientOptions;
12
13
  export declare class LocalSearchIndexClient implements SearchClient {
13
- searchIndex: any;
14
+ searchIndex?: SearchIndex;
14
15
  protected readonly memoryLevel: MemoryLevel;
15
16
  private readonly stopwords;
16
17
  private readonly tokenSplitRegex;
18
+ fuzzySearchWrapper?: FuzzySearchWrapper;
17
19
  constructor(options: TinaSearchIndexerClientOptions);
18
20
  onStartIndexing(): Promise<void>;
19
- put(docs: any[]): Promise<any>;
20
- del(ids: string[]): Promise<any>;
21
- query(query: string, options: {
22
- cursor?: string;
23
- limit?: number;
24
- } | undefined): Promise<{
25
- results: any[];
26
- total: number;
27
- nextCursor: string | null;
28
- prevCursor: string | null;
29
- }>;
21
+ put(docs: IndexableDocument[]): Promise<void>;
22
+ del(ids: string[]): Promise<void>;
23
+ query(query: string, options?: SearchOptions): Promise<SearchQueryResponse>;
30
24
  export(filename: string): Promise<void>;
31
25
  }
32
26
  export declare class TinaCMSSearchIndexClient extends LocalSearchIndexClient {
@@ -34,6 +28,9 @@ export declare class TinaCMSSearchIndexClient extends LocalSearchIndexClient {
34
28
  private readonly branch;
35
29
  private readonly indexerToken;
36
30
  constructor(options: TinaCloudSearchIndexerClientOptions);
31
+ private getUploadUrl;
32
+ private serializeIndex;
33
+ private uploadIndex;
37
34
  onFinishIndexing(): Promise<void>;
38
35
  }
39
36
  export {};
@@ -0,0 +1,11 @@
1
+ import type { FuzzyMatch, FuzzySearchOptions } from './types';
2
+ export declare class FuzzyCache {
3
+ private cache;
4
+ private maxSize;
5
+ constructor(maxSize?: number);
6
+ private getCacheKey;
7
+ get(query: string, options: Partial<FuzzySearchOptions>): FuzzyMatch[] | undefined;
8
+ set(query: string, options: Partial<FuzzySearchOptions>, results: FuzzyMatch[]): void;
9
+ clear(): void;
10
+ get size(): number;
11
+ }
@@ -0,0 +1,8 @@
1
+ import type { FuzzySearchOptions, FuzzyMatch } from './types';
2
+ export declare const PREFIX_MATCH_MIN_SIMILARITY = 0.8;
3
+ export declare function levenshteinDistance(str1: string, str2: string): number;
4
+ export declare function similarityScore(str1: string, str2: string, useTranspositions?: boolean): number;
5
+ export declare function damerauLevenshteinDistance(str1: string, str2: string): number;
6
+ export declare function getNgrams(str: string, n?: number): Set<string>;
7
+ export declare function ngramOverlap(ngrams1: Set<string>, ngrams2: Set<string>): number;
8
+ export declare function findSimilarTerms(query: string, dictionary: string[], options?: FuzzySearchOptions): FuzzyMatch[];
@@ -0,0 +1,4 @@
1
+ export type { FuzzySearchOptions, FuzzyMatch } from './types';
2
+ export { DEFAULT_FUZZY_OPTIONS } from './types';
3
+ export { FuzzyCache } from './cache';
4
+ export { levenshteinDistance, similarityScore, damerauLevenshteinDistance, findSimilarTerms, getNgrams, ngramOverlap, PREFIX_MATCH_MIN_SIMILARITY, } from './distance';
@@ -0,0 +1,19 @@
1
+ export interface FuzzySearchOptions {
2
+ maxDistance?: number;
3
+ minSimilarity?: number;
4
+ maxResults?: number;
5
+ useTranspositions?: boolean;
6
+ caseSensitive?: boolean;
7
+ /** Use n-gram filtering for candidate selection (supports transpositions) */
8
+ useNgramFilter?: boolean;
9
+ /** Size of n-grams for filtering (default: 2) */
10
+ ngramSize?: number;
11
+ /** Minimum n-gram overlap ratio to consider a candidate (0-1, default: 0.2) */
12
+ minNgramOverlap?: number;
13
+ }
14
+ export interface FuzzyMatch {
15
+ term: string;
16
+ distance: number;
17
+ similarity: number;
18
+ }
19
+ export declare const DEFAULT_FUZZY_OPTIONS: Required<FuzzySearchOptions>;
@@ -0,0 +1,23 @@
1
+ import type { FuzzySearchOptions, FuzzyMatch } from './fuzzy';
2
+ import type { SearchQueryResponse, SearchIndex } from './types';
3
+ interface QueryOptions {
4
+ limit?: number;
5
+ cursor?: string;
6
+ fuzzyOptions?: FuzzySearchOptions;
7
+ }
8
+ export declare class FuzzySearchWrapper {
9
+ private cache;
10
+ private searchIndex;
11
+ constructor(searchIndex: SearchIndex, cacheSize?: number);
12
+ getDictionary(field?: string): Promise<string[]>;
13
+ findSimilar(query: string, field?: string, options?: FuzzySearchOptions): Promise<FuzzyMatch[]>;
14
+ expandQuery(query: string, options?: FuzzySearchOptions): Promise<{
15
+ original: string[];
16
+ expanded: string[];
17
+ matches: Record<string, FuzzyMatch[]>;
18
+ }>;
19
+ query(query: string, options?: QueryOptions): Promise<SearchQueryResponse>;
20
+ clearCache(): void;
21
+ getCacheSize(): number;
22
+ }
23
+ export {};
@@ -1,16 +1,28 @@
1
- export type { SearchClient } from './types';
1
+ export type { SearchClient, SearchResult, SearchQueryResponse, IndexableDocument, SearchOptions, } from './types';
2
+ export type { FuzzySearchOptions, FuzzyMatch } from './fuzzy';
2
3
  export { processDocumentForIndexing } from './indexer/utils';
3
- export declare const queryToSearchIndexQuery: (query: string, stopwordLanguages?: string[]) => any;
4
- export declare const optionsToSearchIndexOptions: (options?: {
4
+ import type { FuzzyMatch } from './fuzzy';
5
+ import type { SearchResult, SearchQueryResponse } from './types';
6
+ interface SearchQuery {
7
+ AND: string[];
8
+ }
9
+ interface PaginationOptions {
5
10
  limit?: number;
6
11
  cursor?: string;
7
- }) => {};
8
- export declare const parseSearchIndexResponse: (data: any, options?: {
9
- limit?: number;
10
- cursor?: string;
11
- }) => {
12
- results: any;
13
- total: any;
14
- prevCursor: any;
15
- nextCursor: string;
16
- };
12
+ }
13
+ interface PageOptions {
14
+ PAGE?: {
15
+ SIZE: number;
16
+ NUMBER: number;
17
+ };
18
+ }
19
+ interface SearchIndexResponse {
20
+ RESULT: SearchResult[];
21
+ RESULT_LENGTH: number;
22
+ FUZZY_MATCHES?: Record<string, FuzzyMatch[]>;
23
+ NEXT_CURSOR?: string | null;
24
+ PREV_CURSOR?: string | null;
25
+ }
26
+ export declare const queryToSearchIndexQuery: (query: string, stopwordLanguages?: string[]) => SearchQuery;
27
+ export declare const optionsToSearchIndexOptions: (options?: PaginationOptions) => PageOptions;
28
+ export declare const parseSearchIndexResponse: (data: SearchIndexResponse, options?: PaginationOptions) => SearchQueryResponse;
@@ -1,215 +1,210 @@
1
- (function(global, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("stopword")) : typeof define === "function" && define.amd ? define(["exports", "stopword"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["@tinacms/search"] = {}, global.NOOP));
3
- })(this, function(exports2, sw) {
4
- "use strict";
5
- function _interopNamespaceDefault(e) {
6
- const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
7
- if (e) {
8
- for (const k in e) {
9
- if (k !== "default") {
10
- const d = Object.getOwnPropertyDescriptor(e, k);
11
- Object.defineProperty(n, k, d.get ? d : {
12
- enumerable: true,
13
- get: () => e[k]
14
- });
15
- }
16
- }
17
- }
18
- n.default = e;
19
- return Object.freeze(n);
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ import * as sw from "stopword";
8
+ const INDEXABLE_NODE_TYPES = ["text", "code_block", "html"];
9
+ class StringBuilder {
10
+ constructor(limit) {
11
+ __publicField(this, "buffer", []);
12
+ __publicField(this, "limit");
13
+ __publicField(this, "length", 0);
14
+ this.limit = limit;
20
15
  }
21
- const sw__namespace = /* @__PURE__ */ _interopNamespaceDefault(sw);
22
- class StringBuilder {
23
- constructor(limit) {
24
- this.length = 0;
25
- this.buffer = [];
26
- this.limit = limit;
27
- }
28
- append(str) {
29
- if (this.length + str.length > this.limit) {
30
- return true;
31
- } else {
32
- this.buffer.push(str);
33
- this.length += str.length;
34
- if (this.length > this.limit) {
35
- return true;
36
- }
37
- return false;
38
- }
39
- }
40
- toString() {
41
- return this.buffer.join(" ");
16
+ append(str) {
17
+ if (this.length + str.length > this.limit)
18
+ return true;
19
+ this.buffer.push(str);
20
+ this.length += str.length;
21
+ return this.length > this.limit;
22
+ }
23
+ toString() {
24
+ return this.buffer.join(" ");
25
+ }
26
+ }
27
+ const tokenizeString = (str) => {
28
+ return str.split(/[\s\.,]+/).map((s) => s.toLowerCase()).filter((s) => s);
29
+ };
30
+ const extractText = (data, builder, nodeTypes) => {
31
+ var _a;
32
+ if (!data)
33
+ return;
34
+ if (nodeTypes.includes(data.type ?? "") && (data.text || data.value)) {
35
+ const tokens = tokenizeString(data.text || data.value || "");
36
+ for (const token of tokens) {
37
+ if (builder.append(token))
38
+ return;
42
39
  }
43
40
  }
44
- const extractText = (data, acc, indexableNodeTypes) => {
45
- var _a, _b;
46
- if (data) {
47
- if (indexableNodeTypes.indexOf(data.type) !== -1 && (data.text || data.value)) {
48
- const tokens = tokenizeString(data.text || data.value);
49
- for (const token of tokens) {
50
- if (acc.append(token)) {
51
- return;
52
- }
53
- }
54
- }
55
- (_b = (_a = data.children) == null ? void 0 : _a.forEach) == null ? void 0 : _b.call(
56
- _a,
57
- (child) => extractText(child, acc, indexableNodeTypes)
58
- );
41
+ (_a = data.children) == null ? void 0 : _a.forEach((child) => extractText(child, builder, nodeTypes));
42
+ };
43
+ const getRelativePath = (path, collection) => {
44
+ return path.replace(/\\/g, "/").replace(collection.path, "").replace(/^\/|\/$/g, "");
45
+ };
46
+ const processTextField = (value, maxLength) => {
47
+ const tokens = tokenizeString(value);
48
+ const builder = new StringBuilder(maxLength);
49
+ for (const part of tokens) {
50
+ if (builder.append(part))
51
+ break;
52
+ }
53
+ return builder.toString();
54
+ };
55
+ const processRichTextField = (value, maxLength) => {
56
+ const builder = new StringBuilder(maxLength);
57
+ extractText(value, builder, INDEXABLE_NODE_TYPES);
58
+ return builder.toString();
59
+ };
60
+ const processObjectField = (data, path, collection, textIndexLength, field) => {
61
+ if (field.list) {
62
+ return data.map(
63
+ (obj) => processDocumentForIndexing(obj, path, collection, textIndexLength, field)
64
+ );
65
+ }
66
+ return processDocumentForIndexing(
67
+ data,
68
+ path,
69
+ collection,
70
+ textIndexLength,
71
+ field
72
+ );
73
+ };
74
+ const processStringField = (data, maxLength, isList) => {
75
+ if (isList) {
76
+ return data.map(
77
+ (value) => processTextField(value, maxLength)
78
+ );
79
+ }
80
+ return processTextField(data, maxLength);
81
+ };
82
+ const processRichTextFieldData = (data, maxLength, isList) => {
83
+ if (isList) {
84
+ return data.map(
85
+ (value) => processRichTextField(value, maxLength)
86
+ );
87
+ }
88
+ return processRichTextField(data, maxLength);
89
+ };
90
+ const processDocumentForIndexing = (data, path, collection, textIndexLength, field) => {
91
+ if (!field) {
92
+ const relativePath = getRelativePath(path, collection);
93
+ data["_id"] = `${collection.name}:${relativePath}`;
94
+ data["_relativePath"] = relativePath;
95
+ }
96
+ const fields = (field == null ? void 0 : field.fields) || collection.fields || [];
97
+ for (const f of fields) {
98
+ if (!f.searchable) {
99
+ delete data[f.name];
100
+ continue;
59
101
  }
60
- };
61
- const relativePath = (path, collection) => {
62
- return path.replace(/\\/g, "/").replace(collection.path, "").replace(/^\/|\/$/g, "");
63
- };
64
- const tokenizeString = (str) => {
65
- return str.split(/[\s\.,]+/).map((s) => s.toLowerCase()).filter((s) => s);
66
- };
67
- const processTextFieldValue = (value, maxLen) => {
68
- const tokens = tokenizeString(value);
69
- const builder = new StringBuilder(maxLen);
70
- for (const part of tokens) {
71
- if (builder.append(part)) {
102
+ if (!data[f.name])
103
+ continue;
104
+ const fieldMaxLength = f.maxSearchIndexFieldLength || textIndexLength;
105
+ const isList = Boolean(f.list);
106
+ switch (f.type) {
107
+ case "object":
108
+ data[f.name] = processObjectField(
109
+ data[f.name],
110
+ path,
111
+ collection,
112
+ textIndexLength,
113
+ f
114
+ );
115
+ break;
116
+ case "string":
117
+ data[f.name] = processStringField(
118
+ data[f.name],
119
+ fieldMaxLength,
120
+ isList
121
+ );
122
+ break;
123
+ case "rich-text":
124
+ data[f.name] = processRichTextFieldData(
125
+ data[f.name],
126
+ fieldMaxLength,
127
+ isList
128
+ );
72
129
  break;
73
- }
74
- }
75
- return builder.toString();
76
- };
77
- const processDocumentForIndexing = (data, path, collection, textIndexLength, field) => {
78
- if (!field) {
79
- const relPath = relativePath(path, collection);
80
- data["_id"] = `${collection.name}:${relPath}`;
81
- data["_relativePath"] = relPath;
82
- }
83
- for (const f of (field == null ? void 0 : field.fields) || collection.fields || []) {
84
- if (!f.searchable) {
85
- delete data[f.name];
86
- continue;
87
- }
88
- const isList = f.list;
89
- if (data[f.name]) {
90
- if (f.type === "object") {
91
- if (isList) {
92
- data[f.name] = data[f.name].map(
93
- (obj) => processDocumentForIndexing(
94
- obj,
95
- path,
96
- collection,
97
- textIndexLength,
98
- f
99
- )
100
- );
101
- } else {
102
- data[f.name] = processDocumentForIndexing(
103
- data[f.name],
104
- path,
105
- collection,
106
- textIndexLength,
107
- f
108
- );
109
- }
110
- } else if (f.type === "string") {
111
- const fieldTextIndexLength = f.maxSearchIndexFieldLength || textIndexLength;
112
- if (isList) {
113
- data[f.name] = data[f.name].map(
114
- (value) => processTextFieldValue(value, fieldTextIndexLength)
115
- );
116
- } else {
117
- data[f.name] = processTextFieldValue(
118
- data[f.name],
119
- fieldTextIndexLength
120
- );
121
- }
122
- } else if (f.type === "rich-text") {
123
- const fieldTextIndexLength = f.maxSearchIndexFieldLength || textIndexLength;
124
- if (isList) {
125
- data[f.name] = data[f.name].map((value) => {
126
- const acc = new StringBuilder(fieldTextIndexLength);
127
- extractText(value, acc, ["text", "code_block", "html"]);
128
- return acc.toString();
129
- });
130
- } else {
131
- const acc = new StringBuilder(fieldTextIndexLength);
132
- extractText(data[f.name], acc, ["text", "code_block", "html"]);
133
- data[f.name] = acc.toString();
134
- }
135
- }
136
- }
137
- }
138
- return data;
139
- };
140
- const memo = {};
141
- const lookupStopwords = (keys, defaultStopWords = sw__namespace.eng) => {
142
- let stopwords = defaultStopWords;
143
- if (keys) {
144
- if (memo[keys.join(",")]) {
145
- return memo[keys.join(",")];
146
- }
147
- stopwords = [];
148
- for (const key of keys) {
149
- stopwords.push(...sw__namespace[key]);
150
- }
151
- memo[keys.join(",")] = stopwords;
152
- }
153
- return stopwords;
154
- };
155
- const queryToSearchIndexQuery = (query, stopwordLanguages) => {
156
- let q;
157
- const parts = query.split(" ");
158
- const stopwords = lookupStopwords(stopwordLanguages);
159
- if (parts.length === 1) {
160
- q = { AND: [parts[0]] };
161
- } else {
162
- q = {
163
- AND: parts.filter(
164
- (part) => part.toLowerCase() !== "and" && stopwords.indexOf(part.toLowerCase()) === -1
165
- )
166
- };
167
130
  }
168
- return q;
169
- };
170
- const optionsToSearchIndexOptions = (options) => {
171
- const opt = {};
172
- if (options == null ? void 0 : options.limit) {
173
- opt["PAGE"] = {
174
- SIZE: options.limit,
175
- NUMBER: (options == null ? void 0 : options.cursor) ? parseInt(options.cursor) : 0
176
- };
131
+ }
132
+ return data;
133
+ };
134
+ const stopwordCache = {};
135
+ const lookupStopwords = (keys, defaultStopWords = sw.eng) => {
136
+ if (!keys) {
137
+ return defaultStopWords;
138
+ }
139
+ const cacheKey = keys.join(",");
140
+ if (stopwordCache[cacheKey]) {
141
+ return stopwordCache[cacheKey];
142
+ }
143
+ const stopwords = keys.flatMap((key) => sw[key] || []);
144
+ stopwordCache[cacheKey] = stopwords;
145
+ return stopwords;
146
+ };
147
+ const queryToSearchIndexQuery = (query, stopwordLanguages) => {
148
+ const parts = query.split(" ");
149
+ const stopwords = lookupStopwords(stopwordLanguages);
150
+ if (parts.length === 1) {
151
+ return { AND: [parts[0]] };
152
+ }
153
+ const filteredParts = parts.filter(
154
+ (part) => part.toLowerCase() !== "and" && !stopwords.includes(part.toLowerCase())
155
+ );
156
+ return { AND: filteredParts };
157
+ };
158
+ const optionsToSearchIndexOptions = (options) => {
159
+ if (!(options == null ? void 0 : options.limit))
160
+ return {};
161
+ return {
162
+ PAGE: {
163
+ SIZE: options.limit,
164
+ NUMBER: options.cursor ? parseInt(options.cursor) : 0
177
165
  }
178
- return opt;
179
166
  };
180
- const parseSearchIndexResponse = (data, options) => {
181
- const results = data["RESULT"];
182
- const total = data["RESULT_LENGTH"];
183
- if ((options == null ? void 0 : options.cursor) && (options == null ? void 0 : options.limit)) {
184
- const prevCursor = options.cursor === "0" ? null : (parseInt(options.cursor) - 1).toString();
185
- const nextCursor = total <= (parseInt(options.cursor) + 1) * options.limit ? null : (parseInt(options.cursor) + 1).toString();
186
- return {
187
- results,
188
- total,
189
- prevCursor,
190
- nextCursor
191
- };
192
- } else if (!(options == null ? void 0 : options.cursor) && (options == null ? void 0 : options.limit)) {
193
- const prevCursor = null;
194
- const nextCursor = total <= options.limit ? null : "1";
195
- return {
196
- results,
197
- total,
198
- prevCursor,
199
- nextCursor
200
- };
201
- } else {
202
- return {
203
- results,
204
- total,
205
- prevCursor: null,
206
- nextCursor: null
207
- };
208
- }
167
+ };
168
+ const parseSearchIndexResponse = (data, options) => {
169
+ const resultArray = (data == null ? void 0 : data.RESULT) ?? (data == null ? void 0 : data.results);
170
+ if (!data || !Array.isArray(resultArray)) {
171
+ return {
172
+ results: [],
173
+ total: 0,
174
+ prevCursor: null,
175
+ nextCursor: null,
176
+ fuzzyMatches: void 0
177
+ };
178
+ }
179
+ const results = data.RESULT ?? data.results;
180
+ const total = data.RESULT_LENGTH ?? data.total ?? 0;
181
+ const fuzzyMatches = data.FUZZY_MATCHES ?? data.fuzzyMatches;
182
+ const nextCursor = data.NEXT_CURSOR ?? data.nextCursor;
183
+ const prevCursor = data.PREV_CURSOR ?? data.prevCursor;
184
+ if (nextCursor !== void 0 || prevCursor !== void 0) {
185
+ return {
186
+ results,
187
+ total,
188
+ prevCursor: prevCursor ?? null,
189
+ nextCursor: nextCursor ?? null,
190
+ fuzzyMatches
191
+ };
192
+ }
193
+ const currentPage = (options == null ? void 0 : options.cursor) ? parseInt(options.cursor) : 0;
194
+ const pageSize = options == null ? void 0 : options.limit;
195
+ const hasPreviousPage = currentPage > 0;
196
+ const hasNextPage = pageSize ? total > (currentPage + 1) * pageSize : false;
197
+ return {
198
+ results,
199
+ total,
200
+ prevCursor: hasPreviousPage ? (currentPage - 1).toString() : null,
201
+ nextCursor: hasNextPage ? (currentPage + 1).toString() : null,
202
+ fuzzyMatches
209
203
  };
210
- exports2.optionsToSearchIndexOptions = optionsToSearchIndexOptions;
211
- exports2.parseSearchIndexResponse = parseSearchIndexResponse;
212
- exports2.processDocumentForIndexing = processDocumentForIndexing;
213
- exports2.queryToSearchIndexQuery = queryToSearchIndexQuery;
214
- Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
215
- });
204
+ };
205
+ export {
206
+ optionsToSearchIndexOptions,
207
+ parseSearchIndexResponse,
208
+ processDocumentForIndexing,
209
+ queryToSearchIndexQuery
210
+ };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,10 @@
1
- import si from 'search-index';
1
+ import createSearchIndex from 'search-index';
2
2
  export { SearchIndexer } from './indexer';
3
3
  export { LocalSearchIndexClient, TinaCMSSearchIndexClient } from './client';
4
- export type { SearchClient } from './types';
5
- export { si };
4
+ export type { SearchClient, SearchOptions, SearchResult, SearchQueryResponse, IndexableDocument, SearchIndexResult, SearchIndex, } from './types';
5
+ export type { FuzzySearchOptions, FuzzyMatch } from './fuzzy';
6
+ export { levenshteinDistance, similarityScore, damerauLevenshteinDistance, findSimilarTerms, FuzzyCache, DEFAULT_FUZZY_OPTIONS, } from './fuzzy';
7
+ export { FuzzySearchWrapper } from './fuzzy-search-wrapper';
8
+ export { buildPageOptions, buildPaginationCursors } from './pagination';
9
+ export type { PaginationOptions, PageOptions, PaginationCursors, } from './pagination';
10
+ export { createSearchIndex };