@soulcraft/brainy 2.14.0 → 2.14.2
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.
|
@@ -75,6 +75,48 @@ export declare abstract class BaseStorageAdapter implements StorageAdapter {
|
|
|
75
75
|
hasMore: boolean;
|
|
76
76
|
nextCursor?: string;
|
|
77
77
|
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Get nouns with pagination (internal implementation)
|
|
80
|
+
* This method should be implemented by storage adapters to support efficient pagination
|
|
81
|
+
* @param options Pagination options
|
|
82
|
+
* @returns Promise that resolves to a paginated result of nouns
|
|
83
|
+
*/
|
|
84
|
+
getNounsWithPagination?(options: {
|
|
85
|
+
limit?: number;
|
|
86
|
+
cursor?: string;
|
|
87
|
+
filter?: {
|
|
88
|
+
nounType?: string | string[];
|
|
89
|
+
service?: string | string[];
|
|
90
|
+
metadata?: Record<string, any>;
|
|
91
|
+
};
|
|
92
|
+
}): Promise<{
|
|
93
|
+
items: any[];
|
|
94
|
+
totalCount?: number;
|
|
95
|
+
hasMore: boolean;
|
|
96
|
+
nextCursor?: string;
|
|
97
|
+
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Get verbs with pagination (internal implementation)
|
|
100
|
+
* This method should be implemented by storage adapters to support efficient pagination
|
|
101
|
+
* @param options Pagination options
|
|
102
|
+
* @returns Promise that resolves to a paginated result of verbs
|
|
103
|
+
*/
|
|
104
|
+
getVerbsWithPagination?(options: {
|
|
105
|
+
limit?: number;
|
|
106
|
+
cursor?: string;
|
|
107
|
+
filter?: {
|
|
108
|
+
verbType?: string | string[];
|
|
109
|
+
sourceId?: string | string[];
|
|
110
|
+
targetId?: string | string[];
|
|
111
|
+
service?: string | string[];
|
|
112
|
+
metadata?: Record<string, any>;
|
|
113
|
+
};
|
|
114
|
+
}): Promise<{
|
|
115
|
+
items: any[];
|
|
116
|
+
totalCount?: number;
|
|
117
|
+
hasMore: boolean;
|
|
118
|
+
nextCursor?: string;
|
|
119
|
+
}>;
|
|
78
120
|
protected statisticsCache: StatisticsData | null;
|
|
79
121
|
protected statisticsBatchUpdateTimerId: NodeJS.Timeout | null;
|
|
80
122
|
protected statisticsModified: boolean;
|
|
@@ -189,6 +189,26 @@ export declare class FileSystemStorage extends BaseStorage {
|
|
|
189
189
|
* Get verbs by type
|
|
190
190
|
*/
|
|
191
191
|
protected getVerbsByType_internal(type: string): Promise<GraphVerb[]>;
|
|
192
|
+
/**
|
|
193
|
+
* Get verbs with pagination
|
|
194
|
+
* This method reads verb files from the filesystem and returns them with pagination
|
|
195
|
+
*/
|
|
196
|
+
getVerbsWithPagination(options?: {
|
|
197
|
+
limit?: number;
|
|
198
|
+
cursor?: string;
|
|
199
|
+
filter?: {
|
|
200
|
+
verbType?: string | string[];
|
|
201
|
+
sourceId?: string | string[];
|
|
202
|
+
targetId?: string | string[];
|
|
203
|
+
service?: string | string[];
|
|
204
|
+
metadata?: Record<string, any>;
|
|
205
|
+
};
|
|
206
|
+
}): Promise<{
|
|
207
|
+
items: GraphVerb[];
|
|
208
|
+
totalCount?: number;
|
|
209
|
+
hasMore: boolean;
|
|
210
|
+
nextCursor?: string;
|
|
211
|
+
}>;
|
|
192
212
|
/**
|
|
193
213
|
* Delete a verb from storage
|
|
194
214
|
*/
|
|
@@ -793,6 +793,103 @@ export class FileSystemStorage extends BaseStorage {
|
|
|
793
793
|
console.warn('getVerbsByType_internal is deprecated and not efficiently supported in new storage pattern');
|
|
794
794
|
return [];
|
|
795
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* Get verbs with pagination
|
|
798
|
+
* This method reads verb files from the filesystem and returns them with pagination
|
|
799
|
+
*/
|
|
800
|
+
async getVerbsWithPagination(options = {}) {
|
|
801
|
+
await this.ensureInitialized();
|
|
802
|
+
const limit = options.limit || 100;
|
|
803
|
+
const startIndex = options.cursor ? parseInt(options.cursor, 10) : 0;
|
|
804
|
+
try {
|
|
805
|
+
// List all verb files in the verbs directory
|
|
806
|
+
// Note: For very large directories (millions of files), this could be memory-intensive
|
|
807
|
+
// Future optimization: Use fs.opendir() for streaming directory reads
|
|
808
|
+
const files = await fs.promises.readdir(this.verbsDir);
|
|
809
|
+
const verbFiles = files.filter((f) => f.endsWith('.json'));
|
|
810
|
+
// Sort files for consistent ordering
|
|
811
|
+
verbFiles.sort();
|
|
812
|
+
// Calculate pagination
|
|
813
|
+
const totalCount = verbFiles.length;
|
|
814
|
+
const endIndex = Math.min(startIndex + limit, totalCount);
|
|
815
|
+
const hasMore = endIndex < totalCount;
|
|
816
|
+
// Safety check for large datasets
|
|
817
|
+
if (totalCount > 100000) {
|
|
818
|
+
console.warn(`Large verb dataset detected (${totalCount} verbs). Consider using a database for better performance.`);
|
|
819
|
+
}
|
|
820
|
+
// Load the requested page of verbs
|
|
821
|
+
const verbs = [];
|
|
822
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
823
|
+
const file = verbFiles[i];
|
|
824
|
+
const id = file.replace('.json', '');
|
|
825
|
+
try {
|
|
826
|
+
// Read the verb data
|
|
827
|
+
const filePath = path.join(this.verbsDir, file);
|
|
828
|
+
const data = await fs.promises.readFile(filePath, 'utf-8');
|
|
829
|
+
const edge = JSON.parse(data);
|
|
830
|
+
// Also try to get metadata if it exists
|
|
831
|
+
const metadata = await this.getVerbMetadata(id);
|
|
832
|
+
// Convert to GraphVerb format
|
|
833
|
+
const verb = {
|
|
834
|
+
id: edge.id,
|
|
835
|
+
source: metadata?.source || '',
|
|
836
|
+
target: metadata?.target || '',
|
|
837
|
+
type: metadata?.type || 'relationship',
|
|
838
|
+
...(metadata || {})
|
|
839
|
+
};
|
|
840
|
+
// Apply filters if provided
|
|
841
|
+
if (options.filter) {
|
|
842
|
+
const filter = options.filter;
|
|
843
|
+
// Check verbType filter
|
|
844
|
+
if (filter.verbType) {
|
|
845
|
+
const types = Array.isArray(filter.verbType) ? filter.verbType : [filter.verbType];
|
|
846
|
+
if (!types.includes(verb.type || ''))
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
// Check sourceId filter
|
|
850
|
+
if (filter.sourceId) {
|
|
851
|
+
const sources = Array.isArray(filter.sourceId) ? filter.sourceId : [filter.sourceId];
|
|
852
|
+
if (!sources.includes(verb.source || ''))
|
|
853
|
+
continue;
|
|
854
|
+
}
|
|
855
|
+
// Check targetId filter
|
|
856
|
+
if (filter.targetId) {
|
|
857
|
+
const targets = Array.isArray(filter.targetId) ? filter.targetId : [filter.targetId];
|
|
858
|
+
if (!targets.includes(verb.target || ''))
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
// Check service filter
|
|
862
|
+
if (filter.service && metadata?.service) {
|
|
863
|
+
const services = Array.isArray(filter.service) ? filter.service : [filter.service];
|
|
864
|
+
if (!services.includes(metadata.service))
|
|
865
|
+
continue;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
verbs.push(verb);
|
|
869
|
+
}
|
|
870
|
+
catch (error) {
|
|
871
|
+
console.warn(`Failed to read verb ${id}:`, error);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return {
|
|
875
|
+
items: verbs,
|
|
876
|
+
totalCount,
|
|
877
|
+
hasMore,
|
|
878
|
+
nextCursor: hasMore ? String(endIndex) : undefined
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
catch (error) {
|
|
882
|
+
if (error.code === 'ENOENT') {
|
|
883
|
+
// Verbs directory doesn't exist yet
|
|
884
|
+
return {
|
|
885
|
+
items: [],
|
|
886
|
+
totalCount: 0,
|
|
887
|
+
hasMore: false
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
throw error;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
796
893
|
/**
|
|
797
894
|
* Delete a verb from storage
|
|
798
895
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.2",
|
|
4
4
|
"description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. 31 nouns × 40 verbs for infinite expressiveness.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|