@peam-ai/search 0.1.4 → 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 +83 -45
- package/dist/index.d.ts +83 -45
- package/dist/index.js +19 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
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
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
|
|
14
|
+
interface SearchOptions {
|
|
24
15
|
limit?: number;
|
|
25
16
|
offset?: number;
|
|
26
17
|
suggest?: boolean;
|
|
27
18
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Interface for a search engine.
|
|
21
|
+
*/
|
|
22
|
+
interface SearchEngine {
|
|
23
|
+
/**
|
|
24
|
+
* Initializes the search engine.
|
|
25
|
+
*/
|
|
34
26
|
initialize(): Promise<void>;
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
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?:
|
|
83
|
+
constructor(_config?: TextBasedSearchEngineConfig);
|
|
53
84
|
initialize(): Promise<void>;
|
|
54
85
|
addPage(path: string, content: StructuredPage): Promise<void>;
|
|
55
|
-
search(query: string, options?:
|
|
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
|
|
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
|
|
105
|
+
* Interface for storing and loading search indexes
|
|
75
106
|
*/
|
|
76
|
-
interface
|
|
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
|
|
116
|
+
* @param options Store options
|
|
86
117
|
*/
|
|
87
|
-
export(data: SearchIndexData, options?:
|
|
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
|
|
122
|
+
* @param options Store options
|
|
92
123
|
*/
|
|
93
|
-
exportSync?(data: SearchIndexData, options?:
|
|
124
|
+
exportSync?(data: SearchIndexData, options?: StoreOptions): void;
|
|
94
125
|
}
|
|
95
126
|
|
|
96
|
-
|
|
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
|
|
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
|
|
145
|
+
* File-based implementation of SearchIndexStore
|
|
108
146
|
* Reads and writes search index data to/from a JSON file
|
|
109
147
|
*/
|
|
110
|
-
declare class
|
|
148
|
+
declare class FileBasedSearchIndexStore implements SearchIndexStore {
|
|
111
149
|
private baseDir;
|
|
112
150
|
private indexPath;
|
|
113
151
|
private cachedData;
|
|
114
|
-
constructor(options:
|
|
152
|
+
constructor(options: FileBasedSearchIndexStoreOptions);
|
|
115
153
|
private getFullPath;
|
|
116
154
|
private loadData;
|
|
117
155
|
import(): Promise<SearchIndexData | null>;
|
|
118
|
-
export(data: SearchIndexData, options?:
|
|
119
|
-
exportSync(data: SearchIndexData, options?:
|
|
156
|
+
export(data: SearchIndexData, options?: StoreOptions): Promise<void>;
|
|
157
|
+
exportSync(data: SearchIndexData, options?: StoreOptions): void;
|
|
120
158
|
}
|
|
121
159
|
|
|
122
|
-
type
|
|
160
|
+
type SearchStoreConfig = {
|
|
123
161
|
type: 'fileBased';
|
|
124
|
-
config:
|
|
162
|
+
config: FileBasedSearchIndexStoreOptions;
|
|
125
163
|
};
|
|
126
164
|
/**
|
|
127
|
-
* Creates a
|
|
165
|
+
* Creates a SearchIndexStore instance from a SearchStoreConfig
|
|
128
166
|
*/
|
|
129
|
-
declare function
|
|
167
|
+
declare function createStoreFromConfig(storeConfig: SearchStoreConfig): SearchIndexStore;
|
|
130
168
|
|
|
131
|
-
export {
|
|
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
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
|
|
14
|
+
interface SearchOptions {
|
|
24
15
|
limit?: number;
|
|
25
16
|
offset?: number;
|
|
26
17
|
suggest?: boolean;
|
|
27
18
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Interface for a search engine.
|
|
21
|
+
*/
|
|
22
|
+
interface SearchEngine {
|
|
23
|
+
/**
|
|
24
|
+
* Initializes the search engine.
|
|
25
|
+
*/
|
|
34
26
|
initialize(): Promise<void>;
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
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?:
|
|
83
|
+
constructor(_config?: TextBasedSearchEngineConfig);
|
|
53
84
|
initialize(): Promise<void>;
|
|
54
85
|
addPage(path: string, content: StructuredPage): Promise<void>;
|
|
55
|
-
search(query: string, options?:
|
|
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
|
|
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
|
|
105
|
+
* Interface for storing and loading search indexes
|
|
75
106
|
*/
|
|
76
|
-
interface
|
|
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
|
|
116
|
+
* @param options Store options
|
|
86
117
|
*/
|
|
87
|
-
export(data: SearchIndexData, options?:
|
|
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
|
|
122
|
+
* @param options Store options
|
|
92
123
|
*/
|
|
93
|
-
exportSync?(data: SearchIndexData, options?:
|
|
124
|
+
exportSync?(data: SearchIndexData, options?: StoreOptions): void;
|
|
94
125
|
}
|
|
95
126
|
|
|
96
|
-
|
|
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
|
|
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
|
|
145
|
+
* File-based implementation of SearchIndexStore
|
|
108
146
|
* Reads and writes search index data to/from a JSON file
|
|
109
147
|
*/
|
|
110
|
-
declare class
|
|
148
|
+
declare class FileBasedSearchIndexStore implements SearchIndexStore {
|
|
111
149
|
private baseDir;
|
|
112
150
|
private indexPath;
|
|
113
151
|
private cachedData;
|
|
114
|
-
constructor(options:
|
|
152
|
+
constructor(options: FileBasedSearchIndexStoreOptions);
|
|
115
153
|
private getFullPath;
|
|
116
154
|
private loadData;
|
|
117
155
|
import(): Promise<SearchIndexData | null>;
|
|
118
|
-
export(data: SearchIndexData, options?:
|
|
119
|
-
exportSync(data: SearchIndexData, options?:
|
|
156
|
+
export(data: SearchIndexData, options?: StoreOptions): Promise<void>;
|
|
157
|
+
exportSync(data: SearchIndexData, options?: StoreOptions): void;
|
|
120
158
|
}
|
|
121
159
|
|
|
122
|
-
type
|
|
160
|
+
type SearchStoreConfig = {
|
|
123
161
|
type: 'fileBased';
|
|
124
|
-
config:
|
|
162
|
+
config: FileBasedSearchIndexStoreOptions;
|
|
125
163
|
};
|
|
126
164
|
/**
|
|
127
|
-
* Creates a
|
|
165
|
+
* Creates a SearchIndexStore instance from a SearchStoreConfig
|
|
128
166
|
*/
|
|
129
|
-
declare function
|
|
167
|
+
declare function createStoreFromConfig(storeConfig: SearchStoreConfig): SearchIndexStore;
|
|
130
168
|
|
|
131
|
-
export {
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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";
|
|
@@ -228,9 +226,9 @@ var TextSearch = class {
|
|
|
228
226
|
}
|
|
229
227
|
};
|
|
230
228
|
|
|
231
|
-
// src/searchEngine.ts
|
|
229
|
+
// src/searchEngine/textBasedSearchEngine.ts
|
|
232
230
|
var log2 = import_logger2.loggers.search;
|
|
233
|
-
var
|
|
231
|
+
var TextBasedSearchEngine = class {
|
|
234
232
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
235
233
|
constructor(_config) {
|
|
236
234
|
this.textSearch = new TextSearch();
|
|
@@ -303,37 +301,18 @@ var SearchEngine = class {
|
|
|
303
301
|
}
|
|
304
302
|
};
|
|
305
303
|
|
|
306
|
-
// src/
|
|
307
|
-
function buildSearchIndex(pages) {
|
|
308
|
-
return __async(this, null, function* () {
|
|
309
|
-
const searchEngine = new SearchEngine();
|
|
310
|
-
yield searchEngine.initialize();
|
|
311
|
-
for (const page of pages) {
|
|
312
|
-
yield searchEngine.addPage(page.path, page.structuredPage);
|
|
313
|
-
}
|
|
314
|
-
const exportedData = {};
|
|
315
|
-
const result = yield searchEngine.export((key, data) => __async(null, null, function* () {
|
|
316
|
-
exportedData[key] = data;
|
|
317
|
-
}));
|
|
318
|
-
return {
|
|
319
|
-
keys: result.keys,
|
|
320
|
-
data: exportedData
|
|
321
|
-
};
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// src/exporters/FileBasedSearchIndexExporter.ts
|
|
304
|
+
// src/stores/FileBasedSearchIndexStore.ts
|
|
326
305
|
var import_logger3 = require("@peam-ai/logger");
|
|
327
306
|
var fsSync = __toESM(require("fs"));
|
|
328
307
|
var fs = __toESM(require("fs/promises"));
|
|
329
308
|
var path = __toESM(require("path"));
|
|
330
309
|
var log3 = import_logger3.loggers.search;
|
|
331
|
-
var
|
|
310
|
+
var FileBasedSearchIndexStore = class {
|
|
332
311
|
constructor(options) {
|
|
333
312
|
this.cachedData = null;
|
|
334
|
-
var _a;
|
|
313
|
+
var _a, _b;
|
|
335
314
|
this.baseDir = (_a = options.baseDir) != null ? _a : process.cwd();
|
|
336
|
-
this.indexPath = options.indexPath;
|
|
315
|
+
this.indexPath = (_b = options.indexPath) != null ? _b : ".peam/index.json";
|
|
337
316
|
}
|
|
338
317
|
getFullPath() {
|
|
339
318
|
return path.join(this.baseDir, this.indexPath);
|
|
@@ -414,19 +393,17 @@ var FileBasedSearchIndexExporter = class {
|
|
|
414
393
|
}
|
|
415
394
|
};
|
|
416
395
|
|
|
417
|
-
// src/
|
|
418
|
-
function
|
|
419
|
-
if (
|
|
420
|
-
return new
|
|
396
|
+
// src/stores/config.ts
|
|
397
|
+
function createStoreFromConfig(storeConfig) {
|
|
398
|
+
if (storeConfig.type === "fileBased") {
|
|
399
|
+
return new FileBasedSearchIndexStore(__spreadValues({}, storeConfig.config));
|
|
421
400
|
}
|
|
422
|
-
throw new Error(`Unknown
|
|
401
|
+
throw new Error(`Unknown store type: ${storeConfig.type}`);
|
|
423
402
|
}
|
|
424
403
|
// Annotate the CommonJS export names for ESM import in node:
|
|
425
404
|
0 && (module.exports = {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
buildSearchIndex,
|
|
430
|
-
createExporterFromConfig
|
|
405
|
+
FileBasedSearchIndexStore,
|
|
406
|
+
TextBasedSearchEngine,
|
|
407
|
+
createStoreFromConfig
|
|
431
408
|
});
|
|
432
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 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: 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: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: TextSearchOptions = {\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 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";
|
|
@@ -191,9 +191,9 @@ var TextSearch = class {
|
|
|
191
191
|
}
|
|
192
192
|
};
|
|
193
193
|
|
|
194
|
-
// src/searchEngine.ts
|
|
194
|
+
// src/searchEngine/textBasedSearchEngine.ts
|
|
195
195
|
var log2 = loggers2.search;
|
|
196
|
-
var
|
|
196
|
+
var TextBasedSearchEngine = class {
|
|
197
197
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
198
198
|
constructor(_config) {
|
|
199
199
|
this.textSearch = new TextSearch();
|
|
@@ -266,37 +266,18 @@ var SearchEngine = class {
|
|
|
266
266
|
}
|
|
267
267
|
};
|
|
268
268
|
|
|
269
|
-
// src/
|
|
270
|
-
function buildSearchIndex(pages) {
|
|
271
|
-
return __async(this, null, function* () {
|
|
272
|
-
const searchEngine = new SearchEngine();
|
|
273
|
-
yield searchEngine.initialize();
|
|
274
|
-
for (const page of pages) {
|
|
275
|
-
yield searchEngine.addPage(page.path, page.structuredPage);
|
|
276
|
-
}
|
|
277
|
-
const exportedData = {};
|
|
278
|
-
const result = yield searchEngine.export((key, data) => __async(null, null, function* () {
|
|
279
|
-
exportedData[key] = data;
|
|
280
|
-
}));
|
|
281
|
-
return {
|
|
282
|
-
keys: result.keys,
|
|
283
|
-
data: exportedData
|
|
284
|
-
};
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// src/exporters/FileBasedSearchIndexExporter.ts
|
|
269
|
+
// src/stores/FileBasedSearchIndexStore.ts
|
|
289
270
|
import { loggers as loggers3 } from "@peam-ai/logger";
|
|
290
271
|
import * as fsSync from "fs";
|
|
291
272
|
import * as fs from "fs/promises";
|
|
292
273
|
import * as path from "path";
|
|
293
274
|
var log3 = loggers3.search;
|
|
294
|
-
var
|
|
275
|
+
var FileBasedSearchIndexStore = class {
|
|
295
276
|
constructor(options) {
|
|
296
277
|
this.cachedData = null;
|
|
297
|
-
var _a;
|
|
278
|
+
var _a, _b;
|
|
298
279
|
this.baseDir = (_a = options.baseDir) != null ? _a : process.cwd();
|
|
299
|
-
this.indexPath = options.indexPath;
|
|
280
|
+
this.indexPath = (_b = options.indexPath) != null ? _b : ".peam/index.json";
|
|
300
281
|
}
|
|
301
282
|
getFullPath() {
|
|
302
283
|
return path.join(this.baseDir, this.indexPath);
|
|
@@ -377,18 +358,16 @@ var FileBasedSearchIndexExporter = class {
|
|
|
377
358
|
}
|
|
378
359
|
};
|
|
379
360
|
|
|
380
|
-
// src/
|
|
381
|
-
function
|
|
382
|
-
if (
|
|
383
|
-
return new
|
|
361
|
+
// src/stores/config.ts
|
|
362
|
+
function createStoreFromConfig(storeConfig) {
|
|
363
|
+
if (storeConfig.type === "fileBased") {
|
|
364
|
+
return new FileBasedSearchIndexStore(__spreadValues({}, storeConfig.config));
|
|
384
365
|
}
|
|
385
|
-
throw new Error(`Unknown
|
|
366
|
+
throw new Error(`Unknown store type: ${storeConfig.type}`);
|
|
386
367
|
}
|
|
387
368
|
export {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
buildSearchIndex,
|
|
392
|
-
createExporterFromConfig
|
|
369
|
+
FileBasedSearchIndexStore,
|
|
370
|
+
TextBasedSearchEngine,
|
|
371
|
+
createStoreFromConfig
|
|
393
372
|
};
|
|
394
373
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 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: 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: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: TextSearchOptions = {\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 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":["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
|
+
"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.
|
|
33
|
-
"@peam-ai/parser": "0.1.
|
|
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,10 +39,11 @@
|
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsup",
|
|
42
|
-
"
|
|
42
|
+
"build:watch": "tsup --watch",
|
|
43
43
|
"clean": "rm -rf dist",
|
|
44
|
+
"format": "prettier --write \"src/**/*.ts*\"",
|
|
44
45
|
"test:lint": "eslint \"src/**/*.ts*\"",
|
|
45
|
-
"test:
|
|
46
|
+
"test:format": "prettier --check \"src/**/*.ts*\"",
|
|
46
47
|
"test:unit": "vitest run"
|
|
47
48
|
}
|
|
48
49
|
}
|