@soulcraft/brainy 5.11.1 → 6.0.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +155 -5
  2. package/README.md +2 -6
  3. package/dist/api/DataAPI.d.ts +0 -40
  4. package/dist/api/DataAPI.js +0 -235
  5. package/dist/brainy.d.ts +28 -106
  6. package/dist/brainy.js +53 -370
  7. package/dist/cli/commands/cow.d.ts +1 -9
  8. package/dist/cli/commands/cow.js +1 -61
  9. package/dist/cli/commands/data.d.ts +1 -13
  10. package/dist/cli/commands/data.js +1 -74
  11. package/dist/cli/index.js +1 -16
  12. package/dist/neural/embeddedTypeEmbeddings.d.ts +1 -1
  13. package/dist/neural/embeddedTypeEmbeddings.js +2 -2
  14. package/dist/storage/adapters/azureBlobStorage.d.ts +21 -7
  15. package/dist/storage/adapters/azureBlobStorage.js +69 -14
  16. package/dist/storage/adapters/fileSystemStorage.js +2 -1
  17. package/dist/storage/adapters/gcsStorage.d.ts +29 -15
  18. package/dist/storage/adapters/gcsStorage.js +82 -27
  19. package/dist/storage/adapters/historicalStorageAdapter.js +2 -2
  20. package/dist/storage/adapters/memoryStorage.d.ts +1 -1
  21. package/dist/storage/adapters/memoryStorage.js +9 -11
  22. package/dist/storage/adapters/opfsStorage.js +2 -1
  23. package/dist/storage/adapters/r2Storage.d.ts +21 -10
  24. package/dist/storage/adapters/r2Storage.js +73 -17
  25. package/dist/storage/adapters/s3CompatibleStorage.d.ts +20 -7
  26. package/dist/storage/adapters/s3CompatibleStorage.js +72 -14
  27. package/dist/storage/baseStorage.d.ts +153 -24
  28. package/dist/storage/baseStorage.js +758 -459
  29. package/dist/vfs/PathResolver.js +6 -2
  30. package/dist/vfs/VirtualFileSystem.d.ts +46 -24
  31. package/dist/vfs/VirtualFileSystem.js +176 -156
  32. package/package.json +1 -1
package/dist/brainy.js CHANGED
@@ -541,6 +541,59 @@ export class Brainy {
541
541
  }
542
542
  });
543
543
  }
544
+ /**
545
+ * Batch get multiple entities by IDs (v5.12.0 - Cloud Storage Optimization)
546
+ *
547
+ * **Performance**: Eliminates N+1 query pattern
548
+ * - Current: N × get() = N × 300ms cloud latency = 3-6 seconds for 10-20 entities
549
+ * - Batched: 1 × batchGet() = 1 × 300ms cloud latency = 0.3 seconds ✨
550
+ *
551
+ * **Use cases:**
552
+ * - VFS tree traversal (get all children at once)
553
+ * - Relationship traversal (get all targets at once)
554
+ * - Import operations (batch existence checks)
555
+ * - Admin tools (fetch multiple entities for listing)
556
+ *
557
+ * @param ids Array of entity IDs to fetch
558
+ * @param options Get options (includeVectors defaults to false for speed)
559
+ * @returns Map of id → entity (only successfully fetched entities included)
560
+ *
561
+ * @example
562
+ * ```typescript
563
+ * // VFS getChildren optimization
564
+ * const childIds = relations.map(r => r.to)
565
+ * const childrenMap = await brain.batchGet(childIds)
566
+ * const children = childIds.map(id => childrenMap.get(id)).filter(Boolean)
567
+ * ```
568
+ *
569
+ * @since v5.12.0
570
+ */
571
+ async batchGet(ids, options) {
572
+ await this.ensureInitialized();
573
+ const results = new Map();
574
+ if (ids.length === 0)
575
+ return results;
576
+ const includeVectors = options?.includeVectors ?? false;
577
+ if (includeVectors) {
578
+ // FULL PATH: Load vectors + metadata (currently not batched, fall back to individual)
579
+ // TODO v5.13.0: Add getNounBatch() for batched vector loading
580
+ for (const id of ids) {
581
+ const entity = await this.get(id, { includeVectors: true });
582
+ if (entity) {
583
+ results.set(id, entity);
584
+ }
585
+ }
586
+ }
587
+ else {
588
+ // FAST PATH: Metadata-only batch (default) - OPTIMIZED
589
+ const metadataMap = await this.storage.getNounMetadataBatch(ids);
590
+ for (const [id, metadata] of metadataMap.entries()) {
591
+ const entity = await this.convertMetadataToEntity(id, metadata);
592
+ results.set(id, entity);
593
+ }
594
+ }
595
+ return results;
596
+ }
544
597
  /**
545
598
  * Create a flattened Result object from entity
546
599
  * Flattens commonly-used entity fields to top level for convenience
@@ -2389,368 +2442,6 @@ export class Brainy {
2389
2442
  console.log(`[asOf] Snapshot ready (lazy-loading, cache size: ${options?.cacheSize || 10000})`);
2390
2443
  return snapshotBrain;
2391
2444
  }
2392
- /**
2393
- * Merge a source branch into target branch
2394
- * @param sourceBranch - Branch to merge from
2395
- * @param targetBranch - Branch to merge into
2396
- * @param options - Merge options (strategy, author, onConflict)
2397
- * @returns Merge result with statistics
2398
- *
2399
- * @example
2400
- * ```typescript
2401
- * const result = await brain.merge('experiment', 'main', {
2402
- * strategy: 'last-write-wins',
2403
- * author: 'dev@example.com'
2404
- * })
2405
- * console.log(result) // { added: 5, modified: 3, deleted: 1, conflicts: 0 }
2406
- * ```
2407
- */
2408
- async merge(sourceBranch, targetBranch, options) {
2409
- await this.ensureInitialized();
2410
- return this.augmentationRegistry.execute('merge', { sourceBranch, targetBranch, options }, async () => {
2411
- if (!('refManager' in this.storage) || !('blobStorage' in this.storage)) {
2412
- throw new Error('Merge requires COW-enabled storage (v5.0.0+)');
2413
- }
2414
- const strategy = options?.strategy || 'last-write-wins';
2415
- let added = 0;
2416
- let modified = 0;
2417
- let deleted = 0;
2418
- let conflicts = 0;
2419
- // Verify both branches exist
2420
- const branches = await this.listBranches();
2421
- if (!branches.includes(sourceBranch)) {
2422
- throw new Error(`Source branch '${sourceBranch}' does not exist`);
2423
- }
2424
- if (!branches.includes(targetBranch)) {
2425
- throw new Error(`Target branch '${targetBranch}' does not exist`);
2426
- }
2427
- // 1. Create temporary fork of source branch to read from
2428
- const sourceFork = await this.fork(`${sourceBranch}-merge-temp-${Date.now()}`);
2429
- await sourceFork.checkout(sourceBranch);
2430
- // 2. Save current branch and checkout target
2431
- const currentBranch = await this.getCurrentBranch();
2432
- if (currentBranch !== targetBranch) {
2433
- await this.checkout(targetBranch);
2434
- }
2435
- try {
2436
- // 3. Get all entities from source and target
2437
- const sourceResults = await sourceFork.find({});
2438
- const targetResults = await this.find({});
2439
- // Create maps for faster lookup
2440
- const targetMap = new Map(targetResults.map(r => [r.entity.id, r.entity]));
2441
- // 4. Merge entities
2442
- for (const sourceResult of sourceResults) {
2443
- const sourceEntity = sourceResult.entity;
2444
- const targetEntity = targetMap.get(sourceEntity.id);
2445
- if (!targetEntity) {
2446
- // NEW entity in source - ADD to target
2447
- await this.add({
2448
- id: sourceEntity.id,
2449
- type: sourceEntity.type,
2450
- data: sourceEntity.data,
2451
- vector: sourceEntity.vector
2452
- });
2453
- added++;
2454
- }
2455
- else {
2456
- // Entity exists in both branches - check for conflicts
2457
- const sourceTime = sourceEntity.updatedAt || sourceEntity.createdAt || 0;
2458
- const targetTime = targetEntity.updatedAt || targetEntity.createdAt || 0;
2459
- // If timestamps are identical, no change needed
2460
- if (sourceTime === targetTime) {
2461
- continue;
2462
- }
2463
- // Apply merge strategy
2464
- if (strategy === 'last-write-wins') {
2465
- if (sourceTime > targetTime) {
2466
- // Source is newer, update target
2467
- await this.update({ id: sourceEntity.id, data: sourceEntity.data });
2468
- modified++;
2469
- }
2470
- // else target is newer, keep target
2471
- }
2472
- else if (strategy === 'first-write-wins') {
2473
- if (sourceTime < targetTime) {
2474
- // Source is older, update target
2475
- await this.update({ id: sourceEntity.id, data: sourceEntity.data });
2476
- modified++;
2477
- }
2478
- }
2479
- else if (strategy === 'custom' && options?.onConflict) {
2480
- // Custom conflict resolution
2481
- const resolved = await options.onConflict(targetEntity, sourceEntity);
2482
- await this.update({ id: sourceEntity.id, data: resolved.data });
2483
- modified++;
2484
- conflicts++;
2485
- }
2486
- else {
2487
- // Conflict detected but no resolution strategy
2488
- conflicts++;
2489
- }
2490
- }
2491
- }
2492
- // 5. Merge relationships (verbs)
2493
- const sourceVerbsResult = await sourceFork.storage.getVerbs({});
2494
- const targetVerbsResult = await this.storage.getVerbs({});
2495
- const sourceVerbs = sourceVerbsResult.items || [];
2496
- const targetVerbs = targetVerbsResult.items || [];
2497
- // Create set of existing target relationships for deduplication
2498
- const targetRelSet = new Set(targetVerbs.map((v) => `${v.sourceId}-${v.verb}-${v.targetId}`));
2499
- // Add relationships that don't exist in target
2500
- for (const sourceVerb of sourceVerbs) {
2501
- const key = `${sourceVerb.sourceId}-${sourceVerb.verb}-${sourceVerb.targetId}`;
2502
- if (!targetRelSet.has(key)) {
2503
- // Only add if both entities exist in target
2504
- const hasSource = targetMap.has(sourceVerb.sourceId);
2505
- const hasTarget = targetMap.has(sourceVerb.targetId);
2506
- if (hasSource && hasTarget) {
2507
- await this.relate({
2508
- from: sourceVerb.sourceId,
2509
- to: sourceVerb.targetId,
2510
- type: sourceVerb.verb,
2511
- weight: sourceVerb.weight,
2512
- metadata: sourceVerb.metadata
2513
- });
2514
- }
2515
- }
2516
- }
2517
- // 6. Create merge commit
2518
- if ('commitLog' in this.storage) {
2519
- await this.commit({
2520
- message: `Merge ${sourceBranch} into ${targetBranch}`,
2521
- author: options?.author || 'system',
2522
- metadata: {
2523
- mergeType: 'branch',
2524
- source: sourceBranch,
2525
- target: targetBranch,
2526
- strategy,
2527
- stats: { added, modified, deleted, conflicts }
2528
- }
2529
- });
2530
- }
2531
- }
2532
- finally {
2533
- // 7. Clean up temporary fork (just delete the temp branch)
2534
- try {
2535
- const tempBranchName = `${sourceBranch}-merge-temp-${Date.now()}`;
2536
- const branches = await this.listBranches();
2537
- if (branches.includes(tempBranchName)) {
2538
- await this.deleteBranch(tempBranchName);
2539
- }
2540
- }
2541
- catch (err) {
2542
- // Ignore cleanup errors
2543
- }
2544
- // Restore original branch if needed
2545
- if (currentBranch !== targetBranch) {
2546
- await this.checkout(currentBranch);
2547
- }
2548
- }
2549
- return { added, modified, deleted, conflicts };
2550
- });
2551
- }
2552
- /**
2553
- * Compare differences between two branches (like git diff)
2554
- * @param sourceBranch - Branch to compare from (defaults to current branch)
2555
- * @param targetBranch - Branch to compare to (defaults to 'main')
2556
- * @returns Diff result showing added, modified, and deleted entities/relationships
2557
- *
2558
- * @example
2559
- * ```typescript
2560
- * // Compare current branch with main
2561
- * const diff = await brain.diff()
2562
- *
2563
- * // Compare two specific branches
2564
- * const diff = await brain.diff('experiment', 'main')
2565
- * console.log(diff)
2566
- * // {
2567
- * // entities: { added: 5, modified: 3, deleted: 1 },
2568
- * // relationships: { added: 10, modified: 2, deleted: 0 }
2569
- * // }
2570
- * ```
2571
- */
2572
- async diff(sourceBranch, targetBranch) {
2573
- await this.ensureInitialized();
2574
- return this.augmentationRegistry.execute('diff', { sourceBranch, targetBranch }, async () => {
2575
- // Default branches
2576
- const source = sourceBranch || (await this.getCurrentBranch());
2577
- const target = targetBranch || 'main';
2578
- const currentBranch = await this.getCurrentBranch();
2579
- // If source is current branch, use this instance directly (no fork needed)
2580
- let sourceFork;
2581
- let sourceForkCreated = false;
2582
- if (source === currentBranch) {
2583
- sourceFork = this;
2584
- }
2585
- else {
2586
- sourceFork = await this.fork(`temp-diff-source-${Date.now()}`);
2587
- sourceForkCreated = true;
2588
- try {
2589
- await sourceFork.checkout(source);
2590
- }
2591
- catch (err) {
2592
- // If checkout fails, branch may not exist - just use current state
2593
- }
2594
- }
2595
- // If target is current branch, use this instance directly (no fork needed)
2596
- let targetFork;
2597
- let targetForkCreated = false;
2598
- if (target === currentBranch) {
2599
- targetFork = this;
2600
- }
2601
- else {
2602
- targetFork = await this.fork(`temp-diff-target-${Date.now()}`);
2603
- targetForkCreated = true;
2604
- try {
2605
- await targetFork.checkout(target);
2606
- }
2607
- catch (err) {
2608
- // If checkout fails, branch may not exist - just use current state
2609
- }
2610
- }
2611
- try {
2612
- // Get all entities from both branches
2613
- const sourceResults = await sourceFork.find({});
2614
- const targetResults = await targetFork.find({});
2615
- // Create maps for lookup
2616
- const sourceMap = new Map(sourceResults.map(r => [r.entity.id, r.entity]));
2617
- const targetMap = new Map(targetResults.map(r => [r.entity.id, r.entity]));
2618
- // Track differences
2619
- const entitiesAdded = [];
2620
- const entitiesModified = [];
2621
- const entitiesDeleted = [];
2622
- // Find added and modified entities
2623
- for (const [id, sourceEntity] of sourceMap.entries()) {
2624
- const targetEntity = targetMap.get(id);
2625
- if (!targetEntity) {
2626
- // Entity exists in source but not target = ADDED
2627
- entitiesAdded.push({
2628
- id: sourceEntity.id,
2629
- type: sourceEntity.type,
2630
- data: sourceEntity.data
2631
- });
2632
- }
2633
- else {
2634
- // Entity exists in both - check for modifications
2635
- const changes = [];
2636
- if (sourceEntity.data !== targetEntity.data) {
2637
- changes.push('data');
2638
- }
2639
- if ((sourceEntity.updatedAt || 0) !== (targetEntity.updatedAt || 0)) {
2640
- changes.push('updatedAt');
2641
- }
2642
- if (changes.length > 0) {
2643
- entitiesModified.push({
2644
- id: sourceEntity.id,
2645
- type: sourceEntity.type,
2646
- changes
2647
- });
2648
- }
2649
- }
2650
- }
2651
- // Find deleted entities (in target but not in source)
2652
- for (const [id, targetEntity] of targetMap.entries()) {
2653
- if (!sourceMap.has(id)) {
2654
- entitiesDeleted.push({
2655
- id: targetEntity.id,
2656
- type: targetEntity.type
2657
- });
2658
- }
2659
- }
2660
- // Compare relationships
2661
- const sourceVerbsResult = await sourceFork.storage.getVerbs({});
2662
- const targetVerbsResult = await targetFork.storage.getVerbs({});
2663
- const sourceVerbs = sourceVerbsResult.items || [];
2664
- const targetVerbs = targetVerbsResult.items || [];
2665
- const sourceRelMap = new Map(sourceVerbs.map((v) => [`${v.sourceId}-${v.verb}-${v.targetId}`, v]));
2666
- const targetRelMap = new Map(targetVerbs.map((v) => [`${v.sourceId}-${v.verb}-${v.targetId}`, v]));
2667
- const relationshipsAdded = [];
2668
- const relationshipsModified = [];
2669
- const relationshipsDeleted = [];
2670
- // Find added and modified relationships
2671
- for (const [key, sourceVerb] of sourceRelMap.entries()) {
2672
- const targetVerb = targetRelMap.get(key);
2673
- if (!targetVerb) {
2674
- // Relationship exists in source but not target = ADDED
2675
- relationshipsAdded.push({
2676
- from: sourceVerb.sourceId,
2677
- to: sourceVerb.targetId,
2678
- type: sourceVerb.verb
2679
- });
2680
- }
2681
- else {
2682
- // Relationship exists in both - check for modifications
2683
- const changes = [];
2684
- if ((sourceVerb.weight || 0) !== (targetVerb.weight || 0)) {
2685
- changes.push('weight');
2686
- }
2687
- if (JSON.stringify(sourceVerb.metadata) !== JSON.stringify(targetVerb.metadata)) {
2688
- changes.push('metadata');
2689
- }
2690
- if (changes.length > 0) {
2691
- relationshipsModified.push({
2692
- from: sourceVerb.sourceId,
2693
- to: sourceVerb.targetId,
2694
- type: sourceVerb.verb,
2695
- changes
2696
- });
2697
- }
2698
- }
2699
- }
2700
- // Find deleted relationships
2701
- for (const [key, targetVerb] of targetRelMap.entries()) {
2702
- if (!sourceRelMap.has(key)) {
2703
- relationshipsDeleted.push({
2704
- from: targetVerb.sourceId,
2705
- to: targetVerb.targetId,
2706
- type: targetVerb.verb
2707
- });
2708
- }
2709
- }
2710
- return {
2711
- entities: {
2712
- added: entitiesAdded,
2713
- modified: entitiesModified,
2714
- deleted: entitiesDeleted
2715
- },
2716
- relationships: {
2717
- added: relationshipsAdded,
2718
- modified: relationshipsModified,
2719
- deleted: relationshipsDeleted
2720
- },
2721
- summary: {
2722
- entitiesAdded: entitiesAdded.length,
2723
- entitiesModified: entitiesModified.length,
2724
- entitiesDeleted: entitiesDeleted.length,
2725
- relationshipsAdded: relationshipsAdded.length,
2726
- relationshipsModified: relationshipsModified.length,
2727
- relationshipsDeleted: relationshipsDeleted.length
2728
- }
2729
- };
2730
- }
2731
- finally {
2732
- // Clean up temporary forks (only if we created them)
2733
- try {
2734
- const branches = await this.listBranches();
2735
- if (sourceForkCreated && sourceFork !== this) {
2736
- const sourceBranchName = await sourceFork.getCurrentBranch();
2737
- if (branches.includes(sourceBranchName)) {
2738
- await this.deleteBranch(sourceBranchName);
2739
- }
2740
- }
2741
- if (targetForkCreated && targetFork !== this) {
2742
- const targetBranchName = await targetFork.getCurrentBranch();
2743
- if (branches.includes(targetBranchName)) {
2744
- await this.deleteBranch(targetBranchName);
2745
- }
2746
- }
2747
- }
2748
- catch (err) {
2749
- // Ignore cleanup errors
2750
- }
2751
- }
2752
- });
2753
- }
2754
2445
  /**
2755
2446
  * Delete a branch/fork
2756
2447
  * @param branch - Branch name to delete
@@ -3327,14 +3018,6 @@ export class Brainy {
3327
3018
  await this.ensureInitialized();
3328
3019
  return this.metadataIndex.getFieldsForType(nounType);
3329
3020
  }
3330
- /**
3331
- * Get comprehensive type-field affinity statistics
3332
- * Useful for understanding data patterns and NLP optimization
3333
- */
3334
- async getTypeFieldAffinityStats() {
3335
- await this.ensureInitialized();
3336
- return this.metadataIndex.getTypeFieldAffinityStats();
3337
- }
3338
3021
  /**
3339
3022
  * Create a streaming pipeline
3340
3023
  */
@@ -13,10 +13,6 @@ interface ForkOptions extends CoreOptions {
13
13
  message?: string;
14
14
  author?: string;
15
15
  }
16
- interface MergeOptions extends CoreOptions {
17
- force?: boolean;
18
- strategy?: 'last-write-wins' | 'custom';
19
- }
20
16
  interface MigrateOptions extends CoreOptions {
21
17
  from?: string;
22
18
  to?: string;
@@ -43,11 +39,7 @@ export declare const cowCommands: {
43
39
  force?: boolean;
44
40
  }): Promise<void>;
45
41
  /**
46
- * Merge a fork/branch into current branch
47
- */
48
- merge(source: string | undefined, target: string | undefined, options: MergeOptions): Promise<void>;
49
- /**
50
- * Get commit history
42
+ * View commit history
51
43
  */
52
44
  history(options: CoreOptions & {
53
45
  limit?: string;
@@ -215,67 +215,7 @@ ${chalk.cyan('Fork Statistics:')}
215
215
  }
216
216
  },
217
217
  /**
218
- * Merge a fork/branch into current branch
219
- */
220
- async merge(source, target, options) {
221
- let spinner = null;
222
- try {
223
- const brain = getBrainy();
224
- await brain.init();
225
- // Interactive mode if parameters missing
226
- if (!source || !target) {
227
- const branches = await brain.listBranches();
228
- const currentBranch = await brain.getCurrentBranch();
229
- const answers = await inquirer.prompt([
230
- {
231
- type: 'list',
232
- name: 'source',
233
- message: 'Merge FROM branch:',
234
- choices: branches.map(b => ({ name: b, value: b })),
235
- when: !source
236
- },
237
- {
238
- type: 'list',
239
- name: 'target',
240
- message: 'Merge INTO branch:',
241
- choices: branches.map(b => ({
242
- name: b === currentBranch ? `${b} (current)` : b,
243
- value: b
244
- })),
245
- default: currentBranch,
246
- when: !target
247
- }
248
- ]);
249
- source = source || answers.source;
250
- target = target || answers.target;
251
- }
252
- spinner = ora(`Merging ${chalk.cyan(source)} → ${chalk.green(target)}...`).start();
253
- const result = await brain.merge(source, target, {
254
- strategy: options.strategy || 'last-write-wins'
255
- });
256
- spinner.succeed(`Merged ${chalk.cyan(source)} → ${chalk.green(target)}`);
257
- console.log(`
258
- ${chalk.cyan('Merge Summary:')}
259
- ${chalk.green('Added:')} ${result.added} entities
260
- ${chalk.yellow('Modified:')} ${result.modified} entities
261
- ${chalk.red('Deleted:')} ${result.deleted} entities
262
- ${chalk.magenta('Conflicts:')} ${result.conflicts} (resolved)
263
- `.trim());
264
- if (options.json) {
265
- formatOutput(result, options);
266
- }
267
- }
268
- catch (error) {
269
- if (spinner)
270
- spinner.fail('Merge failed');
271
- console.error(chalk.red('Error:'), error.message);
272
- if (options.verbose)
273
- console.error(error);
274
- process.exit(1);
275
- }
276
- },
277
- /**
278
- * Get commit history
218
+ * View commit history
279
219
  */
280
220
  async history(options) {
281
221
  try {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Data Management Commands
3
3
  *
4
- * Backup, restore, import, export operations
4
+ * Import, export, and statistics operations
5
5
  */
6
6
  interface DataOptions {
7
7
  verbose?: boolean;
@@ -9,18 +9,6 @@ interface DataOptions {
9
9
  pretty?: boolean;
10
10
  }
11
11
  export declare const dataCommands: {
12
- /**
13
- * Backup database
14
- */
15
- backup(file: string, options: DataOptions & {
16
- compress?: boolean;
17
- }): Promise<void>;
18
- /**
19
- * Restore from backup
20
- */
21
- restore(file: string, options: DataOptions & {
22
- merge?: boolean;
23
- }): Promise<void>;
24
12
  /**
25
13
  * Get database statistics
26
14
  */
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * Data Management Commands
3
3
  *
4
- * Backup, restore, import, export operations
4
+ * Import, export, and statistics operations
5
5
  */
6
6
  import chalk from 'chalk';
7
7
  import ora from 'ora';
8
- import { readFileSync, writeFileSync } from 'node:fs';
9
8
  import { Brainy } from '../../brainy.js';
10
9
  let brainyInstance = null;
11
10
  const getBrainy = () => {
@@ -20,78 +19,6 @@ const formatOutput = (data, options) => {
20
19
  }
21
20
  };
22
21
  export const dataCommands = {
23
- /**
24
- * Backup database
25
- */
26
- async backup(file, options) {
27
- const spinner = ora('Creating backup...').start();
28
- try {
29
- const brain = getBrainy();
30
- const dataApi = await brain.data();
31
- const backup = await dataApi.backup({
32
- compress: options.compress
33
- });
34
- spinner.text = 'Writing backup file...';
35
- // Write backup to file
36
- const content = typeof backup === 'string'
37
- ? backup
38
- : JSON.stringify(backup, null, options.pretty ? 2 : 0);
39
- writeFileSync(file, content);
40
- spinner.succeed('Backup created');
41
- if (!options.json) {
42
- console.log(chalk.green(`✓ Backup saved to: ${file}`));
43
- if (backup.compressed) {
44
- console.log(chalk.dim(` Original size: ${formatBytes(backup.originalSize)}`));
45
- console.log(chalk.dim(` Compressed size: ${formatBytes(backup.compressedSize)}`));
46
- console.log(chalk.dim(` Compression ratio: ${((backup.compressedSize / backup.originalSize) * 100).toFixed(1)}%`));
47
- }
48
- }
49
- else {
50
- formatOutput({ file, backup: true }, options);
51
- }
52
- }
53
- catch (error) {
54
- spinner.fail('Backup failed');
55
- console.error(chalk.red(error.message));
56
- process.exit(1);
57
- }
58
- },
59
- /**
60
- * Restore from backup
61
- */
62
- async restore(file, options) {
63
- const spinner = ora('Restoring from backup...').start();
64
- try {
65
- const brain = getBrainy();
66
- const dataApi = await brain.data();
67
- // Read backup file
68
- const content = readFileSync(file, 'utf-8');
69
- const backup = JSON.parse(content);
70
- // Restore
71
- await dataApi.restore({
72
- backup,
73
- merge: options.merge || false
74
- });
75
- spinner.succeed('Restore complete');
76
- if (!options.json) {
77
- console.log(chalk.green(`✓ Restored from: ${file}`));
78
- if (options.merge) {
79
- console.log(chalk.dim(' Mode: Merged with existing data'));
80
- }
81
- else {
82
- console.log(chalk.dim(' Mode: Replaced all data'));
83
- }
84
- }
85
- else {
86
- formatOutput({ file, restored: true }, options);
87
- }
88
- }
89
- catch (error) {
90
- spinner.fail('Restore failed');
91
- console.error(chalk.red(error.message));
92
- process.exit(1);
93
- }
94
- },
95
22
  /**
96
23
  * Get database statistics
97
24
  */
package/dist/cli/index.js CHANGED
@@ -454,16 +454,7 @@ program
454
454
  storageCommands.costEstimate(options);
455
455
  }));
456
456
  // ===== Data Management Commands =====
457
- program
458
- .command('backup <file>')
459
- .description('Create database backup')
460
- .option('--compress', 'Compress backup')
461
- .action(dataCommands.backup);
462
- program
463
- .command('restore <file>')
464
- .description('Restore from backup')
465
- .option('--merge', 'Merge with existing data (default: replace)')
466
- .action(dataCommands.restore);
457
+ program;
467
458
  program
468
459
  .command('data-stats')
469
460
  .description('Show detailed database statistics')
@@ -551,12 +542,6 @@ program
551
542
  .alias('co')
552
543
  .description('Switch to a different branch')
553
544
  .action(cowCommands.checkout);
554
- program
555
- .command('merge [source] [target]')
556
- .description('Merge a fork/branch into another branch')
557
- .option('--strategy <type>', 'Merge strategy (last-write-wins|custom)', 'last-write-wins')
558
- .option('-f, --force', 'Force merge on conflicts')
559
- .action(cowCommands.merge);
560
545
  program
561
546
  .command('history')
562
547
  .alias('log')