@soleri/core 2.5.0 → 2.7.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/dist/brain/intelligence.d.ts +1 -0
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +160 -148
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/control/identity-manager.d.ts +3 -1
- package/dist/control/identity-manager.d.ts.map +1 -1
- package/dist/control/identity-manager.js +53 -51
- package/dist/control/identity-manager.js.map +1 -1
- package/dist/control/intent-router.d.ts +1 -0
- package/dist/control/intent-router.d.ts.map +1 -1
- package/dist/control/intent-router.js +41 -32
- package/dist/control/intent-router.js.map +1 -1
- package/dist/curator/curator.d.ts +1 -0
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +58 -99
- package/dist/curator/curator.js.map +1 -1
- package/dist/facades/facade-factory.js +1 -1
- package/dist/facades/facade-factory.js.map +1 -1
- package/dist/governance/governance.d.ts +1 -0
- package/dist/governance/governance.d.ts.map +1 -1
- package/dist/governance/governance.js +51 -68
- package/dist/governance/governance.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/persistence/index.d.ts +2 -1
- package/dist/persistence/index.d.ts.map +1 -1
- package/dist/persistence/index.js +1 -0
- package/dist/persistence/index.js.map +1 -1
- package/dist/persistence/postgres-provider.d.ts +46 -0
- package/dist/persistence/postgres-provider.d.ts.map +1 -0
- package/dist/persistence/postgres-provider.js +115 -0
- package/dist/persistence/postgres-provider.js.map +1 -0
- package/dist/persistence/sqlite-provider.d.ts +5 -2
- package/dist/persistence/sqlite-provider.d.ts.map +1 -1
- package/dist/persistence/sqlite-provider.js +37 -1
- package/dist/persistence/sqlite-provider.js.map +1 -1
- package/dist/persistence/types.d.ts +23 -1
- package/dist/persistence/types.d.ts.map +1 -1
- package/dist/project/project-registry.d.ts +4 -4
- package/dist/project/project-registry.d.ts.map +1 -1
- package/dist/project/project-registry.js +32 -50
- package/dist/project/project-registry.js.map +1 -1
- package/dist/runtime/admin-extra-ops.d.ts +3 -3
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +33 -3
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/core-ops.d.ts +4 -4
- package/dist/runtime/core-ops.js +4 -4
- package/dist/runtime/runtime.js +1 -1
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts +3 -2
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.js +40 -2
- package/dist/runtime/vault-extra-ops.js.map +1 -1
- package/dist/vault/vault.d.ts +21 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +99 -0
- package/dist/vault/vault.js.map +1 -1
- package/package.json +4 -2
- package/src/__tests__/admin-extra-ops.test.ts +2 -2
- package/src/__tests__/core-ops.test.ts +8 -2
- package/src/__tests__/persistence.test.ts +66 -0
- package/src/__tests__/postgres-provider.test.ts +58 -0
- package/src/__tests__/vault-extra-ops.test.ts +2 -2
- package/src/__tests__/vault.test.ts +184 -0
- package/src/brain/intelligence.ts +258 -307
- package/src/control/identity-manager.ts +77 -75
- package/src/control/intent-router.ts +55 -57
- package/src/curator/curator.ts +124 -145
- package/src/facades/facade-factory.ts +1 -1
- package/src/governance/governance.ts +90 -107
- package/src/index.ts +2 -0
- package/src/persistence/index.ts +2 -0
- package/src/persistence/postgres-provider.ts +157 -0
- package/src/persistence/sqlite-provider.ts +55 -2
- package/src/persistence/types.ts +31 -1
- package/src/project/project-registry.ts +69 -74
- package/src/runtime/admin-extra-ops.ts +36 -3
- package/src/runtime/core-ops.ts +4 -4
- package/src/runtime/runtime.ts +1 -1
- package/src/runtime/vault-extra-ops.ts +42 -2
- package/src/vault/vault.ts +118 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { translateSql } from '../persistence/postgres-provider.js';
|
|
3
|
+
import { PostgresPersistenceProvider } from '../persistence/postgres-provider.js';
|
|
4
|
+
|
|
5
|
+
describe('translateSql', () => {
|
|
6
|
+
it('converts positional ? to $N', () => {
|
|
7
|
+
const result = translateSql('SELECT * FROM t WHERE a = ? AND b = ?', ['x', 'y']);
|
|
8
|
+
expect(result.sql).toBe('SELECT * FROM t WHERE a = $1 AND b = $2');
|
|
9
|
+
expect(result.values).toEqual(['x', 'y']);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('converts named @params to $N', () => {
|
|
13
|
+
const result = translateSql('INSERT INTO t (a, b) VALUES (@name, @age)', {
|
|
14
|
+
name: 'Alice',
|
|
15
|
+
age: 30,
|
|
16
|
+
});
|
|
17
|
+
expect(result.sql).toBe('INSERT INTO t (a, b) VALUES ($1, $2)');
|
|
18
|
+
expect(result.values).toEqual(['Alice', 30]);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('deduplicates repeated named params', () => {
|
|
22
|
+
const result = translateSql('SELECT * FROM t WHERE a = @x OR b = @x', { x: 42 });
|
|
23
|
+
expect(result.sql).toBe('SELECT * FROM t WHERE a = $1 OR b = $1');
|
|
24
|
+
expect(result.values).toEqual([42]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('replaces unixepoch()', () => {
|
|
28
|
+
const result = translateSql('INSERT INTO t (ts) VALUES (unixepoch())');
|
|
29
|
+
expect(result.sql).toBe('INSERT INTO t (ts) VALUES (EXTRACT(EPOCH FROM NOW())::integer)');
|
|
30
|
+
expect(result.values).toEqual([]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('handles no params', () => {
|
|
34
|
+
const result = translateSql('SELECT 1');
|
|
35
|
+
expect(result.sql).toBe('SELECT 1');
|
|
36
|
+
expect(result.values).toEqual([]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('handles mixed: ? params + unixepoch()', () => {
|
|
40
|
+
const result = translateSql('UPDATE t SET name = ?, updated_at = unixepoch() WHERE id = ?', [
|
|
41
|
+
'Bob',
|
|
42
|
+
'id-1',
|
|
43
|
+
]);
|
|
44
|
+
expect(result.sql).toBe(
|
|
45
|
+
'UPDATE t SET name = $1, updated_at = EXTRACT(EPOCH FROM NOW())::integer WHERE id = $2',
|
|
46
|
+
);
|
|
47
|
+
expect(result.values).toEqual(['Bob', 'id-1']);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('PostgresPersistenceProvider', () => {
|
|
52
|
+
it('backend returns postgres', () => {
|
|
53
|
+
// Access backend without connecting (class-level property)
|
|
54
|
+
// We can't instantiate without pg, so we test the translateSql export
|
|
55
|
+
// and verify the class exists with correct typing
|
|
56
|
+
expect(PostgresPersistenceProvider).toBeDefined();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -47,8 +47,8 @@ describe('createVaultExtraOps', () => {
|
|
|
47
47
|
return op;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
it('should return
|
|
51
|
-
expect(ops.length).toBe(
|
|
50
|
+
it('should return 23 ops', () => {
|
|
51
|
+
expect(ops.length).toBe(23);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
it('should have all expected op names', () => {
|
|
@@ -491,4 +491,188 @@ describe('Vault', () => {
|
|
|
491
491
|
expect(stats.byProject).toEqual({ '/a': 2, '/b': 1 });
|
|
492
492
|
});
|
|
493
493
|
});
|
|
494
|
+
|
|
495
|
+
describe('Vault archival and optimization', () => {
|
|
496
|
+
it('archive moves old entries', () => {
|
|
497
|
+
const v = new Vault(':memory:');
|
|
498
|
+
v.seed([
|
|
499
|
+
{
|
|
500
|
+
id: 'old-1',
|
|
501
|
+
type: 'pattern',
|
|
502
|
+
domain: 'test',
|
|
503
|
+
title: 'Old Pattern',
|
|
504
|
+
severity: 'suggestion',
|
|
505
|
+
description: 'Old entry',
|
|
506
|
+
tags: ['test'],
|
|
507
|
+
},
|
|
508
|
+
]);
|
|
509
|
+
// Manually set the updated_at to 200 days ago
|
|
510
|
+
v.getProvider().run('UPDATE entries SET updated_at = ? WHERE id = ?', [
|
|
511
|
+
Math.floor(Date.now() / 1000) - 200 * 86400,
|
|
512
|
+
'old-1',
|
|
513
|
+
]);
|
|
514
|
+
v.seed([
|
|
515
|
+
{
|
|
516
|
+
id: 'new-1',
|
|
517
|
+
type: 'pattern',
|
|
518
|
+
domain: 'test',
|
|
519
|
+
title: 'New Pattern',
|
|
520
|
+
severity: 'suggestion',
|
|
521
|
+
description: 'New entry',
|
|
522
|
+
tags: ['test'],
|
|
523
|
+
},
|
|
524
|
+
]);
|
|
525
|
+
|
|
526
|
+
const result = v.archive({ olderThanDays: 90 });
|
|
527
|
+
expect(result.archived).toBe(1);
|
|
528
|
+
expect(v.get('old-1')).toBeNull();
|
|
529
|
+
expect(v.get('new-1')).not.toBeNull();
|
|
530
|
+
v.close();
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it('archive respects olderThanDays', () => {
|
|
534
|
+
const v = new Vault(':memory:');
|
|
535
|
+
v.seed([
|
|
536
|
+
{
|
|
537
|
+
id: 'e1',
|
|
538
|
+
type: 'pattern',
|
|
539
|
+
domain: 'test',
|
|
540
|
+
title: 'Entry',
|
|
541
|
+
severity: 'suggestion',
|
|
542
|
+
description: 'Not old enough',
|
|
543
|
+
tags: ['test'],
|
|
544
|
+
},
|
|
545
|
+
]);
|
|
546
|
+
// Entry is fresh (just created), archive with 1 day threshold
|
|
547
|
+
const result = v.archive({ olderThanDays: 1 });
|
|
548
|
+
expect(result.archived).toBe(0);
|
|
549
|
+
expect(v.get('e1')).not.toBeNull();
|
|
550
|
+
v.close();
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it('archive returns 0 when no candidates', () => {
|
|
554
|
+
const v = new Vault(':memory:');
|
|
555
|
+
const result = v.archive({ olderThanDays: 30 });
|
|
556
|
+
expect(result.archived).toBe(0);
|
|
557
|
+
v.close();
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
it('archived entries excluded from search', () => {
|
|
561
|
+
const v = new Vault(':memory:');
|
|
562
|
+
v.seed([
|
|
563
|
+
{
|
|
564
|
+
id: 'search-1',
|
|
565
|
+
type: 'pattern',
|
|
566
|
+
domain: 'test',
|
|
567
|
+
title: 'Searchable Pattern',
|
|
568
|
+
severity: 'suggestion',
|
|
569
|
+
description: 'Should be archived',
|
|
570
|
+
tags: ['search'],
|
|
571
|
+
},
|
|
572
|
+
]);
|
|
573
|
+
v.getProvider().run('UPDATE entries SET updated_at = ? WHERE id = ?', [
|
|
574
|
+
Math.floor(Date.now() / 1000) - 200 * 86400,
|
|
575
|
+
'search-1',
|
|
576
|
+
]);
|
|
577
|
+
|
|
578
|
+
// Before archive: should appear in search
|
|
579
|
+
const before = v.search('searchable');
|
|
580
|
+
expect(before.length).toBeGreaterThan(0);
|
|
581
|
+
|
|
582
|
+
v.archive({ olderThanDays: 90 });
|
|
583
|
+
|
|
584
|
+
// After archive: should not appear
|
|
585
|
+
const after = v.search('searchable');
|
|
586
|
+
expect(after.length).toBe(0);
|
|
587
|
+
v.close();
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
it('restore brings entry back', () => {
|
|
591
|
+
const v = new Vault(':memory:');
|
|
592
|
+
v.seed([
|
|
593
|
+
{
|
|
594
|
+
id: 'restore-1',
|
|
595
|
+
type: 'pattern',
|
|
596
|
+
domain: 'test',
|
|
597
|
+
title: 'Restore Me',
|
|
598
|
+
severity: 'suggestion',
|
|
599
|
+
description: 'Will be restored',
|
|
600
|
+
tags: ['test'],
|
|
601
|
+
},
|
|
602
|
+
]);
|
|
603
|
+
v.getProvider().run('UPDATE entries SET updated_at = ? WHERE id = ?', [
|
|
604
|
+
Math.floor(Date.now() / 1000) - 200 * 86400,
|
|
605
|
+
'restore-1',
|
|
606
|
+
]);
|
|
607
|
+
v.archive({ olderThanDays: 90 });
|
|
608
|
+
expect(v.get('restore-1')).toBeNull();
|
|
609
|
+
|
|
610
|
+
const restored = v.restore('restore-1');
|
|
611
|
+
expect(restored).toBe(true);
|
|
612
|
+
expect(v.get('restore-1')).not.toBeNull();
|
|
613
|
+
expect(v.get('restore-1')!.title).toBe('Restore Me');
|
|
614
|
+
v.close();
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
it('restore returns false for missing id', () => {
|
|
618
|
+
const v = new Vault(':memory:');
|
|
619
|
+
const result = v.restore('nonexistent');
|
|
620
|
+
expect(result).toBe(false);
|
|
621
|
+
v.close();
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('restored entry appears in search', () => {
|
|
625
|
+
const v = new Vault(':memory:');
|
|
626
|
+
v.seed([
|
|
627
|
+
{
|
|
628
|
+
id: 'search-restore',
|
|
629
|
+
type: 'pattern',
|
|
630
|
+
domain: 'test',
|
|
631
|
+
title: 'Unique Findable Pattern',
|
|
632
|
+
severity: 'suggestion',
|
|
633
|
+
description: 'Will be found after restore',
|
|
634
|
+
tags: ['test'],
|
|
635
|
+
},
|
|
636
|
+
]);
|
|
637
|
+
v.getProvider().run('UPDATE entries SET updated_at = ? WHERE id = ?', [
|
|
638
|
+
Math.floor(Date.now() / 1000) - 200 * 86400,
|
|
639
|
+
'search-restore',
|
|
640
|
+
]);
|
|
641
|
+
v.archive({ olderThanDays: 90 });
|
|
642
|
+
v.restore('search-restore');
|
|
643
|
+
|
|
644
|
+
const results = v.search('unique findable');
|
|
645
|
+
expect(results.length).toBeGreaterThan(0);
|
|
646
|
+
v.close();
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
it('optimize runs without error', () => {
|
|
650
|
+
const v = new Vault(':memory:');
|
|
651
|
+
v.seed([
|
|
652
|
+
{
|
|
653
|
+
id: 'opt-1',
|
|
654
|
+
type: 'pattern',
|
|
655
|
+
domain: 'test',
|
|
656
|
+
title: 'Optimize Test',
|
|
657
|
+
severity: 'suggestion',
|
|
658
|
+
description: 'For optimization',
|
|
659
|
+
tags: ['test'],
|
|
660
|
+
},
|
|
661
|
+
]);
|
|
662
|
+
|
|
663
|
+
expect(() => v.optimize()).not.toThrow();
|
|
664
|
+
v.close();
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
it('optimize returns status', () => {
|
|
668
|
+
const v = new Vault(':memory:');
|
|
669
|
+
const status = v.optimize();
|
|
670
|
+
expect(status).toHaveProperty('vacuumed');
|
|
671
|
+
expect(status).toHaveProperty('analyzed');
|
|
672
|
+
expect(status).toHaveProperty('ftsRebuilt');
|
|
673
|
+
// SQLite backend should analyze and rebuild FTS
|
|
674
|
+
expect(status.analyzed).toBe(true);
|
|
675
|
+
v.close();
|
|
676
|
+
});
|
|
677
|
+
});
|
|
494
678
|
});
|