@peam-ai/search 0.1.3 → 0.1.5

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/dist/index.d.mts CHANGED
@@ -1,58 +1,89 @@
1
1
  import { StructuredPage } from '@peam-ai/parser';
2
2
 
3
- interface PageToIndex {
4
- path: string;
5
- structuredPage: StructuredPage;
6
- }
7
- interface SearchIndexData {
8
- keys: string[];
9
- data: Record<string, string>;
10
- }
11
- /**
12
- * Build a search index from structured pages
13
- */
14
- declare function buildSearchIndex(pages: PageToIndex[]): Promise<SearchIndexData>;
15
-
16
3
  type StructuredPageDocumentData = {
17
4
  id: string;
18
5
  path: string;
19
- content: StructuredPage;
6
+ content: Pick<StructuredPage, 'title' | 'description' | 'author' | 'keywords' | 'content' | 'language' | 'publishedTime'>;
20
7
  [key: string]: any;
21
8
  };
9
+ type SearchIndexData = {
10
+ keys: string[];
11
+ data: Record<string, string>;
12
+ };
22
13
 
23
- interface TextSearchOptions {
14
+ interface SearchOptions {
24
15
  limit?: number;
25
16
  offset?: number;
26
17
  suggest?: boolean;
27
18
  }
28
- declare class TextSearch {
29
- private index;
30
- private initialized;
31
- private documentIds;
32
- constructor();
33
- private getIndex;
19
+ /**
20
+ * Interface for a search engine.
21
+ */
22
+ interface SearchEngine {
23
+ /**
24
+ * Initializes the search engine.
25
+ */
34
26
  initialize(): Promise<void>;
35
- addDocument(document: StructuredPageDocumentData): Promise<void>;
36
- search(query: string, options?: TextSearchOptions): Promise<StructuredPageDocumentData[]>;
27
+ /**
28
+ * Adds a page to the search index.
29
+ * @param path The path of the page.
30
+ * @param content The structured content of the page.
31
+ */
32
+ addPage(path: string, content: StructuredPage): Promise<void>;
33
+ /**
34
+ * Searches the index for relevant documents.
35
+ * @param query The search query.
36
+ * @param options Search options.
37
+ * @returns A promise that resolves to an array of structured page document data.
38
+ */
39
+ search(query: string, options?: SearchOptions): Promise<StructuredPageDocumentData[]>;
40
+ /**
41
+ * Returns the total number of documents in the search index.
42
+ * @return The number of documents.
43
+ */
37
44
  count(): number;
45
+ /**
46
+ * Retrieves a document by its path.
47
+ * @param path The path of the page.
48
+ * @returns The structured page document data or null if not found.
49
+ */
38
50
  getDocument(path: string): StructuredPageDocumentData | null;
51
+ /**
52
+ * Retrieves all documents in the search index.
53
+ * @param limit Optional limit on the number of documents to retrieve.
54
+ * @returns An array of structured page document data.
55
+ */
39
56
  getAllDocuments(limit?: number): StructuredPageDocumentData[];
57
+ /**
58
+ * Clears the search index.
59
+ */
40
60
  clear(): void;
61
+ /**
62
+ * Exports the search index data.
63
+ * @param handler A function that handles exporting each key-data pair.
64
+ * @returns A promise that resolves to an object containing all exported keys.
65
+ */
41
66
  export(handler: (key: string, data: string) => Promise<void>): Promise<{
42
67
  keys: string[];
43
68
  }>;
69
+ /**
70
+ * Imports search index data.
71
+ * @param handler A function that handles importing data for each key.
72
+ * @param keys An array of keys to import.
73
+ * @returns A promise that resolves when the import is complete.
74
+ */
44
75
  import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void>;
45
76
  }
46
77
 
47
- interface SearchEngineConfig {
78
+ interface TextBasedSearchEngineConfig {
48
79
  }
49
- declare class SearchEngine {
80
+ declare class TextBasedSearchEngine implements SearchEngine {
50
81
  private textSearch;
51
82
  private initialized;
52
- constructor(_config?: SearchEngineConfig);
83
+ constructor(_config?: TextBasedSearchEngineConfig);
53
84
  initialize(): Promise<void>;
54
85
  addPage(path: string, content: StructuredPage): Promise<void>;
55
- search(query: string, options?: TextSearchOptions): Promise<StructuredPageDocumentData[]>;
86
+ search(query: string, options?: SearchOptions): Promise<StructuredPageDocumentData[]>;
56
87
  count(): number;
57
88
  getDocument(path: string): StructuredPageDocumentData | null;
58
89
  getAllDocuments(limit?: number): StructuredPageDocumentData[];
@@ -63,7 +94,7 @@ declare class SearchEngine {
63
94
  import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void>;
64
95
  }
65
96
 
66
- type ExportOptions = {
97
+ type StoreOptions = {
67
98
  /**
68
99
  * Whether to override existing index data
69
100
  * @default false
@@ -71,9 +102,9 @@ type ExportOptions = {
71
102
  override?: boolean;
72
103
  };
73
104
  /**
74
- * Interface for exporting and importing search indexes
105
+ * Interface for storing and loading search indexes
75
106
  */
76
- interface SearchIndexExporter {
107
+ interface SearchIndexStore {
77
108
  /**
78
109
  * Import a search index from storage
79
110
  * @returns The search index data or null if not available
@@ -82,50 +113,57 @@ interface SearchIndexExporter {
82
113
  /**
83
114
  * Export a search index to storage
84
115
  * @param data The search index data to save
85
- * @param options Exporter options
116
+ * @param options Store options
86
117
  */
87
- export(data: SearchIndexData, options?: ExportOptions): Promise<void>;
118
+ export(data: SearchIndexData, options?: StoreOptions): Promise<void>;
88
119
  /**
89
120
  * Synchronous export of search index to storage
90
121
  * @param data
91
- * @param options Exporter options
122
+ * @param options Store options
92
123
  */
93
- exportSync?(data: SearchIndexData, options?: ExportOptions): void;
124
+ exportSync?(data: SearchIndexData, options?: StoreOptions): void;
94
125
  }
95
126
 
96
- interface FileBasedSearchIndexExporterOptions {
127
+ /**
128
+ * Configuration for file-based search index store
129
+ * @description Configuration for file-based search index store
130
+ */
131
+ interface FileBasedSearchIndexStoreOptions {
97
132
  /**
98
133
  * The path to the index file relative to baseDir
134
+ * @description The path to the index file relative to baseDir
135
+ * @default .peam/index.json
99
136
  */
100
- indexPath: string;
137
+ indexPath?: string;
101
138
  /**
102
139
  * The directory where the index file is located
140
+ * @description The directory where the index file is located
103
141
  */
104
142
  baseDir?: string;
105
143
  }
106
144
  /**
107
- * File-based implementation of SearchIndexExporter
145
+ * File-based implementation of SearchIndexStore
108
146
  * Reads and writes search index data to/from a JSON file
109
147
  */
110
- declare class FileBasedSearchIndexExporter implements SearchIndexExporter {
148
+ declare class FileBasedSearchIndexStore implements SearchIndexStore {
111
149
  private baseDir;
112
150
  private indexPath;
113
151
  private cachedData;
114
- constructor(options: FileBasedSearchIndexExporterOptions);
152
+ constructor(options: FileBasedSearchIndexStoreOptions);
115
153
  private getFullPath;
116
154
  private loadData;
117
155
  import(): Promise<SearchIndexData | null>;
118
- export(data: SearchIndexData, options?: ExportOptions): Promise<void>;
119
- exportSync(data: SearchIndexData, options?: ExportOptions): void;
156
+ export(data: SearchIndexData, options?: StoreOptions): Promise<void>;
157
+ exportSync(data: SearchIndexData, options?: StoreOptions): void;
120
158
  }
121
159
 
122
- type SearchExporterConfig = {
160
+ type SearchStoreConfig = {
123
161
  type: 'fileBased';
124
- config: FileBasedSearchIndexExporterOptions;
162
+ config: FileBasedSearchIndexStoreOptions;
125
163
  };
126
164
  /**
127
- * Creates a SearchIndexExporter instance from a SearchExporterConfig
165
+ * Creates a SearchIndexStore instance from a SearchStoreConfig
128
166
  */
129
- declare function createExporterFromConfig(exporterConfig: SearchExporterConfig): SearchIndexExporter;
167
+ declare function createStoreFromConfig(storeConfig: SearchStoreConfig): SearchIndexStore;
130
168
 
131
- export { FileBasedSearchIndexExporter, type FileBasedSearchIndexExporterOptions, type PageToIndex, SearchEngine, type SearchEngineConfig, type SearchExporterConfig, type SearchIndexData, type SearchIndexExporter, type StructuredPageDocumentData, TextSearch, buildSearchIndex, createExporterFromConfig };
169
+ export { FileBasedSearchIndexStore, type FileBasedSearchIndexStoreOptions, type SearchEngine, type SearchIndexData, type SearchIndexStore, type SearchOptions, type SearchStoreConfig, type StructuredPageDocumentData, TextBasedSearchEngine, type TextBasedSearchEngineConfig, createStoreFromConfig };
package/dist/index.d.ts CHANGED
@@ -1,58 +1,89 @@
1
1
  import { StructuredPage } from '@peam-ai/parser';
2
2
 
3
- interface PageToIndex {
4
- path: string;
5
- structuredPage: StructuredPage;
6
- }
7
- interface SearchIndexData {
8
- keys: string[];
9
- data: Record<string, string>;
10
- }
11
- /**
12
- * Build a search index from structured pages
13
- */
14
- declare function buildSearchIndex(pages: PageToIndex[]): Promise<SearchIndexData>;
15
-
16
3
  type StructuredPageDocumentData = {
17
4
  id: string;
18
5
  path: string;
19
- content: StructuredPage;
6
+ content: Pick<StructuredPage, 'title' | 'description' | 'author' | 'keywords' | 'content' | 'language' | 'publishedTime'>;
20
7
  [key: string]: any;
21
8
  };
9
+ type SearchIndexData = {
10
+ keys: string[];
11
+ data: Record<string, string>;
12
+ };
22
13
 
23
- interface TextSearchOptions {
14
+ interface SearchOptions {
24
15
  limit?: number;
25
16
  offset?: number;
26
17
  suggest?: boolean;
27
18
  }
28
- declare class TextSearch {
29
- private index;
30
- private initialized;
31
- private documentIds;
32
- constructor();
33
- private getIndex;
19
+ /**
20
+ * Interface for a search engine.
21
+ */
22
+ interface SearchEngine {
23
+ /**
24
+ * Initializes the search engine.
25
+ */
34
26
  initialize(): Promise<void>;
35
- addDocument(document: StructuredPageDocumentData): Promise<void>;
36
- search(query: string, options?: TextSearchOptions): Promise<StructuredPageDocumentData[]>;
27
+ /**
28
+ * Adds a page to the search index.
29
+ * @param path The path of the page.
30
+ * @param content The structured content of the page.
31
+ */
32
+ addPage(path: string, content: StructuredPage): Promise<void>;
33
+ /**
34
+ * Searches the index for relevant documents.
35
+ * @param query The search query.
36
+ * @param options Search options.
37
+ * @returns A promise that resolves to an array of structured page document data.
38
+ */
39
+ search(query: string, options?: SearchOptions): Promise<StructuredPageDocumentData[]>;
40
+ /**
41
+ * Returns the total number of documents in the search index.
42
+ * @return The number of documents.
43
+ */
37
44
  count(): number;
45
+ /**
46
+ * Retrieves a document by its path.
47
+ * @param path The path of the page.
48
+ * @returns The structured page document data or null if not found.
49
+ */
38
50
  getDocument(path: string): StructuredPageDocumentData | null;
51
+ /**
52
+ * Retrieves all documents in the search index.
53
+ * @param limit Optional limit on the number of documents to retrieve.
54
+ * @returns An array of structured page document data.
55
+ */
39
56
  getAllDocuments(limit?: number): StructuredPageDocumentData[];
57
+ /**
58
+ * Clears the search index.
59
+ */
40
60
  clear(): void;
61
+ /**
62
+ * Exports the search index data.
63
+ * @param handler A function that handles exporting each key-data pair.
64
+ * @returns A promise that resolves to an object containing all exported keys.
65
+ */
41
66
  export(handler: (key: string, data: string) => Promise<void>): Promise<{
42
67
  keys: string[];
43
68
  }>;
69
+ /**
70
+ * Imports search index data.
71
+ * @param handler A function that handles importing data for each key.
72
+ * @param keys An array of keys to import.
73
+ * @returns A promise that resolves when the import is complete.
74
+ */
44
75
  import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void>;
45
76
  }
46
77
 
47
- interface SearchEngineConfig {
78
+ interface TextBasedSearchEngineConfig {
48
79
  }
49
- declare class SearchEngine {
80
+ declare class TextBasedSearchEngine implements SearchEngine {
50
81
  private textSearch;
51
82
  private initialized;
52
- constructor(_config?: SearchEngineConfig);
83
+ constructor(_config?: TextBasedSearchEngineConfig);
53
84
  initialize(): Promise<void>;
54
85
  addPage(path: string, content: StructuredPage): Promise<void>;
55
- search(query: string, options?: TextSearchOptions): Promise<StructuredPageDocumentData[]>;
86
+ search(query: string, options?: SearchOptions): Promise<StructuredPageDocumentData[]>;
56
87
  count(): number;
57
88
  getDocument(path: string): StructuredPageDocumentData | null;
58
89
  getAllDocuments(limit?: number): StructuredPageDocumentData[];
@@ -63,7 +94,7 @@ declare class SearchEngine {
63
94
  import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void>;
64
95
  }
65
96
 
66
- type ExportOptions = {
97
+ type StoreOptions = {
67
98
  /**
68
99
  * Whether to override existing index data
69
100
  * @default false
@@ -71,9 +102,9 @@ type ExportOptions = {
71
102
  override?: boolean;
72
103
  };
73
104
  /**
74
- * Interface for exporting and importing search indexes
105
+ * Interface for storing and loading search indexes
75
106
  */
76
- interface SearchIndexExporter {
107
+ interface SearchIndexStore {
77
108
  /**
78
109
  * Import a search index from storage
79
110
  * @returns The search index data or null if not available
@@ -82,50 +113,57 @@ interface SearchIndexExporter {
82
113
  /**
83
114
  * Export a search index to storage
84
115
  * @param data The search index data to save
85
- * @param options Exporter options
116
+ * @param options Store options
86
117
  */
87
- export(data: SearchIndexData, options?: ExportOptions): Promise<void>;
118
+ export(data: SearchIndexData, options?: StoreOptions): Promise<void>;
88
119
  /**
89
120
  * Synchronous export of search index to storage
90
121
  * @param data
91
- * @param options Exporter options
122
+ * @param options Store options
92
123
  */
93
- exportSync?(data: SearchIndexData, options?: ExportOptions): void;
124
+ exportSync?(data: SearchIndexData, options?: StoreOptions): void;
94
125
  }
95
126
 
96
- interface FileBasedSearchIndexExporterOptions {
127
+ /**
128
+ * Configuration for file-based search index store
129
+ * @description Configuration for file-based search index store
130
+ */
131
+ interface FileBasedSearchIndexStoreOptions {
97
132
  /**
98
133
  * The path to the index file relative to baseDir
134
+ * @description The path to the index file relative to baseDir
135
+ * @default .peam/index.json
99
136
  */
100
- indexPath: string;
137
+ indexPath?: string;
101
138
  /**
102
139
  * The directory where the index file is located
140
+ * @description The directory where the index file is located
103
141
  */
104
142
  baseDir?: string;
105
143
  }
106
144
  /**
107
- * File-based implementation of SearchIndexExporter
145
+ * File-based implementation of SearchIndexStore
108
146
  * Reads and writes search index data to/from a JSON file
109
147
  */
110
- declare class FileBasedSearchIndexExporter implements SearchIndexExporter {
148
+ declare class FileBasedSearchIndexStore implements SearchIndexStore {
111
149
  private baseDir;
112
150
  private indexPath;
113
151
  private cachedData;
114
- constructor(options: FileBasedSearchIndexExporterOptions);
152
+ constructor(options: FileBasedSearchIndexStoreOptions);
115
153
  private getFullPath;
116
154
  private loadData;
117
155
  import(): Promise<SearchIndexData | null>;
118
- export(data: SearchIndexData, options?: ExportOptions): Promise<void>;
119
- exportSync(data: SearchIndexData, options?: ExportOptions): void;
156
+ export(data: SearchIndexData, options?: StoreOptions): Promise<void>;
157
+ exportSync(data: SearchIndexData, options?: StoreOptions): void;
120
158
  }
121
159
 
122
- type SearchExporterConfig = {
160
+ type SearchStoreConfig = {
123
161
  type: 'fileBased';
124
- config: FileBasedSearchIndexExporterOptions;
162
+ config: FileBasedSearchIndexStoreOptions;
125
163
  };
126
164
  /**
127
- * Creates a SearchIndexExporter instance from a SearchExporterConfig
165
+ * Creates a SearchIndexStore instance from a SearchStoreConfig
128
166
  */
129
- declare function createExporterFromConfig(exporterConfig: SearchExporterConfig): SearchIndexExporter;
167
+ declare function createStoreFromConfig(storeConfig: SearchStoreConfig): SearchIndexStore;
130
168
 
131
- export { FileBasedSearchIndexExporter, type FileBasedSearchIndexExporterOptions, type PageToIndex, SearchEngine, type SearchEngineConfig, type SearchExporterConfig, type SearchIndexData, type SearchIndexExporter, type StructuredPageDocumentData, TextSearch, buildSearchIndex, createExporterFromConfig };
169
+ export { FileBasedSearchIndexStore, type FileBasedSearchIndexStoreOptions, type SearchEngine, type SearchIndexData, type SearchIndexStore, type SearchOptions, type SearchStoreConfig, type StructuredPageDocumentData, TextBasedSearchEngine, type TextBasedSearchEngineConfig, createStoreFromConfig };
package/dist/index.js CHANGED
@@ -64,18 +64,16 @@ var __async = (__this, __arguments, generator) => {
64
64
  // src/index.ts
65
65
  var index_exports = {};
66
66
  __export(index_exports, {
67
- FileBasedSearchIndexExporter: () => FileBasedSearchIndexExporter,
68
- SearchEngine: () => SearchEngine,
69
- TextSearch: () => TextSearch,
70
- buildSearchIndex: () => buildSearchIndex,
71
- createExporterFromConfig: () => createExporterFromConfig
67
+ FileBasedSearchIndexStore: () => FileBasedSearchIndexStore,
68
+ TextBasedSearchEngine: () => TextBasedSearchEngine,
69
+ createStoreFromConfig: () => createStoreFromConfig
72
70
  });
73
71
  module.exports = __toCommonJS(index_exports);
74
72
 
75
- // src/searchEngine.ts
73
+ // src/searchEngine/textBasedSearchEngine.ts
76
74
  var import_logger2 = require("@peam-ai/logger");
77
75
 
78
- // src/textSearch.ts
76
+ // src/searchEngine/textSearch.ts
79
77
  var import_logger = require("@peam-ai/logger");
80
78
  var import_flexsearch = require("flexsearch");
81
79
  var PEAM_DOCUMENT_IDS_KEY = "peam.documentIds";
@@ -92,8 +90,8 @@ var TextSearch = class {
92
90
  worker: false,
93
91
  document: {
94
92
  id: "path",
95
- index: ["content:title", "content:description", "content:textContent", "content:author", "content:keywords"],
96
- store: true
93
+ index: ["content:title", "content:description", "content:content", "content:keywords", "content:author"],
94
+ store: ["id", "path", "content:title", "content:content", "content:language"]
97
95
  },
98
96
  tokenize: "forward",
99
97
  resolution: 9,
@@ -126,16 +124,22 @@ var TextSearch = class {
126
124
  });
127
125
  }
128
126
  search(_0) {
129
- return __async(this, arguments, function* (query, options = {}) {
127
+ return __async(this, arguments, function* (query, options = {
128
+ limit: MAX_DOCUMENTS_RETRIEVE,
129
+ offset: 0,
130
+ suggest: true
131
+ }) {
130
132
  if (!this.initialized) {
131
133
  throw new Error("TextSearch not initialized. Call initialize() first.");
132
134
  }
133
135
  const limit = options.limit || MAX_DOCUMENTS_RETRIEVE;
134
136
  const offset = options.offset || 0;
137
+ const suggest = options.suggest || true;
135
138
  log.debug("Searching for:", query);
136
139
  const results = yield this.index.search(query, {
137
- limit: limit + offset,
138
- suggest: options.suggest,
140
+ offset,
141
+ limit,
142
+ suggest,
139
143
  enrich: true
140
144
  });
141
145
  const pathSet = /* @__PURE__ */ new Set();
@@ -152,8 +156,7 @@ var TextSearch = class {
152
156
  }
153
157
  }
154
158
  }
155
- const pagedResults = documents.slice(offset, offset + limit);
156
- return pagedResults;
159
+ return documents;
157
160
  });
158
161
  }
159
162
  count() {
@@ -223,9 +226,9 @@ var TextSearch = class {
223
226
  }
224
227
  };
225
228
 
226
- // src/searchEngine.ts
229
+ // src/searchEngine/textBasedSearchEngine.ts
227
230
  var log2 = import_logger2.loggers.search;
228
- var SearchEngine = class {
231
+ var TextBasedSearchEngine = class {
229
232
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
230
233
  constructor(_config) {
231
234
  this.textSearch = new TextSearch();
@@ -249,7 +252,15 @@ var SearchEngine = class {
249
252
  const document = {
250
253
  id: path2,
251
254
  path: path2,
252
- content
255
+ content: {
256
+ title: content.title,
257
+ description: content.description,
258
+ content: content.markdownContent ? content.markdownContent : content.textContent,
259
+ author: content.author,
260
+ keywords: content.keywords,
261
+ language: content.language,
262
+ publishedTime: content.publishedTime
263
+ }
253
264
  };
254
265
  yield this.textSearch.addDocument(document);
255
266
  log2.debug("Page added to search engine:", path2);
@@ -290,37 +301,18 @@ var SearchEngine = class {
290
301
  }
291
302
  };
292
303
 
293
- // src/indexBuilder.ts
294
- function buildSearchIndex(pages) {
295
- return __async(this, null, function* () {
296
- const searchEngine = new SearchEngine();
297
- yield searchEngine.initialize();
298
- for (const page of pages) {
299
- yield searchEngine.addPage(page.path, page.structuredPage);
300
- }
301
- const exportedData = {};
302
- const result = yield searchEngine.export((key, data) => __async(null, null, function* () {
303
- exportedData[key] = data;
304
- }));
305
- return {
306
- keys: result.keys,
307
- data: exportedData
308
- };
309
- });
310
- }
311
-
312
- // src/exporters/FileBasedSearchIndexExporter.ts
304
+ // src/stores/FileBasedSearchIndexStore.ts
313
305
  var import_logger3 = require("@peam-ai/logger");
314
306
  var fsSync = __toESM(require("fs"));
315
307
  var fs = __toESM(require("fs/promises"));
316
308
  var path = __toESM(require("path"));
317
309
  var log3 = import_logger3.loggers.search;
318
- var FileBasedSearchIndexExporter = class {
310
+ var FileBasedSearchIndexStore = class {
319
311
  constructor(options) {
320
312
  this.cachedData = null;
321
- var _a;
313
+ var _a, _b;
322
314
  this.baseDir = (_a = options.baseDir) != null ? _a : process.cwd();
323
- this.indexPath = options.indexPath;
315
+ this.indexPath = (_b = options.indexPath) != null ? _b : ".peam/index.json";
324
316
  }
325
317
  getFullPath() {
326
318
  return path.join(this.baseDir, this.indexPath);
@@ -401,19 +393,17 @@ var FileBasedSearchIndexExporter = class {
401
393
  }
402
394
  };
403
395
 
404
- // src/exporters/config.ts
405
- function createExporterFromConfig(exporterConfig) {
406
- if (exporterConfig.type === "fileBased") {
407
- return new FileBasedSearchIndexExporter(__spreadValues({}, exporterConfig.config));
396
+ // src/stores/config.ts
397
+ function createStoreFromConfig(storeConfig) {
398
+ if (storeConfig.type === "fileBased") {
399
+ return new FileBasedSearchIndexStore(__spreadValues({}, storeConfig.config));
408
400
  }
409
- throw new Error(`Unknown exporter type: ${exporterConfig.type}`);
401
+ throw new Error(`Unknown store type: ${storeConfig.type}`);
410
402
  }
411
403
  // Annotate the CommonJS export names for ESM import in node:
412
404
  0 && (module.exports = {
413
- FileBasedSearchIndexExporter,
414
- SearchEngine,
415
- TextSearch,
416
- buildSearchIndex,
417
- createExporterFromConfig
405
+ FileBasedSearchIndexStore,
406
+ TextBasedSearchEngine,
407
+ createStoreFromConfig
418
408
  });
419
409
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/searchEngine.ts","../src/textSearch.ts","../src/indexBuilder.ts","../src/exporters/FileBasedSearchIndexExporter.ts","../src/exporters/config.ts"],"sourcesContent":["export { buildSearchIndex, type PageToIndex, type SearchIndexData } from './indexBuilder';\nexport { SearchEngine } from './searchEngine';\nexport { TextSearch } from './textSearch';\n\nexport type { StructuredPageDocumentData } from './types';\n\nexport type { SearchEngineConfig } from './searchEngine';\n\nexport {\n FileBasedSearchIndexExporter,\n createExporterFromConfig,\n type FileBasedSearchIndexExporterOptions,\n type SearchExporterConfig,\n type SearchIndexExporter,\n} from './exporters';\n","import { loggers } from '@peam-ai/logger';\nimport type { StructuredPage } from '@peam-ai/parser';\nimport { TextSearch, type TextSearchOptions } from './textSearch';\nimport type { StructuredPageDocumentData } from './types';\n\nconst log = loggers.search;\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface SearchEngineConfig {\n // Reserved for future configuration options\n}\n\nexport class SearchEngine {\n private textSearch: TextSearch;\n private initialized: boolean;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n constructor(_config?: SearchEngineConfig) {\n this.textSearch = new TextSearch();\n this.initialized = false;\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n log.debug('Initializing search engine');\n await this.textSearch.initialize();\n this.initialized = true;\n }\n\n async addPage(path: string, content: StructuredPage): Promise<void> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n const document: StructuredPageDocumentData = {\n id: path,\n path,\n content,\n };\n\n await this.textSearch.addDocument(document);\n log.debug('Page added to search engine:', path);\n }\n\n async search(query: string, options: TextSearchOptions = {}): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n log.debug('Performing text search:', query);\n return this.textSearch.search(query, options);\n }\n\n count(): number {\n return this.textSearch.count();\n }\n\n getDocument(path: string) {\n return this.textSearch.getDocument(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n return this.textSearch.getAllDocuments(limit);\n }\n\n clear(): void {\n this.textSearch.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n return this.textSearch.export(handler);\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n await this.textSearch.import(handler, keys);\n this.initialized = true;\n log.debug('Search engine initialized from imported data');\n }\n}\n","import { loggers } from '@peam-ai/logger';\nimport { Charset, Document } from 'flexsearch';\nimport type { StructuredPageDocumentData } from './types';\n\nexport interface TextSearchOptions {\n limit?: number;\n offset?: number;\n suggest?: boolean;\n}\n\nconst PEAM_DOCUMENT_IDS_KEY = 'peam.documentIds';\nconst MAX_DOCUMENTS_RETRIEVE = 25;\nconst log = loggers.search;\n\nexport class TextSearch {\n private index: Document<StructuredPageDocumentData>;\n private initialized: boolean;\n private documentIds: Set<string>;\n\n constructor() {\n this.initialized = false;\n this.index = this.getIndex();\n this.documentIds = new Set();\n }\n\n private getIndex() {\n return new Document<StructuredPageDocumentData>({\n worker: false,\n document: {\n id: 'path',\n index: ['content:title', 'content:description', 'content:textContent', 'content:author', 'content:keywords'],\n store: true,\n },\n tokenize: 'forward',\n resolution: 9,\n context: {\n resolution: 3,\n depth: 2,\n bidirectional: true,\n },\n cache: 100,\n encoder: Charset.LatinExtra,\n });\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n log.debug('Text search already initialized');\n return;\n }\n\n this.initialized = true;\n }\n\n async addDocument(document: StructuredPageDocumentData): Promise<void> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n log.debug('Adding document to text search:', document.path);\n\n this.index.add(document);\n this.documentIds.add(document.path);\n }\n\n async search(query: string, options: TextSearchOptions = {}): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n const limit = options.limit || MAX_DOCUMENTS_RETRIEVE;\n const offset = options.offset || 0;\n\n log.debug('Searching for:', query);\n\n const results = await this.index.search(query, {\n limit: limit + offset,\n suggest: options.suggest,\n enrich: true,\n });\n\n const pathSet = new Set<string>();\n const documents: StructuredPageDocumentData[] = [];\n\n for (const fieldResults of results) {\n if (Array.isArray(fieldResults.result)) {\n for (const result of fieldResults.result) {\n const id = typeof result === 'object' && 'id' in result ? result.id : result;\n const doc = typeof result === 'object' && 'doc' in result ? result.doc : null;\n\n if (!pathSet.has(id as string) && doc) {\n pathSet.add(id as string);\n documents.push(doc);\n }\n }\n }\n }\n\n const pagedResults = documents.slice(offset, offset + limit);\n\n return pagedResults;\n }\n\n count(): number {\n return this.documentIds.size;\n }\n\n getDocument(path: string) {\n return this.index.get(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n const documents: StructuredPageDocumentData[] = [];\n let count = 0;\n limit = limit || MAX_DOCUMENTS_RETRIEVE;\n\n for (const id of this.documentIds) {\n if (count >= limit) {\n break;\n }\n\n const doc = this.index.get(id);\n if (doc) {\n documents.push(doc);\n count++;\n }\n }\n\n log.debug('Retrieved documents from store (limit):', documents.length, limit);\n return documents;\n }\n\n clear(): void {\n this.index.clear();\n this.index = this.getIndex();\n this.documentIds.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n const keys: string[] = [];\n\n await handler(PEAM_DOCUMENT_IDS_KEY, JSON.stringify(Array.from(this.documentIds)));\n keys.push(PEAM_DOCUMENT_IDS_KEY);\n\n await this.index.export(async (key: string, data: string) => {\n keys.push(key);\n await handler(key, data);\n });\n\n log.debug('Exported keys:', keys.length);\n\n return { keys };\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n const documentIdsData = await handler(PEAM_DOCUMENT_IDS_KEY);\n if (documentIdsData) {\n const parsed = typeof documentIdsData === 'string' ? JSON.parse(documentIdsData) : documentIdsData;\n this.documentIds = new Set(parsed);\n }\n\n for (const key of keys) {\n if (key === PEAM_DOCUMENT_IDS_KEY) {\n continue;\n }\n\n try {\n const data = await handler(key);\n if (data) {\n this.index.import(key, data);\n }\n } catch (error) {\n log.error('Error importing key:', key, error);\n }\n }\n\n this.initialized = true;\n log.debug('Import completed with keys:', keys.length);\n }\n}\n","import type { StructuredPage } from '@peam-ai/parser';\nimport { SearchEngine } from './searchEngine';\n\nexport interface PageToIndex {\n path: string;\n structuredPage: StructuredPage;\n}\n\nexport interface SearchIndexData {\n keys: string[];\n data: Record<string, string>;\n}\n\n/**\n * Build a search index from structured pages\n */\nexport async function buildSearchIndex(pages: PageToIndex[]): Promise<SearchIndexData> {\n const searchEngine = new SearchEngine();\n await searchEngine.initialize();\n\n for (const page of pages) {\n await searchEngine.addPage(page.path, page.structuredPage);\n }\n\n const exportedData: Record<string, string> = {};\n const result = await searchEngine.export(async (key, data) => {\n exportedData[key] = data;\n });\n\n return {\n keys: result.keys,\n data: exportedData,\n };\n}\n","import { loggers } from '@peam-ai/logger';\nimport * as fsSync from 'fs';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport type { SearchIndexData } from '../indexBuilder';\nimport type { ExportOptions, SearchIndexExporter } from './SearchIndexExporter';\n\nconst log = loggers.search;\n\nexport interface FileBasedSearchIndexExporterOptions {\n /**\n * The path to the index file relative to baseDir\n */\n indexPath: string;\n\n /**\n * The directory where the index file is located\n */\n baseDir?: string;\n}\n\n/**\n * File-based implementation of SearchIndexExporter\n * Reads and writes search index data to/from a JSON file\n */\nexport class FileBasedSearchIndexExporter implements SearchIndexExporter {\n private baseDir: string;\n private indexPath: string;\n private cachedData: SearchIndexData | null = null;\n\n constructor(options: FileBasedSearchIndexExporterOptions) {\n this.baseDir = options.baseDir ?? process.cwd();\n this.indexPath = options.indexPath;\n }\n\n private getFullPath(): string {\n return path.join(this.baseDir, this.indexPath);\n }\n\n private async loadData(): Promise<SearchIndexData | null> {\n if (this.cachedData) {\n return this.cachedData;\n }\n\n const fullPath = this.getFullPath();\n\n try {\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n const data = JSON.parse(fileContent) as SearchIndexData;\n\n if (!data || !data.keys || !Array.isArray(data.keys) || !data.data) {\n log.warn('Invalid search index structure in file:', fullPath);\n return null;\n }\n\n if (data.keys.length === 0) {\n log.debug('Search index is empty:', fullPath);\n return null;\n }\n\n this.cachedData = data;\n log.debug('Search index loaded from file:', fullPath, 'with', data.keys.length, 'keys');\n return data;\n } catch (error) {\n log.error('Failed to load search index from file:', fullPath, error);\n return null;\n }\n }\n\n async import(): Promise<SearchIndexData | null> {\n const data = await this.loadData();\n return data;\n }\n\n async export(data: SearchIndexData, options: ExportOptions = { override: true }): Promise<void> {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n await fs.access(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n\n exportSync(data: SearchIndexData, options: ExportOptions = { override: true }): void {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n fsSync.accessSync(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n fsSync.mkdirSync(dir, { recursive: true });\n\n fsSync.writeFileSync(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n}\n","import { FileBasedSearchIndexExporter, FileBasedSearchIndexExporterOptions } from './FileBasedSearchIndexExporter';\nimport { SearchIndexExporter } from './SearchIndexExporter';\n\nexport type SearchExporterConfig = {\n type: 'fileBased';\n config: FileBasedSearchIndexExporterOptions;\n};\n\n/**\n * Creates a SearchIndexExporter instance from a SearchExporterConfig\n */\nexport function createExporterFromConfig(exporterConfig: SearchExporterConfig): SearchIndexExporter {\n if (exporterConfig.type === 'fileBased') {\n return new FileBasedSearchIndexExporter({\n ...exporterConfig.config,\n });\n }\n\n throw new Error(`Unknown exporter type: ${exporterConfig.type}`);\n}\n"],"mappings":"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","names":["import_logger","path","log","path","import_logger","log"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/searchEngine/textBasedSearchEngine.ts","../src/searchEngine/textSearch.ts","../src/stores/FileBasedSearchIndexStore.ts","../src/stores/config.ts"],"sourcesContent":["export type { SearchEngine, SearchOptions } from './searchEngine/searchEngine';\nexport { TextBasedSearchEngine, type TextBasedSearchEngineConfig } from './searchEngine/textBasedSearchEngine';\nexport type { SearchIndexData, StructuredPageDocumentData } from './types';\n\nexport {\n FileBasedSearchIndexStore,\n createStoreFromConfig,\n type FileBasedSearchIndexStoreOptions,\n type SearchIndexStore,\n type SearchStoreConfig,\n} from './stores';\n","import { loggers } from '@peam-ai/logger';\nimport type { StructuredPage } from '@peam-ai/parser';\nimport type { StructuredPageDocumentData } from '../types';\nimport { SearchEngine, SearchOptions } from './searchEngine';\nimport { TextSearch } from './textSearch';\n\nconst log = loggers.search;\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TextBasedSearchEngineConfig {\n // Reserved for future configuration options\n}\n\nexport class TextBasedSearchEngine implements SearchEngine {\n private textSearch: TextSearch;\n private initialized: boolean;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n constructor(_config?: TextBasedSearchEngineConfig) {\n this.textSearch = new TextSearch();\n this.initialized = false;\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n log.debug('Initializing search engine');\n await this.textSearch.initialize();\n this.initialized = true;\n }\n\n async addPage(path: string, content: StructuredPage): Promise<void> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n const document: StructuredPageDocumentData = {\n id: path,\n path,\n content: {\n title: content.title,\n description: content.description,\n content: content.markdownContent ? content.markdownContent : content.textContent,\n author: content.author,\n keywords: content.keywords,\n language: content.language,\n publishedTime: content.publishedTime,\n },\n };\n\n await this.textSearch.addDocument(document);\n log.debug('Page added to search engine:', path);\n }\n\n async search(query: string, options: SearchOptions = {}): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n log.debug('Performing text search:', query);\n return this.textSearch.search(query, options);\n }\n\n count(): number {\n return this.textSearch.count();\n }\n\n getDocument(path: string) {\n return this.textSearch.getDocument(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n return this.textSearch.getAllDocuments(limit);\n }\n\n clear(): void {\n this.textSearch.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n return this.textSearch.export(handler);\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n await this.textSearch.import(handler, keys);\n this.initialized = true;\n log.debug('Search engine initialized from imported data');\n }\n}\n","import { loggers } from '@peam-ai/logger';\nimport { Charset, Document } from 'flexsearch';\nimport type { StructuredPageDocumentData } from '../types';\nimport { SearchOptions } from './searchEngine';\n\nconst PEAM_DOCUMENT_IDS_KEY = 'peam.documentIds';\nconst MAX_DOCUMENTS_RETRIEVE = 25;\nconst log = loggers.search;\n\nexport class TextSearch {\n private index: Document<StructuredPageDocumentData>;\n private initialized: boolean;\n private documentIds: Set<string>;\n\n constructor() {\n this.initialized = false;\n this.index = this.getIndex();\n this.documentIds = new Set();\n }\n\n private getIndex() {\n return new Document<StructuredPageDocumentData>({\n worker: false,\n document: {\n id: 'path',\n index: ['content:title', 'content:description', 'content:content', 'content:keywords', 'content:author'],\n store: ['id', 'path', 'content:title', 'content:content', 'content:language'],\n },\n tokenize: 'forward',\n resolution: 9,\n context: {\n resolution: 3,\n depth: 2,\n bidirectional: true,\n },\n cache: 100,\n encoder: Charset.LatinExtra,\n });\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n log.debug('Text search already initialized');\n return;\n }\n\n this.initialized = true;\n }\n\n async addDocument(document: StructuredPageDocumentData): Promise<void> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n log.debug('Adding document to text search:', document.path);\n\n this.index.add(document);\n this.documentIds.add(document.path);\n }\n\n async search(\n query: string,\n options: SearchOptions = {\n limit: MAX_DOCUMENTS_RETRIEVE,\n offset: 0,\n suggest: true,\n }\n ): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n const limit = options.limit || MAX_DOCUMENTS_RETRIEVE;\n const offset = options.offset || 0;\n const suggest = options.suggest || true;\n\n log.debug('Searching for:', query);\n\n const results = await this.index.search(query, {\n offset,\n limit,\n suggest,\n enrich: true,\n });\n\n const pathSet = new Set<string>();\n const documents: StructuredPageDocumentData[] = [];\n\n for (const fieldResults of results) {\n if (Array.isArray(fieldResults.result)) {\n for (const result of fieldResults.result) {\n const id = typeof result === 'object' && 'id' in result ? result.id : result;\n const doc = typeof result === 'object' && 'doc' in result ? result.doc : null;\n\n if (!pathSet.has(id as string) && doc) {\n pathSet.add(id as string);\n documents.push(doc);\n }\n }\n }\n }\n\n return documents;\n }\n\n count(): number {\n return this.documentIds.size;\n }\n\n getDocument(path: string) {\n return this.index.get(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n const documents: StructuredPageDocumentData[] = [];\n let count = 0;\n limit = limit || MAX_DOCUMENTS_RETRIEVE;\n\n for (const id of this.documentIds) {\n if (count >= limit) {\n break;\n }\n\n const doc = this.index.get(id);\n if (doc) {\n documents.push(doc);\n count++;\n }\n }\n\n log.debug('Retrieved documents from store (limit):', documents.length, limit);\n return documents;\n }\n\n clear(): void {\n this.index.clear();\n this.index = this.getIndex();\n this.documentIds.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n const keys: string[] = [];\n\n await handler(PEAM_DOCUMENT_IDS_KEY, JSON.stringify(Array.from(this.documentIds)));\n keys.push(PEAM_DOCUMENT_IDS_KEY);\n\n await this.index.export(async (key: string, data: string) => {\n keys.push(key);\n await handler(key, data);\n });\n\n log.debug('Exported keys:', keys.length);\n\n return { keys };\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n const documentIdsData = await handler(PEAM_DOCUMENT_IDS_KEY);\n if (documentIdsData) {\n const parsed = typeof documentIdsData === 'string' ? JSON.parse(documentIdsData) : documentIdsData;\n this.documentIds = new Set(parsed);\n }\n\n for (const key of keys) {\n if (key === PEAM_DOCUMENT_IDS_KEY) {\n continue;\n }\n\n try {\n const data = await handler(key);\n if (data) {\n this.index.import(key, data);\n }\n } catch (error) {\n log.error('Error importing key:', key, error);\n }\n }\n\n this.initialized = true;\n log.debug('Import completed with keys:', keys.length);\n }\n}\n","import { loggers } from '@peam-ai/logger';\nimport * as fsSync from 'fs';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { SearchIndexData } from '../types';\nimport type { SearchIndexStore, StoreOptions } from './SearchIndexStore';\n\nconst log = loggers.search;\n\n/**\n * Configuration for file-based search index store\n * @description Configuration for file-based search index store\n */\nexport interface FileBasedSearchIndexStoreOptions {\n /**\n * The path to the index file relative to baseDir\n * @description The path to the index file relative to baseDir\n * @default .peam/index.json\n */\n indexPath?: string;\n\n /**\n * The directory where the index file is located\n * @description The directory where the index file is located\n */\n baseDir?: string;\n}\n\n/**\n * File-based implementation of SearchIndexStore\n * Reads and writes search index data to/from a JSON file\n */\nexport class FileBasedSearchIndexStore implements SearchIndexStore {\n private baseDir: string;\n private indexPath: string;\n private cachedData: SearchIndexData | null = null;\n\n constructor(options: FileBasedSearchIndexStoreOptions) {\n this.baseDir = options.baseDir ?? process.cwd();\n this.indexPath = options.indexPath ?? '.peam/index.json';\n }\n\n private getFullPath(): string {\n return path.join(this.baseDir, this.indexPath);\n }\n\n private async loadData(): Promise<SearchIndexData | null> {\n if (this.cachedData) {\n return this.cachedData;\n }\n\n const fullPath = this.getFullPath();\n\n try {\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n const data = JSON.parse(fileContent) as SearchIndexData;\n\n if (!data || !data.keys || !Array.isArray(data.keys) || !data.data) {\n log.warn('Invalid search index structure in file:', fullPath);\n return null;\n }\n\n if (data.keys.length === 0) {\n log.debug('Search index is empty:', fullPath);\n return null;\n }\n\n this.cachedData = data;\n log.debug('Search index loaded from file:', fullPath, 'with', data.keys.length, 'keys');\n return data;\n } catch (error) {\n log.error('Failed to load search index from file:', fullPath, error);\n return null;\n }\n }\n\n async import(): Promise<SearchIndexData | null> {\n const data = await this.loadData();\n return data;\n }\n\n async export(data: SearchIndexData, options: StoreOptions = { override: true }): Promise<void> {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n await fs.access(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n\n exportSync(data: SearchIndexData, options: StoreOptions = { override: true }): void {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n fsSync.accessSync(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n fsSync.mkdirSync(dir, { recursive: true });\n\n fsSync.writeFileSync(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n}\n","import { FileBasedSearchIndexStore, FileBasedSearchIndexStoreOptions } from './FileBasedSearchIndexStore';\nimport { SearchIndexStore } from './SearchIndexStore';\n\nexport type SearchStoreConfig = {\n type: 'fileBased';\n config: FileBasedSearchIndexStoreOptions;\n};\n\n/**\n * Creates a SearchIndexStore instance from a SearchStoreConfig\n */\nexport function createStoreFromConfig(storeConfig: SearchStoreConfig): SearchIndexStore {\n if (storeConfig.type === 'fileBased') {\n return new FileBasedSearchIndexStore({\n ...storeConfig.config,\n });\n }\n\n throw new Error(`Unknown store type: ${storeConfig.type}`);\n}\n"],"mappings":"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","names":["import_logger","path","log","path","import_logger","log"]}
package/dist/index.mjs CHANGED
@@ -35,10 +35,10 @@ var __async = (__this, __arguments, generator) => {
35
35
  });
36
36
  };
37
37
 
38
- // src/searchEngine.ts
38
+ // src/searchEngine/textBasedSearchEngine.ts
39
39
  import { loggers as loggers2 } from "@peam-ai/logger";
40
40
 
41
- // src/textSearch.ts
41
+ // src/searchEngine/textSearch.ts
42
42
  import { loggers } from "@peam-ai/logger";
43
43
  import { Charset, Document } from "flexsearch";
44
44
  var PEAM_DOCUMENT_IDS_KEY = "peam.documentIds";
@@ -55,8 +55,8 @@ var TextSearch = class {
55
55
  worker: false,
56
56
  document: {
57
57
  id: "path",
58
- index: ["content:title", "content:description", "content:textContent", "content:author", "content:keywords"],
59
- store: true
58
+ index: ["content:title", "content:description", "content:content", "content:keywords", "content:author"],
59
+ store: ["id", "path", "content:title", "content:content", "content:language"]
60
60
  },
61
61
  tokenize: "forward",
62
62
  resolution: 9,
@@ -89,16 +89,22 @@ var TextSearch = class {
89
89
  });
90
90
  }
91
91
  search(_0) {
92
- return __async(this, arguments, function* (query, options = {}) {
92
+ return __async(this, arguments, function* (query, options = {
93
+ limit: MAX_DOCUMENTS_RETRIEVE,
94
+ offset: 0,
95
+ suggest: true
96
+ }) {
93
97
  if (!this.initialized) {
94
98
  throw new Error("TextSearch not initialized. Call initialize() first.");
95
99
  }
96
100
  const limit = options.limit || MAX_DOCUMENTS_RETRIEVE;
97
101
  const offset = options.offset || 0;
102
+ const suggest = options.suggest || true;
98
103
  log.debug("Searching for:", query);
99
104
  const results = yield this.index.search(query, {
100
- limit: limit + offset,
101
- suggest: options.suggest,
105
+ offset,
106
+ limit,
107
+ suggest,
102
108
  enrich: true
103
109
  });
104
110
  const pathSet = /* @__PURE__ */ new Set();
@@ -115,8 +121,7 @@ var TextSearch = class {
115
121
  }
116
122
  }
117
123
  }
118
- const pagedResults = documents.slice(offset, offset + limit);
119
- return pagedResults;
124
+ return documents;
120
125
  });
121
126
  }
122
127
  count() {
@@ -186,9 +191,9 @@ var TextSearch = class {
186
191
  }
187
192
  };
188
193
 
189
- // src/searchEngine.ts
194
+ // src/searchEngine/textBasedSearchEngine.ts
190
195
  var log2 = loggers2.search;
191
- var SearchEngine = class {
196
+ var TextBasedSearchEngine = class {
192
197
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
193
198
  constructor(_config) {
194
199
  this.textSearch = new TextSearch();
@@ -212,7 +217,15 @@ var SearchEngine = class {
212
217
  const document = {
213
218
  id: path2,
214
219
  path: path2,
215
- content
220
+ content: {
221
+ title: content.title,
222
+ description: content.description,
223
+ content: content.markdownContent ? content.markdownContent : content.textContent,
224
+ author: content.author,
225
+ keywords: content.keywords,
226
+ language: content.language,
227
+ publishedTime: content.publishedTime
228
+ }
216
229
  };
217
230
  yield this.textSearch.addDocument(document);
218
231
  log2.debug("Page added to search engine:", path2);
@@ -253,37 +266,18 @@ var SearchEngine = class {
253
266
  }
254
267
  };
255
268
 
256
- // src/indexBuilder.ts
257
- function buildSearchIndex(pages) {
258
- return __async(this, null, function* () {
259
- const searchEngine = new SearchEngine();
260
- yield searchEngine.initialize();
261
- for (const page of pages) {
262
- yield searchEngine.addPage(page.path, page.structuredPage);
263
- }
264
- const exportedData = {};
265
- const result = yield searchEngine.export((key, data) => __async(null, null, function* () {
266
- exportedData[key] = data;
267
- }));
268
- return {
269
- keys: result.keys,
270
- data: exportedData
271
- };
272
- });
273
- }
274
-
275
- // src/exporters/FileBasedSearchIndexExporter.ts
269
+ // src/stores/FileBasedSearchIndexStore.ts
276
270
  import { loggers as loggers3 } from "@peam-ai/logger";
277
271
  import * as fsSync from "fs";
278
272
  import * as fs from "fs/promises";
279
273
  import * as path from "path";
280
274
  var log3 = loggers3.search;
281
- var FileBasedSearchIndexExporter = class {
275
+ var FileBasedSearchIndexStore = class {
282
276
  constructor(options) {
283
277
  this.cachedData = null;
284
- var _a;
278
+ var _a, _b;
285
279
  this.baseDir = (_a = options.baseDir) != null ? _a : process.cwd();
286
- this.indexPath = options.indexPath;
280
+ this.indexPath = (_b = options.indexPath) != null ? _b : ".peam/index.json";
287
281
  }
288
282
  getFullPath() {
289
283
  return path.join(this.baseDir, this.indexPath);
@@ -364,18 +358,16 @@ var FileBasedSearchIndexExporter = class {
364
358
  }
365
359
  };
366
360
 
367
- // src/exporters/config.ts
368
- function createExporterFromConfig(exporterConfig) {
369
- if (exporterConfig.type === "fileBased") {
370
- return new FileBasedSearchIndexExporter(__spreadValues({}, exporterConfig.config));
361
+ // src/stores/config.ts
362
+ function createStoreFromConfig(storeConfig) {
363
+ if (storeConfig.type === "fileBased") {
364
+ return new FileBasedSearchIndexStore(__spreadValues({}, storeConfig.config));
371
365
  }
372
- throw new Error(`Unknown exporter type: ${exporterConfig.type}`);
366
+ throw new Error(`Unknown store type: ${storeConfig.type}`);
373
367
  }
374
368
  export {
375
- FileBasedSearchIndexExporter,
376
- SearchEngine,
377
- TextSearch,
378
- buildSearchIndex,
379
- createExporterFromConfig
369
+ FileBasedSearchIndexStore,
370
+ TextBasedSearchEngine,
371
+ createStoreFromConfig
380
372
  };
381
373
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/searchEngine.ts","../src/textSearch.ts","../src/indexBuilder.ts","../src/exporters/FileBasedSearchIndexExporter.ts","../src/exporters/config.ts"],"sourcesContent":["import { loggers } from '@peam-ai/logger';\nimport type { StructuredPage } from '@peam-ai/parser';\nimport { TextSearch, type TextSearchOptions } from './textSearch';\nimport type { StructuredPageDocumentData } from './types';\n\nconst log = loggers.search;\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface SearchEngineConfig {\n // Reserved for future configuration options\n}\n\nexport class SearchEngine {\n private textSearch: TextSearch;\n private initialized: boolean;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n constructor(_config?: SearchEngineConfig) {\n this.textSearch = new TextSearch();\n this.initialized = false;\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n log.debug('Initializing search engine');\n await this.textSearch.initialize();\n this.initialized = true;\n }\n\n async addPage(path: string, content: StructuredPage): Promise<void> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n const document: StructuredPageDocumentData = {\n id: path,\n path,\n content,\n };\n\n await this.textSearch.addDocument(document);\n log.debug('Page added to search engine:', path);\n }\n\n async search(query: string, options: TextSearchOptions = {}): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n log.debug('Performing text search:', query);\n return this.textSearch.search(query, options);\n }\n\n count(): number {\n return this.textSearch.count();\n }\n\n getDocument(path: string) {\n return this.textSearch.getDocument(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n return this.textSearch.getAllDocuments(limit);\n }\n\n clear(): void {\n this.textSearch.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n return this.textSearch.export(handler);\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n await this.textSearch.import(handler, keys);\n this.initialized = true;\n log.debug('Search engine initialized from imported data');\n }\n}\n","import { loggers } from '@peam-ai/logger';\nimport { Charset, Document } from 'flexsearch';\nimport type { StructuredPageDocumentData } from './types';\n\nexport interface TextSearchOptions {\n limit?: number;\n offset?: number;\n suggest?: boolean;\n}\n\nconst PEAM_DOCUMENT_IDS_KEY = 'peam.documentIds';\nconst MAX_DOCUMENTS_RETRIEVE = 25;\nconst log = loggers.search;\n\nexport class TextSearch {\n private index: Document<StructuredPageDocumentData>;\n private initialized: boolean;\n private documentIds: Set<string>;\n\n constructor() {\n this.initialized = false;\n this.index = this.getIndex();\n this.documentIds = new Set();\n }\n\n private getIndex() {\n return new Document<StructuredPageDocumentData>({\n worker: false,\n document: {\n id: 'path',\n index: ['content:title', 'content:description', 'content:textContent', 'content:author', 'content:keywords'],\n store: true,\n },\n tokenize: 'forward',\n resolution: 9,\n context: {\n resolution: 3,\n depth: 2,\n bidirectional: true,\n },\n cache: 100,\n encoder: Charset.LatinExtra,\n });\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n log.debug('Text search already initialized');\n return;\n }\n\n this.initialized = true;\n }\n\n async addDocument(document: StructuredPageDocumentData): Promise<void> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n log.debug('Adding document to text search:', document.path);\n\n this.index.add(document);\n this.documentIds.add(document.path);\n }\n\n async search(query: string, options: TextSearchOptions = {}): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n const limit = options.limit || MAX_DOCUMENTS_RETRIEVE;\n const offset = options.offset || 0;\n\n log.debug('Searching for:', query);\n\n const results = await this.index.search(query, {\n limit: limit + offset,\n suggest: options.suggest,\n enrich: true,\n });\n\n const pathSet = new Set<string>();\n const documents: StructuredPageDocumentData[] = [];\n\n for (const fieldResults of results) {\n if (Array.isArray(fieldResults.result)) {\n for (const result of fieldResults.result) {\n const id = typeof result === 'object' && 'id' in result ? result.id : result;\n const doc = typeof result === 'object' && 'doc' in result ? result.doc : null;\n\n if (!pathSet.has(id as string) && doc) {\n pathSet.add(id as string);\n documents.push(doc);\n }\n }\n }\n }\n\n const pagedResults = documents.slice(offset, offset + limit);\n\n return pagedResults;\n }\n\n count(): number {\n return this.documentIds.size;\n }\n\n getDocument(path: string) {\n return this.index.get(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n const documents: StructuredPageDocumentData[] = [];\n let count = 0;\n limit = limit || MAX_DOCUMENTS_RETRIEVE;\n\n for (const id of this.documentIds) {\n if (count >= limit) {\n break;\n }\n\n const doc = this.index.get(id);\n if (doc) {\n documents.push(doc);\n count++;\n }\n }\n\n log.debug('Retrieved documents from store (limit):', documents.length, limit);\n return documents;\n }\n\n clear(): void {\n this.index.clear();\n this.index = this.getIndex();\n this.documentIds.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n const keys: string[] = [];\n\n await handler(PEAM_DOCUMENT_IDS_KEY, JSON.stringify(Array.from(this.documentIds)));\n keys.push(PEAM_DOCUMENT_IDS_KEY);\n\n await this.index.export(async (key: string, data: string) => {\n keys.push(key);\n await handler(key, data);\n });\n\n log.debug('Exported keys:', keys.length);\n\n return { keys };\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n const documentIdsData = await handler(PEAM_DOCUMENT_IDS_KEY);\n if (documentIdsData) {\n const parsed = typeof documentIdsData === 'string' ? JSON.parse(documentIdsData) : documentIdsData;\n this.documentIds = new Set(parsed);\n }\n\n for (const key of keys) {\n if (key === PEAM_DOCUMENT_IDS_KEY) {\n continue;\n }\n\n try {\n const data = await handler(key);\n if (data) {\n this.index.import(key, data);\n }\n } catch (error) {\n log.error('Error importing key:', key, error);\n }\n }\n\n this.initialized = true;\n log.debug('Import completed with keys:', keys.length);\n }\n}\n","import type { StructuredPage } from '@peam-ai/parser';\nimport { SearchEngine } from './searchEngine';\n\nexport interface PageToIndex {\n path: string;\n structuredPage: StructuredPage;\n}\n\nexport interface SearchIndexData {\n keys: string[];\n data: Record<string, string>;\n}\n\n/**\n * Build a search index from structured pages\n */\nexport async function buildSearchIndex(pages: PageToIndex[]): Promise<SearchIndexData> {\n const searchEngine = new SearchEngine();\n await searchEngine.initialize();\n\n for (const page of pages) {\n await searchEngine.addPage(page.path, page.structuredPage);\n }\n\n const exportedData: Record<string, string> = {};\n const result = await searchEngine.export(async (key, data) => {\n exportedData[key] = data;\n });\n\n return {\n keys: result.keys,\n data: exportedData,\n };\n}\n","import { loggers } from '@peam-ai/logger';\nimport * as fsSync from 'fs';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport type { SearchIndexData } from '../indexBuilder';\nimport type { ExportOptions, SearchIndexExporter } from './SearchIndexExporter';\n\nconst log = loggers.search;\n\nexport interface FileBasedSearchIndexExporterOptions {\n /**\n * The path to the index file relative to baseDir\n */\n indexPath: string;\n\n /**\n * The directory where the index file is located\n */\n baseDir?: string;\n}\n\n/**\n * File-based implementation of SearchIndexExporter\n * Reads and writes search index data to/from a JSON file\n */\nexport class FileBasedSearchIndexExporter implements SearchIndexExporter {\n private baseDir: string;\n private indexPath: string;\n private cachedData: SearchIndexData | null = null;\n\n constructor(options: FileBasedSearchIndexExporterOptions) {\n this.baseDir = options.baseDir ?? process.cwd();\n this.indexPath = options.indexPath;\n }\n\n private getFullPath(): string {\n return path.join(this.baseDir, this.indexPath);\n }\n\n private async loadData(): Promise<SearchIndexData | null> {\n if (this.cachedData) {\n return this.cachedData;\n }\n\n const fullPath = this.getFullPath();\n\n try {\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n const data = JSON.parse(fileContent) as SearchIndexData;\n\n if (!data || !data.keys || !Array.isArray(data.keys) || !data.data) {\n log.warn('Invalid search index structure in file:', fullPath);\n return null;\n }\n\n if (data.keys.length === 0) {\n log.debug('Search index is empty:', fullPath);\n return null;\n }\n\n this.cachedData = data;\n log.debug('Search index loaded from file:', fullPath, 'with', data.keys.length, 'keys');\n return data;\n } catch (error) {\n log.error('Failed to load search index from file:', fullPath, error);\n return null;\n }\n }\n\n async import(): Promise<SearchIndexData | null> {\n const data = await this.loadData();\n return data;\n }\n\n async export(data: SearchIndexData, options: ExportOptions = { override: true }): Promise<void> {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n await fs.access(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n\n exportSync(data: SearchIndexData, options: ExportOptions = { override: true }): void {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n fsSync.accessSync(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n fsSync.mkdirSync(dir, { recursive: true });\n\n fsSync.writeFileSync(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n}\n","import { FileBasedSearchIndexExporter, FileBasedSearchIndexExporterOptions } from './FileBasedSearchIndexExporter';\nimport { SearchIndexExporter } from './SearchIndexExporter';\n\nexport type SearchExporterConfig = {\n type: 'fileBased';\n config: FileBasedSearchIndexExporterOptions;\n};\n\n/**\n * Creates a SearchIndexExporter instance from a SearchExporterConfig\n */\nexport function createExporterFromConfig(exporterConfig: SearchExporterConfig): SearchIndexExporter {\n if (exporterConfig.type === 'fileBased') {\n return new FileBasedSearchIndexExporter({\n ...exporterConfig.config,\n });\n }\n\n throw new Error(`Unknown exporter type: ${exporterConfig.type}`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,WAAAA,gBAAe;;;ACAxB,SAAS,eAAe;AACxB,SAAS,SAAS,gBAAgB;AASlC,IAAM,wBAAwB;AAC9B,IAAM,yBAAyB;AAC/B,IAAM,MAAM,QAAQ;AAEb,IAAM,aAAN,MAAiB;AAAA,EAKtB,cAAc;AACZ,SAAK,cAAc;AACnB,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,cAAc,oBAAI,IAAI;AAAA,EAC7B;AAAA,EAEQ,WAAW;AACjB,WAAO,IAAI,SAAqC;AAAA,MAC9C,QAAQ;AAAA,MACR,UAAU;AAAA,QACR,IAAI;AAAA,QACJ,OAAO,CAAC,iBAAiB,uBAAuB,uBAAuB,kBAAkB,kBAAkB;AAAA,QAC3G,OAAO;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,SAAS;AAAA,QACP,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,eAAe;AAAA,MACjB;AAAA,MACA,OAAO;AAAA,MACP,SAAS,QAAQ;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEM,aAA4B;AAAA;AAChC,UAAI,KAAK,aAAa;AACpB,YAAI,MAAM,iCAAiC;AAC3C;AAAA,MACF;AAEA,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA,EAEM,YAAY,UAAqD;AAAA;AACrE,UAAI,CAAC,KAAK,aAAa;AACrB,cAAM,IAAI,MAAM,sDAAsD;AAAA,MACxE;AAEA,UAAI,MAAM,mCAAmC,SAAS,IAAI;AAE1D,WAAK,MAAM,IAAI,QAAQ;AACvB,WAAK,YAAY,IAAI,SAAS,IAAI;AAAA,IACpC;AAAA;AAAA,EAEM,OAAO,IAAuF;AAAA,+CAAvF,OAAe,UAA6B,CAAC,GAA0C;AAClG,UAAI,CAAC,KAAK,aAAa;AACrB,cAAM,IAAI,MAAM,sDAAsD;AAAA,MACxE;AAEA,YAAM,QAAQ,QAAQ,SAAS;AAC/B,YAAM,SAAS,QAAQ,UAAU;AAEjC,UAAI,MAAM,kBAAkB,KAAK;AAEjC,YAAM,UAAU,MAAM,KAAK,MAAM,OAAO,OAAO;AAAA,QAC7C,OAAO,QAAQ;AAAA,QACf,SAAS,QAAQ;AAAA,QACjB,QAAQ;AAAA,MACV,CAAC;AAED,YAAM,UAAU,oBAAI,IAAY;AAChC,YAAM,YAA0C,CAAC;AAEjD,iBAAW,gBAAgB,SAAS;AAClC,YAAI,MAAM,QAAQ,aAAa,MAAM,GAAG;AACtC,qBAAW,UAAU,aAAa,QAAQ;AACxC,kBAAM,KAAK,OAAO,WAAW,YAAY,QAAQ,SAAS,OAAO,KAAK;AACtE,kBAAM,MAAM,OAAO,WAAW,YAAY,SAAS,SAAS,OAAO,MAAM;AAEzE,gBAAI,CAAC,QAAQ,IAAI,EAAY,KAAK,KAAK;AACrC,sBAAQ,IAAI,EAAY;AACxB,wBAAU,KAAK,GAAG;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,eAAe,UAAU,MAAM,QAAQ,SAAS,KAAK;AAE3D,aAAO;AAAA,IACT;AAAA;AAAA,EAEA,QAAgB;AACd,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,YAAYC,OAAc;AACxB,WAAO,KAAK,MAAM,IAAIA,KAAI;AAAA,EAC5B;AAAA,EAEA,gBAAgB,OAA8C;AAC5D,UAAM,YAA0C,CAAC;AACjD,QAAI,QAAQ;AACZ,YAAQ,SAAS;AAEjB,eAAW,MAAM,KAAK,aAAa;AACjC,UAAI,SAAS,OAAO;AAClB;AAAA,MACF;AAEA,YAAM,MAAM,KAAK,MAAM,IAAI,EAAE;AAC7B,UAAI,KAAK;AACP,kBAAU,KAAK,GAAG;AAClB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,2CAA2C,UAAU,QAAQ,KAAK;AAC5E,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,MAAM;AACjB,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,YAAY,MAAM;AAAA,EACzB;AAAA,EAEM,OAAO,SAAoF;AAAA;AAC/F,YAAM,OAAiB,CAAC;AAExB,YAAM,QAAQ,uBAAuB,KAAK,UAAU,MAAM,KAAK,KAAK,WAAW,CAAC,CAAC;AACjF,WAAK,KAAK,qBAAqB;AAE/B,YAAM,KAAK,MAAM,OAAO,CAAO,KAAa,SAAiB;AAC3D,aAAK,KAAK,GAAG;AACb,cAAM,QAAQ,KAAK,IAAI;AAAA,MACzB,EAAC;AAED,UAAI,MAAM,kBAAkB,KAAK,MAAM;AAEvC,aAAO,EAAE,KAAK;AAAA,IAChB;AAAA;AAAA,EAEM,OAAO,SAA2C,MAA+B;AAAA;AACrF,YAAM,kBAAkB,MAAM,QAAQ,qBAAqB;AAC3D,UAAI,iBAAiB;AACnB,cAAM,SAAS,OAAO,oBAAoB,WAAW,KAAK,MAAM,eAAe,IAAI;AACnF,aAAK,cAAc,IAAI,IAAI,MAAM;AAAA,MACnC;AAEA,iBAAW,OAAO,MAAM;AACtB,YAAI,QAAQ,uBAAuB;AACjC;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,OAAO,MAAM,QAAQ,GAAG;AAC9B,cAAI,MAAM;AACR,iBAAK,MAAM,OAAO,KAAK,IAAI;AAAA,UAC7B;AAAA,QACF,SAAS,OAAO;AACd,cAAI,MAAM,wBAAwB,KAAK,KAAK;AAAA,QAC9C;AAAA,MACF;AAEA,WAAK,cAAc;AACnB,UAAI,MAAM,+BAA+B,KAAK,MAAM;AAAA,IACtD;AAAA;AACF;;;AD9KA,IAAMC,OAAMC,SAAQ;AAOb,IAAM,eAAN,MAAmB;AAAA;AAAA,EAKxB,YAAY,SAA8B;AACxC,SAAK,aAAa,IAAI,WAAW;AACjC,SAAK,cAAc;AAAA,EACrB;AAAA,EAEM,aAA4B;AAAA;AAChC,UAAI,KAAK,aAAa;AACpB;AAAA,MACF;AAEA,MAAAD,KAAI,MAAM,4BAA4B;AACtC,YAAM,KAAK,WAAW,WAAW;AACjC,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA,EAEM,QAAQE,OAAc,SAAwC;AAAA;AAClE,UAAI,CAAC,KAAK,aAAa;AACrB,cAAM,IAAI,MAAM,yDAAyD;AAAA,MAC3E;AAEA,YAAM,WAAuC;AAAA,QAC3C,IAAIA;AAAA,QACJ,MAAAA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,KAAK,WAAW,YAAY,QAAQ;AAC1C,MAAAF,KAAI,MAAM,gCAAgCE,KAAI;AAAA,IAChD;AAAA;AAAA,EAEM,OAAO,IAAuF;AAAA,+CAAvF,OAAe,UAA6B,CAAC,GAA0C;AAClG,UAAI,CAAC,KAAK,aAAa;AACrB,cAAM,IAAI,MAAM,yDAAyD;AAAA,MAC3E;AAEA,MAAAF,KAAI,MAAM,2BAA2B,KAAK;AAC1C,aAAO,KAAK,WAAW,OAAO,OAAO,OAAO;AAAA,IAC9C;AAAA;AAAA,EAEA,QAAgB;AACd,WAAO,KAAK,WAAW,MAAM;AAAA,EAC/B;AAAA,EAEA,YAAYE,OAAc;AACxB,WAAO,KAAK,WAAW,YAAYA,KAAI;AAAA,EACzC;AAAA,EAEA,gBAAgB,OAA8C;AAC5D,WAAO,KAAK,WAAW,gBAAgB,KAAK;AAAA,EAC9C;AAAA,EAEA,QAAc;AACZ,SAAK,WAAW,MAAM;AAAA,EACxB;AAAA,EAEM,OAAO,SAAoF;AAAA;AAC/F,aAAO,KAAK,WAAW,OAAO,OAAO;AAAA,IACvC;AAAA;AAAA,EAEM,OAAO,SAA2C,MAA+B;AAAA;AACrF,YAAM,KAAK,WAAW,OAAO,SAAS,IAAI;AAC1C,WAAK,cAAc;AACnB,MAAAF,KAAI,MAAM,8CAA8C;AAAA,IAC1D;AAAA;AACF;;;AEjEA,SAAsB,iBAAiB,OAAgD;AAAA;AACrF,UAAM,eAAe,IAAI,aAAa;AACtC,UAAM,aAAa,WAAW;AAE9B,eAAW,QAAQ,OAAO;AACxB,YAAM,aAAa,QAAQ,KAAK,MAAM,KAAK,cAAc;AAAA,IAC3D;AAEA,UAAM,eAAuC,CAAC;AAC9C,UAAM,SAAS,MAAM,aAAa,OAAO,CAAO,KAAK,SAAS;AAC5D,mBAAa,GAAG,IAAI;AAAA,IACtB,EAAC;AAED,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF;AAAA;;;ACjCA,SAAS,WAAAG,gBAAe;AACxB,YAAY,YAAY;AACxB,YAAY,QAAQ;AACpB,YAAY,UAAU;AAItB,IAAMC,OAAMC,SAAQ;AAkBb,IAAM,+BAAN,MAAkE;AAAA,EAKvE,YAAY,SAA8C;AAF1D,SAAQ,aAAqC;AA5B/C;AA+BI,SAAK,WAAU,aAAQ,YAAR,YAAmB,QAAQ,IAAI;AAC9C,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA,EAEQ,cAAsB;AAC5B,WAAY,UAAK,KAAK,SAAS,KAAK,SAAS;AAAA,EAC/C;AAAA,EAEc,WAA4C;AAAA;AACxD,UAAI,KAAK,YAAY;AACnB,eAAO,KAAK;AAAA,MACd;AAEA,YAAM,WAAW,KAAK,YAAY;AAElC,UAAI;AACF,cAAM,cAAc,MAAS,YAAS,UAAU,OAAO;AACvD,cAAM,OAAO,KAAK,MAAM,WAAW;AAEnC,YAAI,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,MAAM,QAAQ,KAAK,IAAI,KAAK,CAAC,KAAK,MAAM;AAClE,UAAAD,KAAI,KAAK,2CAA2C,QAAQ;AAC5D,iBAAO;AAAA,QACT;AAEA,YAAI,KAAK,KAAK,WAAW,GAAG;AAC1B,UAAAA,KAAI,MAAM,0BAA0B,QAAQ;AAC5C,iBAAO;AAAA,QACT;AAEA,aAAK,aAAa;AAClB,QAAAA,KAAI,MAAM,kCAAkC,UAAU,QAAQ,KAAK,KAAK,QAAQ,MAAM;AACtF,eAAO;AAAA,MACT,SAAS,OAAO;AACd,QAAAA,KAAI,MAAM,0CAA0C,UAAU,KAAK;AACnE,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA,EAEM,SAA0C;AAAA;AAC9C,YAAM,OAAO,MAAM,KAAK,SAAS;AACjC,aAAO;AAAA,IACT;AAAA;AAAA,EAEM,OAAO,IAAmF;AAAA,+CAAnF,MAAuB,UAAyB,EAAE,UAAU,KAAK,GAAkB;AAC9F,YAAM,WAAW,KAAK,YAAY;AAElC,UAAI;AACF,YAAI,EAAC,mCAAS,WAAU;AACtB,cAAI;AACF,kBAAS,UAAO,QAAQ;AACxB,YAAAA,KAAI,MAAM,4EAA4E,QAAQ;AAC9F;AAAA,UACF,SAAQ;AAAA,UAER;AAAA,QACF;AAEA,cAAM,MAAW,aAAQ,QAAQ;AACjC,cAAS,SAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAEvC,cAAS,aAAU,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AAEnE,QAAAA,KAAI,MAAM,+BAA+B,UAAU,QAAQ,KAAK,KAAK,QAAQ,MAAM;AAAA,MACrF,SAAS,OAAO;AACd,QAAAA,KAAI,MAAM,wCAAwC,UAAU,KAAK;AACjE,cAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA,EAEA,WAAW,MAAuB,UAAyB,EAAE,UAAU,KAAK,GAAS;AACnF,UAAM,WAAW,KAAK,YAAY;AAElC,QAAI;AACF,UAAI,EAAC,mCAAS,WAAU;AACtB,YAAI;AACF,UAAO,kBAAW,QAAQ;AAC1B,UAAAA,KAAI,MAAM,4EAA4E,QAAQ;AAC9F;AAAA,QACF,SAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,MAAW,aAAQ,QAAQ;AACjC,MAAO,iBAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAEzC,MAAO,qBAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AAErE,MAAAA,KAAI,MAAM,+BAA+B,UAAU,QAAQ,KAAK,KAAK,QAAQ,MAAM;AAAA,IACrF,SAAS,OAAO;AACd,MAAAA,KAAI,MAAM,wCAAwC,UAAU,KAAK;AACjE,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AClHO,SAAS,yBAAyB,gBAA2D;AAClG,MAAI,eAAe,SAAS,aAAa;AACvC,WAAO,IAAI,6BAA6B,mBACnC,eAAe,OACnB;AAAA,EACH;AAEA,QAAM,IAAI,MAAM,0BAA0B,eAAe,IAAI,EAAE;AACjE;","names":["loggers","path","log","loggers","path","loggers","log","loggers"]}
1
+ {"version":3,"sources":["../src/searchEngine/textBasedSearchEngine.ts","../src/searchEngine/textSearch.ts","../src/stores/FileBasedSearchIndexStore.ts","../src/stores/config.ts"],"sourcesContent":["import { loggers } from '@peam-ai/logger';\nimport type { StructuredPage } from '@peam-ai/parser';\nimport type { StructuredPageDocumentData } from '../types';\nimport { SearchEngine, SearchOptions } from './searchEngine';\nimport { TextSearch } from './textSearch';\n\nconst log = loggers.search;\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TextBasedSearchEngineConfig {\n // Reserved for future configuration options\n}\n\nexport class TextBasedSearchEngine implements SearchEngine {\n private textSearch: TextSearch;\n private initialized: boolean;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n constructor(_config?: TextBasedSearchEngineConfig) {\n this.textSearch = new TextSearch();\n this.initialized = false;\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n log.debug('Initializing search engine');\n await this.textSearch.initialize();\n this.initialized = true;\n }\n\n async addPage(path: string, content: StructuredPage): Promise<void> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n const document: StructuredPageDocumentData = {\n id: path,\n path,\n content: {\n title: content.title,\n description: content.description,\n content: content.markdownContent ? content.markdownContent : content.textContent,\n author: content.author,\n keywords: content.keywords,\n language: content.language,\n publishedTime: content.publishedTime,\n },\n };\n\n await this.textSearch.addDocument(document);\n log.debug('Page added to search engine:', path);\n }\n\n async search(query: string, options: SearchOptions = {}): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('Search engine not initialized. Call initialize() first.');\n }\n\n log.debug('Performing text search:', query);\n return this.textSearch.search(query, options);\n }\n\n count(): number {\n return this.textSearch.count();\n }\n\n getDocument(path: string) {\n return this.textSearch.getDocument(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n return this.textSearch.getAllDocuments(limit);\n }\n\n clear(): void {\n this.textSearch.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n return this.textSearch.export(handler);\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n await this.textSearch.import(handler, keys);\n this.initialized = true;\n log.debug('Search engine initialized from imported data');\n }\n}\n","import { loggers } from '@peam-ai/logger';\nimport { Charset, Document } from 'flexsearch';\nimport type { StructuredPageDocumentData } from '../types';\nimport { SearchOptions } from './searchEngine';\n\nconst PEAM_DOCUMENT_IDS_KEY = 'peam.documentIds';\nconst MAX_DOCUMENTS_RETRIEVE = 25;\nconst log = loggers.search;\n\nexport class TextSearch {\n private index: Document<StructuredPageDocumentData>;\n private initialized: boolean;\n private documentIds: Set<string>;\n\n constructor() {\n this.initialized = false;\n this.index = this.getIndex();\n this.documentIds = new Set();\n }\n\n private getIndex() {\n return new Document<StructuredPageDocumentData>({\n worker: false,\n document: {\n id: 'path',\n index: ['content:title', 'content:description', 'content:content', 'content:keywords', 'content:author'],\n store: ['id', 'path', 'content:title', 'content:content', 'content:language'],\n },\n tokenize: 'forward',\n resolution: 9,\n context: {\n resolution: 3,\n depth: 2,\n bidirectional: true,\n },\n cache: 100,\n encoder: Charset.LatinExtra,\n });\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n log.debug('Text search already initialized');\n return;\n }\n\n this.initialized = true;\n }\n\n async addDocument(document: StructuredPageDocumentData): Promise<void> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n log.debug('Adding document to text search:', document.path);\n\n this.index.add(document);\n this.documentIds.add(document.path);\n }\n\n async search(\n query: string,\n options: SearchOptions = {\n limit: MAX_DOCUMENTS_RETRIEVE,\n offset: 0,\n suggest: true,\n }\n ): Promise<StructuredPageDocumentData[]> {\n if (!this.initialized) {\n throw new Error('TextSearch not initialized. Call initialize() first.');\n }\n\n const limit = options.limit || MAX_DOCUMENTS_RETRIEVE;\n const offset = options.offset || 0;\n const suggest = options.suggest || true;\n\n log.debug('Searching for:', query);\n\n const results = await this.index.search(query, {\n offset,\n limit,\n suggest,\n enrich: true,\n });\n\n const pathSet = new Set<string>();\n const documents: StructuredPageDocumentData[] = [];\n\n for (const fieldResults of results) {\n if (Array.isArray(fieldResults.result)) {\n for (const result of fieldResults.result) {\n const id = typeof result === 'object' && 'id' in result ? result.id : result;\n const doc = typeof result === 'object' && 'doc' in result ? result.doc : null;\n\n if (!pathSet.has(id as string) && doc) {\n pathSet.add(id as string);\n documents.push(doc);\n }\n }\n }\n }\n\n return documents;\n }\n\n count(): number {\n return this.documentIds.size;\n }\n\n getDocument(path: string) {\n return this.index.get(path);\n }\n\n getAllDocuments(limit?: number): StructuredPageDocumentData[] {\n const documents: StructuredPageDocumentData[] = [];\n let count = 0;\n limit = limit || MAX_DOCUMENTS_RETRIEVE;\n\n for (const id of this.documentIds) {\n if (count >= limit) {\n break;\n }\n\n const doc = this.index.get(id);\n if (doc) {\n documents.push(doc);\n count++;\n }\n }\n\n log.debug('Retrieved documents from store (limit):', documents.length, limit);\n return documents;\n }\n\n clear(): void {\n this.index.clear();\n this.index = this.getIndex();\n this.documentIds.clear();\n }\n\n async export(handler: (key: string, data: string) => Promise<void>): Promise<{ keys: string[] }> {\n const keys: string[] = [];\n\n await handler(PEAM_DOCUMENT_IDS_KEY, JSON.stringify(Array.from(this.documentIds)));\n keys.push(PEAM_DOCUMENT_IDS_KEY);\n\n await this.index.export(async (key: string, data: string) => {\n keys.push(key);\n await handler(key, data);\n });\n\n log.debug('Exported keys:', keys.length);\n\n return { keys };\n }\n\n async import(handler: (key: string) => Promise<string>, keys: string[]): Promise<void> {\n const documentIdsData = await handler(PEAM_DOCUMENT_IDS_KEY);\n if (documentIdsData) {\n const parsed = typeof documentIdsData === 'string' ? JSON.parse(documentIdsData) : documentIdsData;\n this.documentIds = new Set(parsed);\n }\n\n for (const key of keys) {\n if (key === PEAM_DOCUMENT_IDS_KEY) {\n continue;\n }\n\n try {\n const data = await handler(key);\n if (data) {\n this.index.import(key, data);\n }\n } catch (error) {\n log.error('Error importing key:', key, error);\n }\n }\n\n this.initialized = true;\n log.debug('Import completed with keys:', keys.length);\n }\n}\n","import { loggers } from '@peam-ai/logger';\nimport * as fsSync from 'fs';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { SearchIndexData } from '../types';\nimport type { SearchIndexStore, StoreOptions } from './SearchIndexStore';\n\nconst log = loggers.search;\n\n/**\n * Configuration for file-based search index store\n * @description Configuration for file-based search index store\n */\nexport interface FileBasedSearchIndexStoreOptions {\n /**\n * The path to the index file relative to baseDir\n * @description The path to the index file relative to baseDir\n * @default .peam/index.json\n */\n indexPath?: string;\n\n /**\n * The directory where the index file is located\n * @description The directory where the index file is located\n */\n baseDir?: string;\n}\n\n/**\n * File-based implementation of SearchIndexStore\n * Reads and writes search index data to/from a JSON file\n */\nexport class FileBasedSearchIndexStore implements SearchIndexStore {\n private baseDir: string;\n private indexPath: string;\n private cachedData: SearchIndexData | null = null;\n\n constructor(options: FileBasedSearchIndexStoreOptions) {\n this.baseDir = options.baseDir ?? process.cwd();\n this.indexPath = options.indexPath ?? '.peam/index.json';\n }\n\n private getFullPath(): string {\n return path.join(this.baseDir, this.indexPath);\n }\n\n private async loadData(): Promise<SearchIndexData | null> {\n if (this.cachedData) {\n return this.cachedData;\n }\n\n const fullPath = this.getFullPath();\n\n try {\n const fileContent = await fs.readFile(fullPath, 'utf-8');\n const data = JSON.parse(fileContent) as SearchIndexData;\n\n if (!data || !data.keys || !Array.isArray(data.keys) || !data.data) {\n log.warn('Invalid search index structure in file:', fullPath);\n return null;\n }\n\n if (data.keys.length === 0) {\n log.debug('Search index is empty:', fullPath);\n return null;\n }\n\n this.cachedData = data;\n log.debug('Search index loaded from file:', fullPath, 'with', data.keys.length, 'keys');\n return data;\n } catch (error) {\n log.error('Failed to load search index from file:', fullPath, error);\n return null;\n }\n }\n\n async import(): Promise<SearchIndexData | null> {\n const data = await this.loadData();\n return data;\n }\n\n async export(data: SearchIndexData, options: StoreOptions = { override: true }): Promise<void> {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n await fs.access(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n\n exportSync(data: SearchIndexData, options: StoreOptions = { override: true }): void {\n const fullPath = this.getFullPath();\n\n try {\n if (!options?.override) {\n try {\n fsSync.accessSync(fullPath);\n log.debug('Search index file already exists and override is false, skipping export:', fullPath);\n return;\n } catch {\n // noop\n }\n }\n\n const dir = path.dirname(fullPath);\n fsSync.mkdirSync(dir, { recursive: true });\n\n fsSync.writeFileSync(fullPath, JSON.stringify(data, null, 2), 'utf-8');\n\n log.debug('Search index saved to file:', fullPath, 'with', data.keys.length, 'keys');\n } catch (error) {\n log.error('Failed to save search index to file:', fullPath, error);\n throw error;\n }\n }\n}\n","import { FileBasedSearchIndexStore, FileBasedSearchIndexStoreOptions } from './FileBasedSearchIndexStore';\nimport { SearchIndexStore } from './SearchIndexStore';\n\nexport type SearchStoreConfig = {\n type: 'fileBased';\n config: FileBasedSearchIndexStoreOptions;\n};\n\n/**\n * Creates a SearchIndexStore instance from a SearchStoreConfig\n */\nexport function createStoreFromConfig(storeConfig: SearchStoreConfig): SearchIndexStore {\n if (storeConfig.type === 'fileBased') {\n return new FileBasedSearchIndexStore({\n ...storeConfig.config,\n });\n }\n\n throw new Error(`Unknown store type: ${storeConfig.type}`);\n}\n"],"mappings":"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","names":["loggers","path","log","loggers","path","loggers","log","loggers"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peam-ai/search",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Vector database and search functionality for Peam",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "flexsearch": "^0.8.212",
32
- "@peam-ai/logger": "0.1.3",
33
- "@peam-ai/parser": "0.1.3"
32
+ "@peam-ai/logger": "0.1.5",
33
+ "@peam-ai/parser": "0.1.5"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^22.10.2",
@@ -39,11 +39,11 @@
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsup",
42
- "dev": "tsup --watch",
42
+ "build:watch": "tsup --watch",
43
43
  "clean": "rm -rf dist",
44
- "lint": "eslint .",
45
- "test:eslint": "eslint \"src/**/*.ts*\"",
46
- "test:prettier": "prettier --check \"src/**/*.ts*\"",
47
- "test:jest": "jest"
44
+ "format": "prettier --write \"src/**/*.ts*\"",
45
+ "test:lint": "eslint \"src/**/*.ts*\"",
46
+ "test:format": "prettier --check \"src/**/*.ts*\"",
47
+ "test:unit": "vitest run"
48
48
  }
49
49
  }