aifastdb 3.7.6 → 3.8.6-mac.0
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/LICENSE +137 -137
- package/{aifastdb.win32-x64-msvc.node → aifastdb.darwin-arm64.node} +0 -0
- package/dist/cli.js +30 -30
- package/dist/llm-gateway.d.ts +73 -6
- package/dist/llm-gateway.d.ts.map +1 -1
- package/dist/llm-gateway.js.map +1 -1
- package/dist/security/server/admin/crud-table.js +603 -603
- package/dist/security/server/admin/icons.js +64 -64
- package/dist/security/server/admin/styles.js +942 -942
- package/dist/security/server/admin/templates.js +866 -866
- package/dist/types.d.ts +19 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +42 -4
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/aidb.win32-x64-msvc.node +0 -0
- package/dist/dev-plan-store.d.ts +0 -656
- package/dist/dev-plan-store.d.ts.map +0 -1
- package/dist/dev-plan-store.js +0 -1679
- package/dist/dev-plan-store.js.map +0 -1
- package/dist/migrate-federation-plan.d.ts +0 -16
- package/dist/migrate-federation-plan.d.ts.map +0 -1
- package/dist/migrate-federation-plan.js +0 -420
- package/dist/migrate-federation-plan.js.map +0 -1
- package/dist/social-graph.d.ts +0 -532
- package/dist/social-graph.d.ts.map +0 -1
- package/dist/social-graph.js +0 -997
- package/dist/social-graph.js.map +0 -1
- package/vibebase.node +0 -0
- package/vibebase.win32-x64-msvc.node +0 -0
package/dist/social-graph.js
DELETED
|
@@ -1,997 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* SocialGraph - High-level TypeScript API for social network operations
|
|
4
|
-
*
|
|
5
|
-
* Provides a friendly API wrapper around the native Rust social graph implementation.
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.SocialGraph = void 0;
|
|
9
|
-
/**
|
|
10
|
-
* SocialGraph provides high-level APIs for social network operations.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* const db = new AiFastDb({ path: './data', dimension: 768 });
|
|
15
|
-
* const social = new SocialGraph(db);
|
|
16
|
-
*
|
|
17
|
-
* // Add persons
|
|
18
|
-
* const alice = social.addPerson({ name: 'Alice' });
|
|
19
|
-
* const bob = social.addPerson({ name: 'Bob' });
|
|
20
|
-
*
|
|
21
|
-
* // Create friendship
|
|
22
|
-
* social.addFriend(alice.id, bob.id);
|
|
23
|
-
*
|
|
24
|
-
* // Find path between people
|
|
25
|
-
* const path = social.findPath(alice.id, someoneElse.id);
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
class SocialGraph {
|
|
29
|
-
constructor(db) {
|
|
30
|
-
// Access the native social graph through AiFastDb
|
|
31
|
-
this.native = db.socialGraph();
|
|
32
|
-
}
|
|
33
|
-
// ========================================================================
|
|
34
|
-
// Person Management
|
|
35
|
-
// ========================================================================
|
|
36
|
-
/**
|
|
37
|
-
* Add a new person to the social graph
|
|
38
|
-
*/
|
|
39
|
-
addPerson(input) {
|
|
40
|
-
return this.native.addPerson(input);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Get a person by ID
|
|
44
|
-
*/
|
|
45
|
-
getPerson(id) {
|
|
46
|
-
return this.native.getPerson(id) ?? null;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Update a person's information
|
|
50
|
-
*/
|
|
51
|
-
updatePerson(id, updates) {
|
|
52
|
-
return this.native.updatePerson(id, updates) ?? null;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Delete a person from the social graph
|
|
56
|
-
*/
|
|
57
|
-
deletePerson(id) {
|
|
58
|
-
return this.native.deletePerson(id);
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* List all persons with optional filter
|
|
62
|
-
*/
|
|
63
|
-
listPersons(filter) {
|
|
64
|
-
return this.native.listPersons(filter);
|
|
65
|
-
}
|
|
66
|
-
// ========================================================================
|
|
67
|
-
// Friend Relationships
|
|
68
|
-
// ========================================================================
|
|
69
|
-
/**
|
|
70
|
-
* Add a friend relationship between two persons
|
|
71
|
-
*/
|
|
72
|
-
addFriend(personA, personB, config) {
|
|
73
|
-
return this.native.addFriend(personA, personB, config) ?? null;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Remove a friend relationship
|
|
77
|
-
*/
|
|
78
|
-
removeFriend(personA, personB) {
|
|
79
|
-
return this.native.removeFriend(personA, personB);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Get all friends of a person
|
|
83
|
-
*/
|
|
84
|
-
getFriends(personId) {
|
|
85
|
-
return this.native.getFriends(personId);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Check if two persons are friends
|
|
89
|
-
*/
|
|
90
|
-
areFriends(personA, personB) {
|
|
91
|
-
return this.native.areFriends(personA, personB);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* List all relations with optional filter
|
|
95
|
-
*
|
|
96
|
-
* Returns all relation edges including friend relations, person-tag relations, etc.
|
|
97
|
-
* Each relation includes full metadata (relation_type, weight, bidirectional, metadata).
|
|
98
|
-
*
|
|
99
|
-
* @param filter - Optional filter criteria
|
|
100
|
-
* @returns Array of relations
|
|
101
|
-
*
|
|
102
|
-
* @example
|
|
103
|
-
* ```typescript
|
|
104
|
-
* // Get all relations
|
|
105
|
-
* const allRelations = social.listRelations();
|
|
106
|
-
*
|
|
107
|
-
* // Get only friend relations
|
|
108
|
-
* const friendRelations = social.listRelations({ relationType: 'friend' });
|
|
109
|
-
*
|
|
110
|
-
* // Get relations for a specific person
|
|
111
|
-
* const personRelations = social.listRelations({ sourceId: alice.id });
|
|
112
|
-
* ```
|
|
113
|
-
*/
|
|
114
|
-
listRelations(filter) {
|
|
115
|
-
// Try native method first
|
|
116
|
-
if (typeof this.native.listRelations === 'function') {
|
|
117
|
-
return this.native.listRelations(filter);
|
|
118
|
-
}
|
|
119
|
-
// Fallback: reconstruct relations from API calls
|
|
120
|
-
// Note: This fallback has limitations - it may not capture all metadata
|
|
121
|
-
const relations = [];
|
|
122
|
-
const seenEdges = new Set();
|
|
123
|
-
const now = Date.now();
|
|
124
|
-
const persons = this.listPersons();
|
|
125
|
-
for (const person of persons) {
|
|
126
|
-
// Get friend relations
|
|
127
|
-
const friends = this.getFriends(person.id);
|
|
128
|
-
for (const friend of friends) {
|
|
129
|
-
// Create unique edge ID (sorted to avoid duplicates)
|
|
130
|
-
const edgeId = [person.id, friend.id].sort().join('-');
|
|
131
|
-
if (!seenEdges.has(edgeId)) {
|
|
132
|
-
seenEdges.add(edgeId);
|
|
133
|
-
relations.push({
|
|
134
|
-
id: edgeId,
|
|
135
|
-
source: person.id,
|
|
136
|
-
target: friend.id,
|
|
137
|
-
relation_type: 'friend', // Default - actual type not available in fallback
|
|
138
|
-
weight: 1.0, // Default - actual weight not available in fallback
|
|
139
|
-
bidirectional: true,
|
|
140
|
-
metadata: {},
|
|
141
|
-
created_at: now,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// Get person-tag relations
|
|
146
|
-
const tags = this.getPersonTags(person.id);
|
|
147
|
-
for (const tag of tags) {
|
|
148
|
-
const edgeId = `${person.id}-tag-${tag.id}`;
|
|
149
|
-
if (!seenEdges.has(edgeId)) {
|
|
150
|
-
seenEdges.add(edgeId);
|
|
151
|
-
const props = tag.properties;
|
|
152
|
-
const isCompany = props?.tagType === 'company' || props?.category === 'company';
|
|
153
|
-
relations.push({
|
|
154
|
-
id: edgeId,
|
|
155
|
-
source: person.id,
|
|
156
|
-
target: tag.id,
|
|
157
|
-
relation_type: isCompany ? 'work_for' : 'tagged',
|
|
158
|
-
weight: 1.0,
|
|
159
|
-
bidirectional: false,
|
|
160
|
-
metadata: { tagType: props?.tagType },
|
|
161
|
-
created_at: now,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// Apply filters
|
|
167
|
-
let results = relations;
|
|
168
|
-
if (filter) {
|
|
169
|
-
if (filter.relationType) {
|
|
170
|
-
results = results.filter(r => r.relation_type === filter.relationType);
|
|
171
|
-
}
|
|
172
|
-
if (filter.sourceId) {
|
|
173
|
-
results = results.filter(r => r.source === filter.sourceId || r.target === filter.sourceId);
|
|
174
|
-
}
|
|
175
|
-
if (filter.targetId) {
|
|
176
|
-
results = results.filter(r => r.target === filter.targetId || r.source === filter.targetId);
|
|
177
|
-
}
|
|
178
|
-
if (filter.limit && filter.limit > 0) {
|
|
179
|
-
results = results.slice(0, filter.limit);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return results;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Get a specific relation by ID
|
|
186
|
-
*
|
|
187
|
-
* @param relationId - The relation ID
|
|
188
|
-
* @returns The relation if found, null otherwise
|
|
189
|
-
*/
|
|
190
|
-
getRelation(relationId) {
|
|
191
|
-
// Try native method first
|
|
192
|
-
if (typeof this.native.getRelation === 'function') {
|
|
193
|
-
return this.native.getRelation(relationId) ?? null;
|
|
194
|
-
}
|
|
195
|
-
// Fallback: search in listRelations
|
|
196
|
-
const relations = this.listRelations();
|
|
197
|
-
return relations.find(r => r.id === relationId) ?? null;
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Get relation between two specific entities
|
|
201
|
-
*
|
|
202
|
-
* @param entityA - First entity ID
|
|
203
|
-
* @param entityB - Second entity ID
|
|
204
|
-
* @returns The relation if found, null otherwise
|
|
205
|
-
*/
|
|
206
|
-
getRelationBetween(entityA, entityB) {
|
|
207
|
-
// Try native method first
|
|
208
|
-
if (typeof this.native.getRelationBetween === 'function') {
|
|
209
|
-
return this.native.getRelationBetween(entityA, entityB) ?? null;
|
|
210
|
-
}
|
|
211
|
-
// Fallback: search in listRelations
|
|
212
|
-
const relations = this.listRelations();
|
|
213
|
-
return relations.find(r => (r.source === entityA && r.target === entityB) ||
|
|
214
|
-
(r.source === entityB && r.target === entityA)) ?? null;
|
|
215
|
-
}
|
|
216
|
-
// ========================================================================
|
|
217
|
-
// Tag Management
|
|
218
|
-
// ========================================================================
|
|
219
|
-
/**
|
|
220
|
-
* Add a new tag
|
|
221
|
-
*/
|
|
222
|
-
addTag(input) {
|
|
223
|
-
return this.native.addTag(input);
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Tag a person (add person to a tag/organization)
|
|
227
|
-
*/
|
|
228
|
-
tagPerson(personId, tagId) {
|
|
229
|
-
return this.native.tagPerson(personId, tagId) ?? null;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Remove tag from person
|
|
233
|
-
*/
|
|
234
|
-
untagPerson(personId, tagId) {
|
|
235
|
-
return this.native.untagPerson(personId, tagId);
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Get all tags of a person
|
|
239
|
-
*/
|
|
240
|
-
getPersonTags(personId) {
|
|
241
|
-
return this.native.getPersonTags(personId);
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Get all members of a tag
|
|
245
|
-
*/
|
|
246
|
-
getTagMembers(tagId) {
|
|
247
|
-
return this.native.getTagMembers(tagId);
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* List all tags with optional filter
|
|
251
|
-
*
|
|
252
|
-
* Returns all tag entities (including company, organization, skill, interest types).
|
|
253
|
-
* Use the filter to narrow down results by tagType or name.
|
|
254
|
-
*
|
|
255
|
-
* @param filter - Optional filter criteria
|
|
256
|
-
* @returns Array of tag entities
|
|
257
|
-
*
|
|
258
|
-
* @example
|
|
259
|
-
* ```typescript
|
|
260
|
-
* // Get all tags
|
|
261
|
-
* const allTags = social.listTags();
|
|
262
|
-
*
|
|
263
|
-
* // Get only companies
|
|
264
|
-
* const companies = social.listTags({ tagType: 'company' });
|
|
265
|
-
*
|
|
266
|
-
* // Get tags with name containing 'tech'
|
|
267
|
-
* const techTags = social.listTags({ name: 'tech' });
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
listTags(filter) {
|
|
271
|
-
// Try native method first
|
|
272
|
-
if (typeof this.native.listTags === 'function') {
|
|
273
|
-
return this.native.listTags(filter);
|
|
274
|
-
}
|
|
275
|
-
// Fallback: collect tags from all persons (may miss orphan tags)
|
|
276
|
-
const tagMap = new Map();
|
|
277
|
-
const persons = this.listPersons();
|
|
278
|
-
for (const person of persons) {
|
|
279
|
-
const tags = this.getPersonTags(person.id);
|
|
280
|
-
for (const tag of tags) {
|
|
281
|
-
if (!tagMap.has(tag.id)) {
|
|
282
|
-
tagMap.set(tag.id, tag);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
let results = Array.from(tagMap.values());
|
|
287
|
-
// Apply filters
|
|
288
|
-
if (filter) {
|
|
289
|
-
if (filter.tagType) {
|
|
290
|
-
results = results.filter(t => {
|
|
291
|
-
const props = t.properties;
|
|
292
|
-
return props?.tagType === filter.tagType;
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
if (filter.name) {
|
|
296
|
-
const nameLower = filter.name.toLowerCase();
|
|
297
|
-
results = results.filter(t => t.name.toLowerCase().includes(nameLower));
|
|
298
|
-
}
|
|
299
|
-
if (filter.limit && filter.limit > 0) {
|
|
300
|
-
results = results.slice(0, filter.limit);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return results;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Get a tag by ID
|
|
307
|
-
*/
|
|
308
|
-
getTag(tagId) {
|
|
309
|
-
// Try native method first
|
|
310
|
-
if (typeof this.native.getTag === 'function') {
|
|
311
|
-
return this.native.getTag(tagId) ?? null;
|
|
312
|
-
}
|
|
313
|
-
// Fallback: search in listTags
|
|
314
|
-
const tags = this.listTags();
|
|
315
|
-
return tags.find(t => t.id === tagId) ?? null;
|
|
316
|
-
}
|
|
317
|
-
// ========================================================================
|
|
318
|
-
// Item Management
|
|
319
|
-
// ========================================================================
|
|
320
|
-
/**
|
|
321
|
-
* Add a new item
|
|
322
|
-
*/
|
|
323
|
-
addItem(input) {
|
|
324
|
-
return this.native.addItem(input);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Add item to person (ownership)
|
|
328
|
-
*/
|
|
329
|
-
addItemToPerson(personId, itemId, relation) {
|
|
330
|
-
return this.native.addItemToPerson(personId, itemId, relation) ?? null;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Get all items owned by a person
|
|
334
|
-
*/
|
|
335
|
-
getPersonItems(personId) {
|
|
336
|
-
return this.native.getPersonItems(personId);
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Get all owners of an item
|
|
340
|
-
*/
|
|
341
|
-
getItemOwners(itemId) {
|
|
342
|
-
return this.native.getItemOwners(itemId);
|
|
343
|
-
}
|
|
344
|
-
// ========================================================================
|
|
345
|
-
// Attribute Management
|
|
346
|
-
// ========================================================================
|
|
347
|
-
/**
|
|
348
|
-
* Add a new attribute
|
|
349
|
-
*/
|
|
350
|
-
addAttribute(input) {
|
|
351
|
-
return this.native.addAttribute(input);
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Find or create an attribute by category and value
|
|
355
|
-
*/
|
|
356
|
-
findOrCreateAttribute(category, value) {
|
|
357
|
-
return this.native.findOrCreateAttribute(category, value);
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Set a person's attribute
|
|
361
|
-
*/
|
|
362
|
-
setPersonAttribute(personId, attrId, relation) {
|
|
363
|
-
return this.native.setPersonAttribute(personId, attrId, relation) ?? null;
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Get all attributes of a person
|
|
367
|
-
*/
|
|
368
|
-
getPersonAttributes(personId) {
|
|
369
|
-
return this.native.getPersonAttributes(personId);
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Get all persons with a specific attribute
|
|
373
|
-
*/
|
|
374
|
-
getPersonsByAttribute(attrId) {
|
|
375
|
-
return this.native.getPersonsByAttribute(attrId);
|
|
376
|
-
}
|
|
377
|
-
// ========================================================================
|
|
378
|
-
// Path Finding (Person-to-Person)
|
|
379
|
-
// ========================================================================
|
|
380
|
-
/**
|
|
381
|
-
* Find the shortest path between two persons
|
|
382
|
-
*
|
|
383
|
-
* @example
|
|
384
|
-
* ```typescript
|
|
385
|
-
* const path = social.findPath(alice.id, bob.id);
|
|
386
|
-
* if (path) {
|
|
387
|
-
* console.log(`Found path with ${path.hops} hops`);
|
|
388
|
-
* console.log('Intermediaries:', path.intermediaries.map(p => p.name));
|
|
389
|
-
* }
|
|
390
|
-
* ```
|
|
391
|
-
*/
|
|
392
|
-
findPath(fromId, toId, options) {
|
|
393
|
-
return this.native.findPath(fromId, toId, options) ?? null;
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
|
-
* Find all paths between two persons
|
|
397
|
-
*/
|
|
398
|
-
findAllPaths(fromId, toId, maxHops, maxPaths) {
|
|
399
|
-
return this.native.findAllPaths(fromId, toId, maxHops, maxPaths);
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Find all intermediaries who can introduce two persons
|
|
403
|
-
*
|
|
404
|
-
* @example
|
|
405
|
-
* ```typescript
|
|
406
|
-
* const intermediaries = social.findIntermediaries(alice.id, bob.id);
|
|
407
|
-
* console.log('Can be introduced via:', intermediaries.map(p => p.name));
|
|
408
|
-
* ```
|
|
409
|
-
*/
|
|
410
|
-
findIntermediaries(personA, personB, maxHops) {
|
|
411
|
-
return this.native.findIntermediaries(personA, personB, maxHops);
|
|
412
|
-
}
|
|
413
|
-
// ========================================================================
|
|
414
|
-
// Network Analysis
|
|
415
|
-
// ========================================================================
|
|
416
|
-
/**
|
|
417
|
-
* Get N-degree contacts of a person
|
|
418
|
-
*
|
|
419
|
-
* @example
|
|
420
|
-
* ```typescript
|
|
421
|
-
* const contacts = social.getNthDegreeContacts(alice.id, 3);
|
|
422
|
-
* console.log('Direct friends:', contacts.degree1.length);
|
|
423
|
-
* console.log('Friends of friends:', contacts.degree2.length);
|
|
424
|
-
* console.log('3rd degree:', contacts.degree3.length);
|
|
425
|
-
* ```
|
|
426
|
-
*/
|
|
427
|
-
getNthDegreeContacts(personId, maxDegree) {
|
|
428
|
-
return this.native.getNthDegreeContacts(personId, maxDegree);
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Get mutual friends between two persons
|
|
432
|
-
*/
|
|
433
|
-
getMutualFriends(personA, personB) {
|
|
434
|
-
return this.native.getMutualFriends(personA, personB);
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Get mutual tags between two persons
|
|
438
|
-
*/
|
|
439
|
-
getMutualTags(personA, personB) {
|
|
440
|
-
return this.native.getMutualTags(personA, personB);
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* Calculate relationship strength between two persons
|
|
444
|
-
*/
|
|
445
|
-
getRelationshipStrength(personA, personB) {
|
|
446
|
-
return this.native.getRelationshipStrength(personA, personB);
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Get connection suggestions for a person
|
|
450
|
-
*
|
|
451
|
-
* @example
|
|
452
|
-
* ```typescript
|
|
453
|
-
* const suggestions = social.suggestConnections(alice.id, {
|
|
454
|
-
* maxResults: 10,
|
|
455
|
-
* minScore: 0.3,
|
|
456
|
-
* });
|
|
457
|
-
*
|
|
458
|
-
* for (const s of suggestions) {
|
|
459
|
-
* console.log(`Suggest: ${s.person.name} (score: ${s.score})`);
|
|
460
|
-
* for (const reason of s.reasons) {
|
|
461
|
-
* console.log(` - ${reason.type}`);
|
|
462
|
-
* }
|
|
463
|
-
* }
|
|
464
|
-
* ```
|
|
465
|
-
*/
|
|
466
|
-
suggestConnections(personId, config) {
|
|
467
|
-
return this.native.suggestConnections(personId, config);
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Get network statistics for a person
|
|
471
|
-
*/
|
|
472
|
-
getNetworkStats(personId) {
|
|
473
|
-
return this.native.getNetworkStats(personId);
|
|
474
|
-
}
|
|
475
|
-
// ========================================================================
|
|
476
|
-
// Item Matching
|
|
477
|
-
// ========================================================================
|
|
478
|
-
/**
|
|
479
|
-
* Find shared items between two people
|
|
480
|
-
*/
|
|
481
|
-
findSharedItems(personA, personB) {
|
|
482
|
-
return this.native.findSharedItems(personA, personB);
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Find people who share items with a given person
|
|
486
|
-
*
|
|
487
|
-
* @example
|
|
488
|
-
* ```typescript
|
|
489
|
-
* const carFriends = social.findPeopleBySharedItems(alice.id, 'vehicle');
|
|
490
|
-
* for (const match of carFriends) {
|
|
491
|
-
* console.log(`${match.person.name} shares ${match.sharedItems.length} items`);
|
|
492
|
-
* }
|
|
493
|
-
* ```
|
|
494
|
-
*/
|
|
495
|
-
findPeopleBySharedItems(personId, category) {
|
|
496
|
-
return this.native.findPeopleBySharedItems(personId, category);
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* Find people who own items of a specific brand
|
|
500
|
-
*/
|
|
501
|
-
findPeopleByBrand(brand, category) {
|
|
502
|
-
return this.native.findPeopleByBrand(brand, category);
|
|
503
|
-
}
|
|
504
|
-
/**
|
|
505
|
-
* Get popular items (most owned)
|
|
506
|
-
*/
|
|
507
|
-
getPopularItems(category, limit) {
|
|
508
|
-
return this.native.getPopularItems(category, limit);
|
|
509
|
-
}
|
|
510
|
-
// ========================================================================
|
|
511
|
-
// Attribute Matching
|
|
512
|
-
// ========================================================================
|
|
513
|
-
/**
|
|
514
|
-
* Find shared attributes between two people
|
|
515
|
-
*/
|
|
516
|
-
findSharedAttributes(personA, personB) {
|
|
517
|
-
return this.native.findSharedAttributes(personA, personB);
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Find people who share attributes with a given person
|
|
521
|
-
*/
|
|
522
|
-
findPeopleBySharedAttributes(personId, config) {
|
|
523
|
-
return this.native.findPeopleBySharedAttributes(personId, config);
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Find alumni (people who went to the same school)
|
|
527
|
-
*/
|
|
528
|
-
findAlumni(personId) {
|
|
529
|
-
return this.native.findAlumni(personId);
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Find people in the same city
|
|
533
|
-
*/
|
|
534
|
-
findSameCity(personId) {
|
|
535
|
-
return this.native.findSameCity(personId);
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Find people with the same zodiac sign
|
|
539
|
-
*/
|
|
540
|
-
findSameZodiac(personId) {
|
|
541
|
-
return this.native.findSameZodiac(personId);
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Analyze compatibility between two people
|
|
545
|
-
*
|
|
546
|
-
* @example
|
|
547
|
-
* ```typescript
|
|
548
|
-
* const compat = social.analyzeCompatibility(alice.id, bob.id);
|
|
549
|
-
* console.log(`Compatibility: ${(compat.overallScore * 100).toFixed(0)}%`);
|
|
550
|
-
* console.log(compat.analysis);
|
|
551
|
-
* ```
|
|
552
|
-
*/
|
|
553
|
-
analyzeCompatibility(personA, personB) {
|
|
554
|
-
return this.native.analyzeCompatibility(personA, personB);
|
|
555
|
-
}
|
|
556
|
-
/**
|
|
557
|
-
* Get popular attributes in a category
|
|
558
|
-
*/
|
|
559
|
-
getPopularAttributes(category, limit) {
|
|
560
|
-
return this.native.getPopularAttributes(category, limit);
|
|
561
|
-
}
|
|
562
|
-
// ========================================================================
|
|
563
|
-
// Birthday Management
|
|
564
|
-
// ========================================================================
|
|
565
|
-
/**
|
|
566
|
-
* Set a person's birthday (solar calendar, YYYY-MM-DD format)
|
|
567
|
-
*
|
|
568
|
-
* @param personId - The person's ID
|
|
569
|
-
* @param birthday - Birthday in YYYY-MM-DD format (e.g., "1990-05-15")
|
|
570
|
-
* @returns true if set successfully, false if person not found or invalid format
|
|
571
|
-
*
|
|
572
|
-
* @example
|
|
573
|
-
* ```typescript
|
|
574
|
-
* social.setBirthday(alice.id, '1990-05-15');
|
|
575
|
-
* ```
|
|
576
|
-
*/
|
|
577
|
-
setBirthday(personId, birthday) {
|
|
578
|
-
return this.native.setBirthday(personId, birthday);
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* Get a person's birthday
|
|
582
|
-
*
|
|
583
|
-
* @returns Birthday in YYYY-MM-DD format, or null if not set
|
|
584
|
-
*/
|
|
585
|
-
getBirthday(personId) {
|
|
586
|
-
return this.native.getBirthday(personId) ?? null;
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* Remove a person's birthday
|
|
590
|
-
*/
|
|
591
|
-
removeBirthday(personId) {
|
|
592
|
-
return this.native.removeBirthday(personId);
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Find people with exact same birthday (same year-month-day)
|
|
596
|
-
*
|
|
597
|
-
* @param birthday - Birthday in YYYY-MM-DD format
|
|
598
|
-
*
|
|
599
|
-
* @example
|
|
600
|
-
* ```typescript
|
|
601
|
-
* const sameBirthday = social.findSameBirthdayExact('1990-05-15');
|
|
602
|
-
* // Returns people born on May 15, 1990
|
|
603
|
-
* ```
|
|
604
|
-
*/
|
|
605
|
-
findSameBirthdayExact(birthday) {
|
|
606
|
-
return this.native.findSameBirthdayExact(birthday);
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Find people with same month-day birthday (different years allowed)
|
|
610
|
-
*
|
|
611
|
-
* @param birthday - Birthday in YYYY-MM-DD or MM-DD format
|
|
612
|
-
*
|
|
613
|
-
* @example
|
|
614
|
-
* ```typescript
|
|
615
|
-
* const sameDayMonth = social.findSameBirthdayDayMonth('05-15');
|
|
616
|
-
* // Returns all people born on May 15 (any year)
|
|
617
|
-
* ```
|
|
618
|
-
*/
|
|
619
|
-
findSameBirthdayDayMonth(birthday) {
|
|
620
|
-
return this.native.findSameBirthdayDayMonth(birthday);
|
|
621
|
-
}
|
|
622
|
-
/**
|
|
623
|
-
* Find people with same birthday as a given person (exact match)
|
|
624
|
-
*
|
|
625
|
-
* @example
|
|
626
|
-
* ```typescript
|
|
627
|
-
* const twins = social.findSameBirthdayAsPersonExact(alice.id);
|
|
628
|
-
* // Returns people born on the exact same date as Alice
|
|
629
|
-
* ```
|
|
630
|
-
*/
|
|
631
|
-
findSameBirthdayAsPersonExact(personId) {
|
|
632
|
-
return this.native.findSameBirthdayAsPersonExact(personId);
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* Find people with same month-day birthday as a given person
|
|
636
|
-
*
|
|
637
|
-
* @example
|
|
638
|
-
* ```typescript
|
|
639
|
-
* const sameDayPeople = social.findSameBirthdayAsPerson(alice.id);
|
|
640
|
-
* // Returns people who share Alice's birthday month and day
|
|
641
|
-
* ```
|
|
642
|
-
*/
|
|
643
|
-
findSameBirthdayAsPerson(personId) {
|
|
644
|
-
return this.native.findSameBirthdayAsPerson(personId);
|
|
645
|
-
}
|
|
646
|
-
/**
|
|
647
|
-
* Recommend birthday matches with priority: exact > same_day_month
|
|
648
|
-
*
|
|
649
|
-
* @example
|
|
650
|
-
* ```typescript
|
|
651
|
-
* const recommendations = social.recommendBirthdayMatches(alice.id, 10);
|
|
652
|
-
* for (const match of recommendations) {
|
|
653
|
-
* console.log(`${match.person.name}: ${match.birthday} (${match.matchType})`);
|
|
654
|
-
* }
|
|
655
|
-
* ```
|
|
656
|
-
*/
|
|
657
|
-
recommendBirthdayMatches(personId, limit) {
|
|
658
|
-
return this.native.recommendBirthdayMatches(personId, limit);
|
|
659
|
-
}
|
|
660
|
-
/**
|
|
661
|
-
* Find people with birthdays in the next N days
|
|
662
|
-
*
|
|
663
|
-
* @example
|
|
664
|
-
* ```typescript
|
|
665
|
-
* const upcoming = social.findUpcomingBirthdays(7);
|
|
666
|
-
* // Returns people with birthdays in the next 7 days
|
|
667
|
-
* ```
|
|
668
|
-
*/
|
|
669
|
-
findUpcomingBirthdays(days) {
|
|
670
|
-
return this.native.findUpcomingBirthdays(days);
|
|
671
|
-
}
|
|
672
|
-
/**
|
|
673
|
-
* Find people with birthdays today
|
|
674
|
-
*/
|
|
675
|
-
findTodayBirthdays() {
|
|
676
|
-
return this.native.findTodayBirthdays();
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* Find people with birthdays in a specific month
|
|
680
|
-
*
|
|
681
|
-
* @param month - Month number (1-12)
|
|
682
|
-
*/
|
|
683
|
-
findBirthdaysInMonth(month) {
|
|
684
|
-
return this.native.findBirthdaysInMonth(month);
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Get birthday statistics
|
|
688
|
-
*
|
|
689
|
-
* @example
|
|
690
|
-
* ```typescript
|
|
691
|
-
* const stats = social.getBirthdayStats();
|
|
692
|
-
* console.log(`Total: ${stats.totalWithBirthday}`);
|
|
693
|
-
* console.log('Most common dates:', stats.mostCommonDates);
|
|
694
|
-
* ```
|
|
695
|
-
*/
|
|
696
|
-
getBirthdayStats() {
|
|
697
|
-
return this.native.getBirthdayStats();
|
|
698
|
-
}
|
|
699
|
-
/**
|
|
700
|
-
* Check if two people have the same birthday
|
|
701
|
-
*
|
|
702
|
-
* @param exact - If true, checks for same year-month-day. If false, same month-day only.
|
|
703
|
-
*
|
|
704
|
-
* @example
|
|
705
|
-
* ```typescript
|
|
706
|
-
* // Check if same year-month-day
|
|
707
|
-
* const exactSame = social.isSameBirthday(alice.id, bob.id, true);
|
|
708
|
-
*
|
|
709
|
-
* // Check if same month-day (different years allowed)
|
|
710
|
-
* const sameDayMonth = social.isSameBirthday(alice.id, bob.id, false);
|
|
711
|
-
* ```
|
|
712
|
-
*/
|
|
713
|
-
isSameBirthday(personId1, personId2, exact) {
|
|
714
|
-
return this.native.isSameBirthday(personId1, personId2, exact);
|
|
715
|
-
}
|
|
716
|
-
/**
|
|
717
|
-
* Rebuild birthday index from all persons
|
|
718
|
-
*
|
|
719
|
-
* Call this after loading data to rebuild the in-memory index.
|
|
720
|
-
*/
|
|
721
|
-
rebuildBirthdayIndex() {
|
|
722
|
-
this.native.rebuildBirthdayIndex();
|
|
723
|
-
}
|
|
724
|
-
// ========================================================================
|
|
725
|
-
// Graph Export (for visualization)
|
|
726
|
-
// ========================================================================
|
|
727
|
-
/**
|
|
728
|
-
* Export the entire social graph for visualization
|
|
729
|
-
*
|
|
730
|
-
* Returns nodes (persons, companies, tags) and edges (friend relations, person-tag relations)
|
|
731
|
-
* in a format suitable for vis-network or similar graph visualization libraries.
|
|
732
|
-
*
|
|
733
|
-
* @param options - Export options for filtering and limiting results
|
|
734
|
-
* @returns Exported graph data with nodes, edges, and statistics
|
|
735
|
-
*
|
|
736
|
-
* @example
|
|
737
|
-
* ```typescript
|
|
738
|
-
* const graph = social.exportGraph();
|
|
739
|
-
* console.log(`Nodes: ${graph.nodes.length}, Edges: ${graph.edges.length}`);
|
|
740
|
-
* console.log(`Stats:`, graph.stats);
|
|
741
|
-
*
|
|
742
|
-
* // With options
|
|
743
|
-
* const filteredGraph = social.exportGraph({
|
|
744
|
-
* maxNodes: 100,
|
|
745
|
-
* includeTags: true,
|
|
746
|
-
* includeCompanies: true,
|
|
747
|
-
* });
|
|
748
|
-
* ```
|
|
749
|
-
*/
|
|
750
|
-
exportGraph(options) {
|
|
751
|
-
// Try native method first (high-performance Rust implementation)
|
|
752
|
-
if (typeof this.native.exportGraph === 'function') {
|
|
753
|
-
const nativeOptions = options ? {
|
|
754
|
-
max_nodes: options.maxNodes,
|
|
755
|
-
max_edges: options.maxEdges,
|
|
756
|
-
include_tags: options.includeTags,
|
|
757
|
-
include_companies: options.includeCompanies,
|
|
758
|
-
include_edge_meta: options.includeEdgeMeta,
|
|
759
|
-
include_node_degree: options.includeNodeDegree,
|
|
760
|
-
relation_types: options.relationTypes,
|
|
761
|
-
} : undefined;
|
|
762
|
-
const result = this.native.exportGraph(nativeOptions);
|
|
763
|
-
// Transform from snake_case to camelCase if needed
|
|
764
|
-
return {
|
|
765
|
-
nodes: result.nodes.map((n) => ({
|
|
766
|
-
id: n.id,
|
|
767
|
-
label: n.label,
|
|
768
|
-
group: n.group,
|
|
769
|
-
title: n.title,
|
|
770
|
-
degree: n.degree,
|
|
771
|
-
data: n.data,
|
|
772
|
-
})),
|
|
773
|
-
edges: result.edges.map((e) => ({
|
|
774
|
-
id: e.id,
|
|
775
|
-
from: e.from,
|
|
776
|
-
to: e.to,
|
|
777
|
-
label: e.label,
|
|
778
|
-
relationType: e.relation_type,
|
|
779
|
-
weight: e.weight,
|
|
780
|
-
data: e.data,
|
|
781
|
-
})),
|
|
782
|
-
stats: {
|
|
783
|
-
persons: result.stats.persons,
|
|
784
|
-
companies: result.stats.companies,
|
|
785
|
-
tags: result.stats.tags,
|
|
786
|
-
relations: result.stats.relations,
|
|
787
|
-
},
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
|
-
// Fallback: TypeScript implementation
|
|
791
|
-
const opts = {
|
|
792
|
-
maxNodes: options?.maxNodes ?? 500,
|
|
793
|
-
includeTags: options?.includeTags ?? true,
|
|
794
|
-
includeCompanies: options?.includeCompanies ?? true,
|
|
795
|
-
includeEdgeMeta: options?.includeEdgeMeta ?? true,
|
|
796
|
-
relationTypes: options?.relationTypes,
|
|
797
|
-
};
|
|
798
|
-
const nodes = [];
|
|
799
|
-
const edges = [];
|
|
800
|
-
const personIds = new Set();
|
|
801
|
-
const tagIds = new Set();
|
|
802
|
-
const edgeIds = new Set();
|
|
803
|
-
// Helper: determine if a tag is a company
|
|
804
|
-
const isCompanyTag = (tag) => {
|
|
805
|
-
const props = tag.properties;
|
|
806
|
-
return props?.tagType === 'company' || props?.category === 'company';
|
|
807
|
-
};
|
|
808
|
-
// Helper: get node group for a tag
|
|
809
|
-
const getTagGroup = (tag) => {
|
|
810
|
-
return isCompanyTag(tag) ? 'company' : 'tag';
|
|
811
|
-
};
|
|
812
|
-
// Helper: get edge label based on relation type
|
|
813
|
-
const getEdgeLabel = (relationType) => {
|
|
814
|
-
const labels = {
|
|
815
|
-
friend: '好友',
|
|
816
|
-
knows: '认识',
|
|
817
|
-
colleague: '同事',
|
|
818
|
-
classmate: '同学',
|
|
819
|
-
family: '家人',
|
|
820
|
-
mentor: '导师',
|
|
821
|
-
tagged: '标签',
|
|
822
|
-
work_for: '就职于',
|
|
823
|
-
};
|
|
824
|
-
return labels[relationType] || relationType;
|
|
825
|
-
};
|
|
826
|
-
let nodeCount = 0;
|
|
827
|
-
// 1. Get all persons and add person nodes
|
|
828
|
-
const persons = this.listPersons();
|
|
829
|
-
for (const person of persons) {
|
|
830
|
-
if (opts.maxNodes && nodeCount >= opts.maxNodes)
|
|
831
|
-
break;
|
|
832
|
-
const props = person.properties;
|
|
833
|
-
nodes.push({
|
|
834
|
-
id: person.id,
|
|
835
|
-
label: person.name,
|
|
836
|
-
group: 'person',
|
|
837
|
-
title: props?.description || person.name,
|
|
838
|
-
data: {
|
|
839
|
-
type: 'person',
|
|
840
|
-
name: person.name,
|
|
841
|
-
avatar: props?.avatar,
|
|
842
|
-
phone: props?.phone,
|
|
843
|
-
email: props?.email,
|
|
844
|
-
wechat: props?.wechat,
|
|
845
|
-
position: props?.position,
|
|
846
|
-
description: props?.description,
|
|
847
|
-
...props,
|
|
848
|
-
},
|
|
849
|
-
});
|
|
850
|
-
personIds.add(person.id);
|
|
851
|
-
nodeCount++;
|
|
852
|
-
}
|
|
853
|
-
// 2. Get all tags (using listTags to include orphan tags)
|
|
854
|
-
const allTags = this.listTags();
|
|
855
|
-
for (const tag of allTags) {
|
|
856
|
-
if (opts.maxNodes && nodeCount >= opts.maxNodes)
|
|
857
|
-
break;
|
|
858
|
-
const tagGroup = getTagGroup(tag);
|
|
859
|
-
// Check if we should include this tag type
|
|
860
|
-
if (tagGroup === 'company' && !opts.includeCompanies)
|
|
861
|
-
continue;
|
|
862
|
-
if (tagGroup === 'tag' && !opts.includeTags)
|
|
863
|
-
continue;
|
|
864
|
-
const props = tag.properties;
|
|
865
|
-
nodes.push({
|
|
866
|
-
id: tag.id,
|
|
867
|
-
label: tag.name,
|
|
868
|
-
group: tagGroup,
|
|
869
|
-
title: props?.description || tag.name,
|
|
870
|
-
data: {
|
|
871
|
-
type: tagGroup,
|
|
872
|
-
name: tag.name,
|
|
873
|
-
tagType: props?.tagType,
|
|
874
|
-
category: props?.category,
|
|
875
|
-
color: props?.color,
|
|
876
|
-
industry: props?.industry,
|
|
877
|
-
description: props?.description,
|
|
878
|
-
...props,
|
|
879
|
-
},
|
|
880
|
-
});
|
|
881
|
-
tagIds.add(tag.id);
|
|
882
|
-
nodeCount++;
|
|
883
|
-
}
|
|
884
|
-
// 3. Get all relations (using listRelations to get full metadata)
|
|
885
|
-
const allRelations = this.listRelations();
|
|
886
|
-
for (const relation of allRelations) {
|
|
887
|
-
// Check relation type filter
|
|
888
|
-
if (opts.relationTypes && !opts.relationTypes.includes(relation.relation_type))
|
|
889
|
-
continue;
|
|
890
|
-
// Skip edges to/from nodes not in our node set
|
|
891
|
-
const sourceInNodes = personIds.has(relation.source) || tagIds.has(relation.source);
|
|
892
|
-
const targetInNodes = personIds.has(relation.target) || tagIds.has(relation.target);
|
|
893
|
-
if (!sourceInNodes || !targetInNodes)
|
|
894
|
-
continue;
|
|
895
|
-
// Skip duplicate edges (for bidirectional relations)
|
|
896
|
-
const edgeKey = [relation.source, relation.target].sort().join('-');
|
|
897
|
-
if (edgeIds.has(edgeKey))
|
|
898
|
-
continue;
|
|
899
|
-
edgeIds.add(edgeKey);
|
|
900
|
-
edges.push({
|
|
901
|
-
id: relation.id,
|
|
902
|
-
from: relation.source,
|
|
903
|
-
to: relation.target,
|
|
904
|
-
label: getEdgeLabel(relation.relation_type),
|
|
905
|
-
relationType: relation.relation_type,
|
|
906
|
-
weight: relation.weight,
|
|
907
|
-
data: opts.includeEdgeMeta ? {
|
|
908
|
-
bidirectional: relation.bidirectional,
|
|
909
|
-
...relation.metadata,
|
|
910
|
-
} : undefined,
|
|
911
|
-
});
|
|
912
|
-
}
|
|
913
|
-
// 4. Calculate statistics
|
|
914
|
-
const companyCount = allTags.filter(isCompanyTag).length;
|
|
915
|
-
const tagCount = allTags.length - companyCount;
|
|
916
|
-
const stats = {
|
|
917
|
-
persons: persons.length,
|
|
918
|
-
companies: opts.includeCompanies ? companyCount : 0,
|
|
919
|
-
tags: opts.includeTags ? tagCount : 0,
|
|
920
|
-
relations: edges.length,
|
|
921
|
-
};
|
|
922
|
-
return { nodes, edges, stats };
|
|
923
|
-
}
|
|
924
|
-
// ========================================================================
|
|
925
|
-
// Persistence
|
|
926
|
-
// ========================================================================
|
|
927
|
-
/**
|
|
928
|
-
* Save changes to disk
|
|
929
|
-
*/
|
|
930
|
-
save() {
|
|
931
|
-
this.native.save();
|
|
932
|
-
}
|
|
933
|
-
// ========================================================================
|
|
934
|
-
// Diagnostics
|
|
935
|
-
// ========================================================================
|
|
936
|
-
/**
|
|
937
|
-
* Diagnose WAL recovery and database state
|
|
938
|
-
*
|
|
939
|
-
* Returns diagnostic information about the database including:
|
|
940
|
-
* - Current entity/relation counts
|
|
941
|
-
* - Shard information
|
|
942
|
-
* - Recovery status
|
|
943
|
-
*
|
|
944
|
-
* @example
|
|
945
|
-
* ```typescript
|
|
946
|
-
* const diag = social.diagnose();
|
|
947
|
-
* console.log('Counts:', diag.counts);
|
|
948
|
-
* console.log('Message:', diag.message);
|
|
949
|
-
* ```
|
|
950
|
-
*/
|
|
951
|
-
diagnose() {
|
|
952
|
-
if (typeof this.native.diagnose === 'function') {
|
|
953
|
-
return this.native.diagnose();
|
|
954
|
-
}
|
|
955
|
-
// Fallback for older versions
|
|
956
|
-
const persons = this.listPersons();
|
|
957
|
-
const tags = this.listTags();
|
|
958
|
-
const relations = this.listRelations();
|
|
959
|
-
return {
|
|
960
|
-
status: 'ok',
|
|
961
|
-
counts: {
|
|
962
|
-
persons: persons.length,
|
|
963
|
-
tags: tags.length,
|
|
964
|
-
relations: relations.length,
|
|
965
|
-
},
|
|
966
|
-
shards: { count: 0 },
|
|
967
|
-
message: `Fallback diagnose: ${persons.length} persons, ${tags.length} tags, ${relations.length} relations`,
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
/**
|
|
971
|
-
* Force re-recover from WAL files
|
|
972
|
-
*
|
|
973
|
-
* This can be used to reload data from WAL if the initial recovery failed.
|
|
974
|
-
*
|
|
975
|
-
* @example
|
|
976
|
-
* ```typescript
|
|
977
|
-
* const result = social.recover();
|
|
978
|
-
* if (result.success) {
|
|
979
|
-
* console.log('Recovered:', result.counts);
|
|
980
|
-
* } else {
|
|
981
|
-
* console.error('Recovery failed:', result.error);
|
|
982
|
-
* }
|
|
983
|
-
* ```
|
|
984
|
-
*/
|
|
985
|
-
recover() {
|
|
986
|
-
if (typeof this.native.recover === 'function') {
|
|
987
|
-
return this.native.recover();
|
|
988
|
-
}
|
|
989
|
-
return {
|
|
990
|
-
success: false,
|
|
991
|
-
error: 'Native recover method not available',
|
|
992
|
-
};
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
exports.SocialGraph = SocialGraph;
|
|
996
|
-
exports.default = SocialGraph;
|
|
997
|
-
//# sourceMappingURL=social-graph.js.map
|