@skillsmith/core 0.4.13 → 0.4.15
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/README.md +2 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analytics/storage.d.ts +8 -2
- package/dist/src/analytics/storage.d.ts.map +1 -1
- package/dist/src/analytics/storage.js +16 -5
- package/dist/src/analytics/storage.js.map +1 -1
- package/dist/src/analytics/usage-tracker.d.ts +8 -2
- package/dist/src/analytics/usage-tracker.d.ts.map +1 -1
- package/dist/src/analytics/usage-tracker.js +24 -11
- package/dist/src/analytics/usage-tracker.js.map +1 -1
- package/dist/src/api/client.d.ts +1 -0
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.health.d.ts +26 -0
- package/dist/src/api/client.health.d.ts.map +1 -0
- package/dist/src/api/client.health.js +74 -0
- package/dist/src/api/client.health.js.map +1 -0
- package/dist/src/api/client.js +3 -51
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/benchmarks/IndexBenchmark.js +2 -2
- package/dist/src/benchmarks/IndexBenchmark.js.map +1 -1
- package/dist/src/benchmarks/SearchBenchmark.js +2 -2
- package/dist/src/benchmarks/SearchBenchmark.js.map +1 -1
- package/dist/src/benchmarks/cacheBenchmark.js +2 -2
- package/dist/src/benchmarks/cacheBenchmark.js.map +1 -1
- package/dist/src/benchmarks/embeddingBenchmark.js +1 -1
- package/dist/src/benchmarks/embeddingBenchmark.js.map +1 -1
- package/dist/src/cache/CacheManager.d.ts +13 -2
- package/dist/src/cache/CacheManager.d.ts.map +1 -1
- package/dist/src/cache/CacheManager.js +27 -6
- package/dist/src/cache/CacheManager.js.map +1 -1
- package/dist/src/cache/TieredCache.d.ts +15 -2
- package/dist/src/cache/TieredCache.d.ts.map +1 -1
- package/dist/src/cache/TieredCache.js +52 -70
- package/dist/src/cache/TieredCache.js.map +1 -1
- package/dist/src/cache/index.d.ts +12 -0
- package/dist/src/cache/index.d.ts.map +1 -1
- package/dist/src/cache/index.js +20 -1
- package/dist/src/cache/index.js.map +1 -1
- package/dist/src/cache/sqlite.d.ts +15 -1
- package/dist/src/cache/sqlite.d.ts.map +1 -1
- package/dist/src/cache/sqlite.js +22 -4
- package/dist/src/cache/sqlite.js.map +1 -1
- package/dist/src/db/createDatabase.d.ts +9 -1
- package/dist/src/db/createDatabase.d.ts.map +1 -1
- package/dist/src/db/createDatabase.js +21 -1
- package/dist/src/db/createDatabase.js.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.d.ts.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.js +5 -2
- package/dist/src/db/drivers/sqljsDriver.js.map +1 -1
- package/dist/src/db/migrations/v5-skill-versions.d.ts +30 -0
- package/dist/src/db/migrations/v5-skill-versions.d.ts.map +1 -0
- package/dist/src/db/migrations/v5-skill-versions.js +45 -0
- package/dist/src/db/migrations/v5-skill-versions.js.map +1 -0
- package/dist/src/db/migrations/v5b-change-type.d.ts +19 -0
- package/dist/src/db/migrations/v5b-change-type.d.ts.map +1 -0
- package/dist/src/db/migrations/v5b-change-type.js +22 -0
- package/dist/src/db/migrations/v5b-change-type.js.map +1 -0
- package/dist/src/db/migrations/v6-advisories.d.ts +32 -0
- package/dist/src/db/migrations/v6-advisories.d.ts.map +1 -0
- package/dist/src/db/migrations/v6-advisories.js +53 -0
- package/dist/src/db/migrations/v6-advisories.js.map +1 -0
- package/dist/src/db/migrations/v7-compatibility.d.ts +21 -0
- package/dist/src/db/migrations/v7-compatibility.d.ts.map +1 -0
- package/dist/src/db/migrations/v7-compatibility.js +23 -0
- package/dist/src/db/migrations/v7-compatibility.js.map +1 -0
- package/dist/src/db/migrations/v8-co-installs.d.ts +21 -0
- package/dist/src/db/migrations/v8-co-installs.d.ts.map +1 -0
- package/dist/src/db/migrations/v8-co-installs.js +33 -0
- package/dist/src/db/migrations/v8-co-installs.js.map +1 -0
- package/dist/src/db/schema.d.ts +6 -11
- package/dist/src/db/schema.d.ts.map +1 -1
- package/dist/src/db/schema.js +38 -17
- package/dist/src/db/schema.js.map +1 -1
- package/dist/src/embeddings/hnsw-store.d.ts +14 -0
- package/dist/src/embeddings/hnsw-store.d.ts.map +1 -1
- package/dist/src/embeddings/hnsw-store.helpers.d.ts +4 -4
- package/dist/src/embeddings/hnsw-store.helpers.d.ts.map +1 -1
- package/dist/src/embeddings/hnsw-store.helpers.js +5 -5
- package/dist/src/embeddings/hnsw-store.helpers.js.map +1 -1
- package/dist/src/embeddings/hnsw-store.js +32 -4
- package/dist/src/embeddings/hnsw-store.js.map +1 -1
- package/dist/src/embeddings/index.d.ts +15 -1
- package/dist/src/embeddings/index.d.ts.map +1 -1
- package/dist/src/embeddings/index.js +24 -4
- package/dist/src/embeddings/index.js.map +1 -1
- package/dist/src/exports/repositories.d.ts +5 -0
- package/dist/src/exports/repositories.d.ts.map +1 -1
- package/dist/src/exports/repositories.js +17 -0
- package/dist/src/exports/repositories.js.map +1 -1
- package/dist/src/exports/types.d.ts +1 -1
- package/dist/src/exports/types.d.ts.map +1 -1
- package/dist/src/exports/types.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexer/SkillParser.d.ts +2 -0
- package/dist/src/indexer/SkillParser.d.ts.map +1 -1
- package/dist/src/indexer/SkillParser.js.map +1 -1
- package/dist/src/learning/PatternStore.d.ts +8 -2
- package/dist/src/learning/PatternStore.d.ts.map +1 -1
- package/dist/src/learning/PatternStore.helpers.d.ts +19 -1
- package/dist/src/learning/PatternStore.helpers.d.ts.map +1 -1
- package/dist/src/learning/PatternStore.helpers.js +51 -0
- package/dist/src/learning/PatternStore.helpers.js.map +1 -1
- package/dist/src/learning/PatternStore.js +19 -39
- package/dist/src/learning/PatternStore.js.map +1 -1
- package/dist/src/repositories/AdvisoryRepository.d.ts +80 -0
- package/dist/src/repositories/AdvisoryRepository.d.ts.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.js +128 -0
- package/dist/src/repositories/AdvisoryRepository.js.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.test.d.ts +6 -0
- package/dist/src/repositories/AdvisoryRepository.test.d.ts.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.test.js +149 -0
- package/dist/src/repositories/AdvisoryRepository.test.js.map +1 -0
- package/dist/src/repositories/CoInstallRepository.d.ts +68 -0
- package/dist/src/repositories/CoInstallRepository.d.ts.map +1 -0
- package/dist/src/repositories/CoInstallRepository.js +122 -0
- package/dist/src/repositories/CoInstallRepository.js.map +1 -0
- package/dist/src/repositories/SkillRepository.d.ts.map +1 -1
- package/dist/src/repositories/SkillRepository.js +16 -5
- package/dist/src/repositories/SkillRepository.js.map +1 -1
- package/dist/src/repositories/SkillVersionRepository.d.ts +82 -0
- package/dist/src/repositories/SkillVersionRepository.d.ts.map +1 -0
- package/dist/src/repositories/SkillVersionRepository.js +118 -0
- package/dist/src/repositories/SkillVersionRepository.js.map +1 -0
- package/dist/src/search/hybrid.d.ts +15 -4
- package/dist/src/search/hybrid.d.ts.map +1 -1
- package/dist/src/search/hybrid.js +25 -9
- package/dist/src/search/hybrid.js.map +1 -1
- package/dist/src/services/SearchService.helpers.d.ts.map +1 -1
- package/dist/src/services/SearchService.helpers.js +4 -0
- package/dist/src/services/SearchService.helpers.js.map +1 -1
- package/dist/src/services/SearchService.types.d.ts +1 -0
- package/dist/src/services/SearchService.types.d.ts.map +1 -1
- package/dist/src/services/TaskRunner.d.ts +5 -81
- package/dist/src/services/TaskRunner.d.ts.map +1 -1
- package/dist/src/services/TaskRunner.js +7 -68
- package/dist/src/services/TaskRunner.js.map +1 -1
- package/dist/src/services/TaskRunner.process.d.ts +33 -0
- package/dist/src/services/TaskRunner.process.d.ts.map +1 -0
- package/dist/src/services/TaskRunner.process.js +70 -0
- package/dist/src/services/TaskRunner.process.js.map +1 -0
- package/dist/src/services/TaskRunner.types.d.ts +76 -0
- package/dist/src/services/TaskRunner.types.d.ts.map +1 -0
- package/dist/src/services/TaskRunner.types.js +22 -0
- package/dist/src/services/TaskRunner.types.js.map +1 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.d.ts +13 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.d.ts.map +1 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.js +91 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.js.map +1 -0
- package/dist/src/services/quarantine/QuarantineService.d.ts +3 -24
- package/dist/src/services/quarantine/QuarantineService.d.ts.map +1 -1
- package/dist/src/services/quarantine/QuarantineService.js +8 -205
- package/dist/src/services/quarantine/QuarantineService.js.map +1 -1
- package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts +57 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts.map +1 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.js +211 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.js.map +1 -0
- package/dist/src/session/SessionManager.d.ts +2 -33
- package/dist/src/session/SessionManager.d.ts.map +1 -1
- package/dist/src/session/SessionManager.js +14 -238
- package/dist/src/session/SessionManager.js.map +1 -1
- package/dist/src/session/SessionManager.memory.d.ts +67 -0
- package/dist/src/session/SessionManager.memory.d.ts.map +1 -0
- package/dist/src/session/SessionManager.memory.js +262 -0
- package/dist/src/session/SessionManager.memory.js.map +1 -0
- package/dist/src/sync/SyncEngine.d.ts +13 -1
- package/dist/src/sync/SyncEngine.d.ts.map +1 -1
- package/dist/src/sync/SyncEngine.js +50 -1
- package/dist/src/sync/SyncEngine.js.map +1 -1
- package/dist/src/testing/MultiLLMProvider.d.ts +5 -6
- package/dist/src/testing/MultiLLMProvider.d.ts.map +1 -1
- package/dist/src/testing/MultiLLMProvider.js +18 -130
- package/dist/src/testing/MultiLLMProvider.js.map +1 -1
- package/dist/src/testing/MultiLLMProvider.metrics.d.ts +33 -0
- package/dist/src/testing/MultiLLMProvider.metrics.d.ts.map +1 -0
- package/dist/src/testing/MultiLLMProvider.metrics.js +87 -0
- package/dist/src/testing/MultiLLMProvider.metrics.js.map +1 -0
- package/dist/src/testing/MultiLLMProvider.selection.d.ts +77 -0
- package/dist/src/testing/MultiLLMProvider.selection.d.ts.map +1 -0
- package/dist/src/testing/MultiLLMProvider.selection.js +151 -0
- package/dist/src/testing/MultiLLMProvider.selection.js.map +1 -0
- package/dist/src/types/skill.d.ts +10 -0
- package/dist/src/types/skill.d.ts.map +1 -1
- package/dist/src/types.d.ts +34 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/versioning/change-classifier.d.ts +38 -0
- package/dist/src/versioning/change-classifier.d.ts.map +1 -0
- package/dist/src/versioning/change-classifier.js +187 -0
- package/dist/src/versioning/change-classifier.js.map +1 -0
- package/dist/src/versioning/change-classifier.test.d.ts +6 -0
- package/dist/src/versioning/change-classifier.test.d.ts.map +1 -0
- package/dist/src/versioning/change-classifier.test.js +275 -0
- package/dist/src/versioning/change-classifier.test.js.map +1 -0
- package/dist/src/versioning/update-risk.d.ts +50 -0
- package/dist/src/versioning/update-risk.d.ts.map +1 -0
- package/dist/src/versioning/update-risk.js +80 -0
- package/dist/src/versioning/update-risk.js.map +1 -0
- package/dist/src/versioning/update-risk.test.d.ts +6 -0
- package/dist/src/versioning/update-risk.test.d.ts.map +1 -0
- package/dist/src/versioning/update-risk.test.js +200 -0
- package/dist/src/versioning/update-risk.test.js.map +1 -0
- package/dist/tests/AnalyticsStorage.test.js +2 -2
- package/dist/tests/AnalyticsStorage.test.js.map +1 -1
- package/dist/tests/AuditLogger.edge-cases.test.d.ts +10 -0
- package/dist/tests/AuditLogger.edge-cases.test.d.ts.map +1 -0
- package/dist/tests/AuditLogger.edge-cases.test.js +183 -0
- package/dist/tests/AuditLogger.edge-cases.test.js.map +1 -0
- package/dist/tests/CacheManager.test.d.ts +9 -0
- package/dist/tests/CacheManager.test.d.ts.map +1 -0
- package/dist/tests/CacheManager.test.js +163 -0
- package/dist/tests/CacheManager.test.js.map +1 -0
- package/dist/tests/CacheSecurity.test.js +4 -4
- package/dist/tests/CacheSecurity.test.js.map +1 -1
- package/dist/tests/EmbeddingService.test.js +11 -12
- package/dist/tests/EmbeddingService.test.js.map +1 -1
- package/dist/tests/GitHubIndexer.edge-cases.test.d.ts +10 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.d.ts.map +1 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.js +255 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.js.map +1 -0
- package/dist/tests/HybridSearch.test.d.ts +8 -0
- package/dist/tests/HybridSearch.test.d.ts.map +1 -0
- package/dist/tests/HybridSearch.test.js +48 -0
- package/dist/tests/HybridSearch.test.js.map +1 -0
- package/dist/tests/SearchService.test.js +71 -0
- package/dist/tests/SearchService.test.js.map +1 -1
- package/dist/tests/SkillVersionRepository.test.d.ts +2 -0
- package/dist/tests/SkillVersionRepository.test.d.ts.map +1 -0
- package/dist/tests/SkillVersionRepository.test.js +168 -0
- package/dist/tests/SkillVersionRepository.test.js.map +1 -0
- package/dist/tests/TieredCache.test.js +10 -10
- package/dist/tests/TieredCache.test.js.map +1 -1
- package/dist/tests/UsageTracker.test.js +6 -6
- package/dist/tests/UsageTracker.test.js.map +1 -1
- package/dist/tests/analytics/usage-tracker.test.js +8 -8
- package/dist/tests/analytics/usage-tracker.test.js.map +1 -1
- package/dist/tests/api/client.health.test.d.ts +15 -0
- package/dist/tests/api/client.health.test.d.ts.map +1 -0
- package/dist/tests/api/client.health.test.js +111 -0
- package/dist/tests/api/client.health.test.js.map +1 -0
- package/dist/tests/cache.test.js +7 -9
- package/dist/tests/cache.test.js.map +1 -1
- package/dist/tests/db/betterSqlite3Driver.test.d.ts +8 -0
- package/dist/tests/db/betterSqlite3Driver.test.d.ts.map +1 -0
- package/dist/tests/db/betterSqlite3Driver.test.js +88 -0
- package/dist/tests/db/betterSqlite3Driver.test.js.map +1 -0
- package/dist/tests/db/database-abstraction.test.js +48 -0
- package/dist/tests/db/database-abstraction.test.js.map +1 -1
- package/dist/tests/db/schema-migrations.test.d.ts +10 -0
- package/dist/tests/db/schema-migrations.test.d.ts.map +1 -0
- package/dist/tests/db/schema-migrations.test.js +134 -0
- package/dist/tests/db/schema-migrations.test.js.map +1 -0
- package/dist/tests/db/sqljsDriver.test.d.ts +9 -0
- package/dist/tests/db/sqljsDriver.test.d.ts.map +1 -0
- package/dist/tests/db/sqljsDriver.test.js +75 -0
- package/dist/tests/db/sqljsDriver.test.js.map +1 -0
- package/dist/tests/embeddings/hnsw-store.test.js +27 -24
- package/dist/tests/embeddings/hnsw-store.test.js.map +1 -1
- package/dist/tests/helpers/database.d.ts +32 -0
- package/dist/tests/helpers/database.d.ts.map +1 -0
- package/dist/tests/helpers/database.js +54 -0
- package/dist/tests/helpers/database.js.map +1 -0
- package/dist/tests/learning/PatternStore.helpers.test.d.ts +17 -0
- package/dist/tests/learning/PatternStore.helpers.test.d.ts.map +1 -0
- package/dist/tests/learning/PatternStore.helpers.test.js +301 -0
- package/dist/tests/learning/PatternStore.helpers.test.js.map +1 -0
- package/dist/tests/learning/PatternStore.test.js +9 -0
- package/dist/tests/learning/PatternStore.test.js.map +1 -1
- package/dist/tests/repositories/CoInstallRepository.test.d.ts +9 -0
- package/dist/tests/repositories/CoInstallRepository.test.d.ts.map +1 -0
- package/dist/tests/repositories/CoInstallRepository.test.js +126 -0
- package/dist/tests/repositories/CoInstallRepository.test.js.map +1 -0
- package/dist/tests/routing/LanguageRouter.test.d.ts +9 -0
- package/dist/tests/routing/LanguageRouter.test.d.ts.map +1 -0
- package/dist/tests/routing/LanguageRouter.test.js +150 -0
- package/dist/tests/routing/LanguageRouter.test.js.map +1 -0
- package/dist/tests/session/SessionManager.memory.test.d.ts +11 -0
- package/dist/tests/session/SessionManager.memory.test.d.ts.map +1 -0
- package/dist/tests/session/SessionManager.memory.test.js +219 -0
- package/dist/tests/session/SessionManager.memory.test.js.map +1 -0
- package/dist/tests/sync/SyncEngine.test.js +32 -18
- package/dist/tests/sync/SyncEngine.test.js.map +1 -1
- package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts +13 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.js +149 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.js.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts +15 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.js +249 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.js.map +1 -0
- package/dist/tests/unit/quarantine-query-builder.test.d.ts +10 -0
- package/dist/tests/unit/quarantine-query-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/quarantine-query-builder.test.js +157 -0
- package/dist/tests/unit/quarantine-query-builder.test.js.map +1 -0
- package/package.json +1 -3
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-2756: Wave 3 — LanguageRouter tests
|
|
3
|
+
*
|
|
4
|
+
* Tests the LanguageRouter dispatch layer: adapter registration,
|
|
5
|
+
* extension-based lookup, tryGetAdapter, canHandle, getLanguage,
|
|
6
|
+
* getSupportedLanguages, framework rules aggregation, and dispose.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect } from 'vitest';
|
|
9
|
+
import { LanguageRouter } from '../../src/analysis/router.js';
|
|
10
|
+
describe('LanguageRouter', () => {
|
|
11
|
+
// -------------------------------------------------------------------------
|
|
12
|
+
// createWithAllAdapters factory
|
|
13
|
+
// -------------------------------------------------------------------------
|
|
14
|
+
describe('createWithAllAdapters', () => {
|
|
15
|
+
it('creates a router with multiple adapters pre-registered', () => {
|
|
16
|
+
const router = LanguageRouter.createWithAllAdapters();
|
|
17
|
+
expect(router.adapterCount).toBeGreaterThan(0);
|
|
18
|
+
});
|
|
19
|
+
it('creates a router with only specified languages', () => {
|
|
20
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['typescript'] });
|
|
21
|
+
expect(router.getSupportedLanguages()).toContain('typescript');
|
|
22
|
+
// Should have fewer adapters than the full set
|
|
23
|
+
const fullRouter = LanguageRouter.createWithAllAdapters();
|
|
24
|
+
expect(router.adapterCount).toBeLessThanOrEqual(fullRouter.adapterCount);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
// -------------------------------------------------------------------------
|
|
28
|
+
// registerAdapter / unregisterAdapter
|
|
29
|
+
// -------------------------------------------------------------------------
|
|
30
|
+
describe('registerAdapter / unregisterAdapter', () => {
|
|
31
|
+
it('registers an adapter and makes its extension routable', () => {
|
|
32
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['typescript'] });
|
|
33
|
+
expect(router.canHandle('main.ts')).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it('unregisterAdapter removes extension mappings', () => {
|
|
36
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['typescript'] });
|
|
37
|
+
expect(router.canHandle('main.ts')).toBe(true);
|
|
38
|
+
const removed = router.unregisterAdapter('typescript');
|
|
39
|
+
expect(removed).toBe(true);
|
|
40
|
+
expect(router.canHandle('main.ts')).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
it('unregisterAdapter returns false for unknown language', () => {
|
|
43
|
+
const router = new LanguageRouter();
|
|
44
|
+
const result = router.unregisterAdapter('typescript');
|
|
45
|
+
expect(result).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
it('re-registering an adapter replaces the old one', () => {
|
|
48
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['typescript'] });
|
|
49
|
+
const before = router.adapterCount;
|
|
50
|
+
// Re-register the same language
|
|
51
|
+
const tsAdapter = router.getAdapterByLanguage('typescript');
|
|
52
|
+
router.registerAdapter(tsAdapter);
|
|
53
|
+
// Count should not grow
|
|
54
|
+
expect(router.adapterCount).toBe(before);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
// -------------------------------------------------------------------------
|
|
58
|
+
// getAdapter / tryGetAdapter / canHandle / getLanguage
|
|
59
|
+
// -------------------------------------------------------------------------
|
|
60
|
+
describe('getAdapter', () => {
|
|
61
|
+
it('returns adapter for a known extension', () => {
|
|
62
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['typescript'] });
|
|
63
|
+
const adapter = router.tryGetAdapter('main.ts');
|
|
64
|
+
expect(adapter).not.toBeNull();
|
|
65
|
+
expect(adapter?.language).toBe('typescript');
|
|
66
|
+
});
|
|
67
|
+
it('throws for unknown extension', () => {
|
|
68
|
+
const router = new LanguageRouter();
|
|
69
|
+
expect(() => router.getAdapter('unknown.xyz')).toThrow(/No adapter registered/);
|
|
70
|
+
});
|
|
71
|
+
it('tryGetAdapter returns null for unknown extension', () => {
|
|
72
|
+
const router = new LanguageRouter();
|
|
73
|
+
expect(router.tryGetAdapter('unknown.xyz')).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('canHandle', () => {
|
|
77
|
+
it('returns true for registered extension', () => {
|
|
78
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['python'] });
|
|
79
|
+
expect(router.canHandle('app.py')).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it('returns false for unregistered extension', () => {
|
|
82
|
+
const router = new LanguageRouter();
|
|
83
|
+
expect(router.canHandle('app.cobol')).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('getLanguage', () => {
|
|
87
|
+
it('returns language for a known file path', () => {
|
|
88
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['python'] });
|
|
89
|
+
expect(router.getLanguage('script.py')).toBe('python');
|
|
90
|
+
});
|
|
91
|
+
it('returns null for unsupported extension', () => {
|
|
92
|
+
const router = new LanguageRouter();
|
|
93
|
+
expect(router.getLanguage('file.cobol')).toBeNull();
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
// -------------------------------------------------------------------------
|
|
97
|
+
// getSupportedLanguages / getSupportedExtensions
|
|
98
|
+
// -------------------------------------------------------------------------
|
|
99
|
+
describe('getSupportedLanguages / getSupportedExtensions', () => {
|
|
100
|
+
it('getSupportedLanguages returns registered language keys', () => {
|
|
101
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['typescript', 'python'] });
|
|
102
|
+
const langs = router.getSupportedLanguages();
|
|
103
|
+
expect(langs).toContain('typescript');
|
|
104
|
+
expect(langs).toContain('python');
|
|
105
|
+
});
|
|
106
|
+
it('getSupportedExtensions includes dot-prefixed extensions', () => {
|
|
107
|
+
const router = LanguageRouter.createWithAllAdapters({ languages: ['typescript'] });
|
|
108
|
+
const exts = router.getSupportedExtensions();
|
|
109
|
+
expect(exts.some((e) => e.startsWith('.'))).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
// -------------------------------------------------------------------------
|
|
113
|
+
// getAllFrameworkRules / getFrameworkRules
|
|
114
|
+
// -------------------------------------------------------------------------
|
|
115
|
+
describe('framework rules', () => {
|
|
116
|
+
it('getAllFrameworkRules returns an array', () => {
|
|
117
|
+
const router = LanguageRouter.createWithAllAdapters();
|
|
118
|
+
const rules = router.getAllFrameworkRules();
|
|
119
|
+
expect(Array.isArray(rules)).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
it('getFrameworkRules returns empty array for unregistered language', () => {
|
|
122
|
+
const router = new LanguageRouter();
|
|
123
|
+
const rules = router.getFrameworkRules('typescript');
|
|
124
|
+
expect(rules).toEqual([]);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
// -------------------------------------------------------------------------
|
|
128
|
+
// dispose
|
|
129
|
+
// -------------------------------------------------------------------------
|
|
130
|
+
describe('dispose', () => {
|
|
131
|
+
it('clears adapter registry after dispose', () => {
|
|
132
|
+
const router = LanguageRouter.createWithAllAdapters();
|
|
133
|
+
expect(router.adapterCount).toBeGreaterThan(0);
|
|
134
|
+
router.dispose();
|
|
135
|
+
expect(router.adapterCount).toBe(0);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
// -------------------------------------------------------------------------
|
|
139
|
+
// detectLanguageFromContent (disabled)
|
|
140
|
+
// -------------------------------------------------------------------------
|
|
141
|
+
describe('detectLanguageFromContent', () => {
|
|
142
|
+
it('returns language:null and method:none when detection is disabled', () => {
|
|
143
|
+
const router = new LanguageRouter({ enableLanguageDetection: false });
|
|
144
|
+
const result = router.detectLanguageFromContent('#!/usr/bin/env python3\nprint("hello")');
|
|
145
|
+
expect(result.language).toBeNull();
|
|
146
|
+
expect(result.method).toBe('none');
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
//# sourceMappingURL=LanguageRouter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LanguageRouter.test.js","sourceRoot":"","sources":["../../../tests/routing/LanguageRouter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-2754: SessionManager Memory Operation Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for storeMemoryEntry, retrieveMemoryEntry, deleteMemoryEntry,
|
|
5
|
+
* runPreTaskHook, and runPostTaskHook.
|
|
6
|
+
*
|
|
7
|
+
* Since USE_V3_API is evaluated at module load time, we mock the helpers
|
|
8
|
+
* module to control getClaudeFlowMemory / getClaudeFlowMcp / USE_V3_API.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=SessionManager.memory.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionManager.memory.test.d.ts","sourceRoot":"","sources":["../../../tests/session/SessionManager.memory.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-2754: SessionManager Memory Operation Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for storeMemoryEntry, retrieveMemoryEntry, deleteMemoryEntry,
|
|
5
|
+
* runPreTaskHook, and runPostTaskHook.
|
|
6
|
+
*
|
|
7
|
+
* Since USE_V3_API is evaluated at module load time, we mock the helpers
|
|
8
|
+
* module to control getClaudeFlowMemory / getClaudeFlowMcp / USE_V3_API.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// We mock the helpers module to control USE_V3_API and module loading
|
|
13
|
+
// ============================================================================
|
|
14
|
+
vi.mock('../../src/session/SessionManager.helpers.js', () => {
|
|
15
|
+
return {
|
|
16
|
+
validateMemoryKey: (key) => /^[a-zA-Z0-9/_-]+$/.test(key) && key.length <= 256,
|
|
17
|
+
MEMORY_KEYS: { CURRENT: 'session/current' },
|
|
18
|
+
MEMORY_NAMESPACE: 'skillsmith-sessions',
|
|
19
|
+
USE_V3_API: false, // Start with spawn path; override per test
|
|
20
|
+
getClaudeFlowMemory: vi.fn(),
|
|
21
|
+
getClaudeFlowMcp: vi.fn(),
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
import { storeMemoryEntry, retrieveMemoryEntry, deleteMemoryEntry, runPreTaskHook, runPostTaskHook, } from '../../src/session/SessionManager.memory.js';
|
|
25
|
+
import * as helpers from '../../src/session/SessionManager.helpers.js';
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Helpers
|
|
28
|
+
// ============================================================================
|
|
29
|
+
function makeSpawnExecutor(overrides = {}) {
|
|
30
|
+
return {
|
|
31
|
+
execute: vi.fn().mockResolvedValue({ stdout: '', stderr: '' }),
|
|
32
|
+
spawn: vi.fn().mockResolvedValue({ stdout: overrides.stdout ?? '', stderr: '' }),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function enableV3(enabled) {
|
|
36
|
+
// Override the USE_V3_API value in the mocked module
|
|
37
|
+
// @ts-expect-error - overriding readonly for testing
|
|
38
|
+
helpers.USE_V3_API = enabled;
|
|
39
|
+
}
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
enableV3(false);
|
|
42
|
+
vi.mocked(helpers.getClaudeFlowMemory).mockReset();
|
|
43
|
+
vi.mocked(helpers.getClaudeFlowMcp).mockReset();
|
|
44
|
+
});
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
vi.clearAllMocks();
|
|
47
|
+
});
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// storeMemoryEntry
|
|
50
|
+
// ============================================================================
|
|
51
|
+
describe('storeMemoryEntry', () => {
|
|
52
|
+
it('returns { success: false, error: "Invalid memory key" } for an invalid key', async () => {
|
|
53
|
+
const executor = makeSpawnExecutor();
|
|
54
|
+
const result = await storeMemoryEntry('bad key!', 'value', executor);
|
|
55
|
+
expect(result).toEqual({ success: false, error: 'Invalid memory key' });
|
|
56
|
+
expect(executor.spawn).not.toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
it('uses V3 storeEntry when USE_V3_API is true and module is available', async () => {
|
|
59
|
+
enableV3(true);
|
|
60
|
+
const storeEntry = vi.fn().mockResolvedValue({ success: true });
|
|
61
|
+
vi.mocked(helpers.getClaudeFlowMemory).mockResolvedValue({ storeEntry });
|
|
62
|
+
const executor = makeSpawnExecutor();
|
|
63
|
+
const result = await storeMemoryEntry('session/test', 'my-value', executor);
|
|
64
|
+
expect(result).toEqual({ success: true });
|
|
65
|
+
expect(storeEntry).toHaveBeenCalledWith({
|
|
66
|
+
key: 'session/test',
|
|
67
|
+
value: 'my-value',
|
|
68
|
+
namespace: 'skillsmith-sessions',
|
|
69
|
+
});
|
|
70
|
+
expect(executor.spawn).not.toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
it('falls back to spawn when V3 storeEntry returns success:false', async () => {
|
|
73
|
+
enableV3(true);
|
|
74
|
+
const storeEntry = vi.fn().mockResolvedValue({ success: false, error: 'V3 error' });
|
|
75
|
+
vi.mocked(helpers.getClaudeFlowMemory).mockResolvedValue({ storeEntry });
|
|
76
|
+
const executor = makeSpawnExecutor();
|
|
77
|
+
const result = await storeMemoryEntry('session/fallback', 'value', executor);
|
|
78
|
+
expect(result).toEqual({ success: true });
|
|
79
|
+
expect(executor.spawn).toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
it('uses spawn directly when USE_V3_API is false', async () => {
|
|
82
|
+
enableV3(false);
|
|
83
|
+
const executor = makeSpawnExecutor();
|
|
84
|
+
const result = await storeMemoryEntry('session/key', 'val', executor);
|
|
85
|
+
expect(result).toEqual({ success: true });
|
|
86
|
+
expect(executor.spawn).toHaveBeenCalledWith('npx', expect.arrayContaining(['claude-flow', 'memory', 'store', '--key', 'session/key']));
|
|
87
|
+
expect(helpers.getClaudeFlowMemory).not.toHaveBeenCalled();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// retrieveMemoryEntry
|
|
92
|
+
// ============================================================================
|
|
93
|
+
describe('retrieveMemoryEntry', () => {
|
|
94
|
+
it('returns { success: false, error: "Invalid memory key" } for an invalid key', async () => {
|
|
95
|
+
const executor = makeSpawnExecutor();
|
|
96
|
+
const result = await retrieveMemoryEntry('bad key!', executor);
|
|
97
|
+
expect(result).toEqual({ success: false, error: 'Invalid memory key' });
|
|
98
|
+
});
|
|
99
|
+
it('returns data from V3 getEntry when found', async () => {
|
|
100
|
+
enableV3(true);
|
|
101
|
+
const getEntry = vi.fn().mockResolvedValue({
|
|
102
|
+
success: true,
|
|
103
|
+
found: true,
|
|
104
|
+
entry: { content: 'stored-value' },
|
|
105
|
+
});
|
|
106
|
+
vi.mocked(helpers.getClaudeFlowMemory).mockResolvedValue({ getEntry });
|
|
107
|
+
const executor = makeSpawnExecutor();
|
|
108
|
+
const result = await retrieveMemoryEntry('session/found', executor);
|
|
109
|
+
expect(result).toEqual({ success: true, data: 'stored-value' });
|
|
110
|
+
expect(executor.spawn).not.toHaveBeenCalled();
|
|
111
|
+
});
|
|
112
|
+
it('returns not-found error from V3 when key does not exist', async () => {
|
|
113
|
+
enableV3(true);
|
|
114
|
+
const getEntry = vi.fn().mockResolvedValue({
|
|
115
|
+
success: true,
|
|
116
|
+
found: false,
|
|
117
|
+
});
|
|
118
|
+
vi.mocked(helpers.getClaudeFlowMemory).mockResolvedValue({ getEntry });
|
|
119
|
+
const executor = makeSpawnExecutor();
|
|
120
|
+
const result = await retrieveMemoryEntry('session/missing', executor);
|
|
121
|
+
expect(result).toEqual({ success: false, error: 'Key not found' });
|
|
122
|
+
expect(executor.spawn).not.toHaveBeenCalled();
|
|
123
|
+
});
|
|
124
|
+
it('falls back to spawn when V3 getEntry throws an exception', async () => {
|
|
125
|
+
enableV3(true);
|
|
126
|
+
vi.mocked(helpers.getClaudeFlowMemory).mockRejectedValue(new Error('module load error'));
|
|
127
|
+
const executor = makeSpawnExecutor({ stdout: 'spawned-data' });
|
|
128
|
+
const result = await retrieveMemoryEntry('session/key', executor);
|
|
129
|
+
expect(result).toEqual({ success: true, data: 'spawned-data' });
|
|
130
|
+
expect(executor.spawn).toHaveBeenCalled();
|
|
131
|
+
});
|
|
132
|
+
it('uses spawn directly when USE_V3_API is false', async () => {
|
|
133
|
+
enableV3(false);
|
|
134
|
+
const executor = makeSpawnExecutor({ stdout: 'value-from-spawn\n' });
|
|
135
|
+
const result = await retrieveMemoryEntry('session/key', executor);
|
|
136
|
+
expect(result).toEqual({ success: true, data: 'value-from-spawn' });
|
|
137
|
+
expect(helpers.getClaudeFlowMemory).not.toHaveBeenCalled();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// deleteMemoryEntry
|
|
142
|
+
// ============================================================================
|
|
143
|
+
describe('deleteMemoryEntry', () => {
|
|
144
|
+
it('returns { success: false, error: "Invalid memory key" } for an invalid key', async () => {
|
|
145
|
+
const executor = makeSpawnExecutor();
|
|
146
|
+
const result = await deleteMemoryEntry('bad key!', executor);
|
|
147
|
+
expect(result).toEqual({ success: false, error: 'Invalid memory key' });
|
|
148
|
+
});
|
|
149
|
+
it('returns success when V3 callMCPTool succeeds', async () => {
|
|
150
|
+
enableV3(true);
|
|
151
|
+
const callMCPTool = vi.fn().mockResolvedValue({ success: true, deleted: true });
|
|
152
|
+
vi.mocked(helpers.getClaudeFlowMcp).mockResolvedValue({ callMCPTool });
|
|
153
|
+
const executor = makeSpawnExecutor();
|
|
154
|
+
const result = await deleteMemoryEntry('session/to-delete', executor);
|
|
155
|
+
expect(result).toEqual({ success: true });
|
|
156
|
+
expect(callMCPTool).toHaveBeenCalledWith('memory/delete', { key: 'session/to-delete' });
|
|
157
|
+
});
|
|
158
|
+
it('falls back to spawn (and returns success) when V3 callMCPTool fails', async () => {
|
|
159
|
+
enableV3(true);
|
|
160
|
+
const callMCPTool = vi.fn().mockResolvedValue({ success: false });
|
|
161
|
+
vi.mocked(helpers.getClaudeFlowMcp).mockResolvedValue({ callMCPTool });
|
|
162
|
+
const executor = makeSpawnExecutor();
|
|
163
|
+
const result = await deleteMemoryEntry('session/key', executor);
|
|
164
|
+
expect(result).toEqual({ success: true });
|
|
165
|
+
expect(executor.spawn).toHaveBeenCalled();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// runPreTaskHook
|
|
170
|
+
// ============================================================================
|
|
171
|
+
describe('runPreTaskHook', () => {
|
|
172
|
+
it('calls V3 MCP pre-task hook when USE_V3_API is true', async () => {
|
|
173
|
+
enableV3(true);
|
|
174
|
+
const callMCPTool = vi.fn().mockResolvedValue({});
|
|
175
|
+
vi.mocked(helpers.getClaudeFlowMcp).mockResolvedValue({ callMCPTool });
|
|
176
|
+
const executor = makeSpawnExecutor();
|
|
177
|
+
await runPreTaskHook('test description', executor);
|
|
178
|
+
expect(callMCPTool).toHaveBeenCalledWith('hooks/pre-task', expect.objectContaining({
|
|
179
|
+
description: 'test description',
|
|
180
|
+
}));
|
|
181
|
+
expect(executor.spawn).not.toHaveBeenCalled();
|
|
182
|
+
});
|
|
183
|
+
it('uses spawn when USE_V3_API is false', async () => {
|
|
184
|
+
enableV3(false);
|
|
185
|
+
const executor = makeSpawnExecutor();
|
|
186
|
+
await runPreTaskHook('test description', executor);
|
|
187
|
+
expect(executor.spawn).toHaveBeenCalledWith('npx', expect.arrayContaining(['pre-task', '--description', 'test description']));
|
|
188
|
+
});
|
|
189
|
+
it('swallows errors and does not throw', async () => {
|
|
190
|
+
enableV3(false);
|
|
191
|
+
const executor = {
|
|
192
|
+
execute: vi.fn().mockResolvedValue({ stdout: '', stderr: '' }),
|
|
193
|
+
spawn: vi.fn().mockRejectedValue(new Error('hook failed')),
|
|
194
|
+
};
|
|
195
|
+
// Should not throw
|
|
196
|
+
await expect(runPreTaskHook('test', executor)).resolves.toBeUndefined();
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// runPostTaskHook
|
|
201
|
+
// ============================================================================
|
|
202
|
+
describe('runPostTaskHook', () => {
|
|
203
|
+
it('calls V3 MCP post-task hook when USE_V3_API is true', async () => {
|
|
204
|
+
enableV3(true);
|
|
205
|
+
const callMCPTool = vi.fn().mockResolvedValue({});
|
|
206
|
+
vi.mocked(helpers.getClaudeFlowMcp).mockResolvedValue({ callMCPTool });
|
|
207
|
+
const executor = makeSpawnExecutor();
|
|
208
|
+
await runPostTaskHook('task-123', executor);
|
|
209
|
+
expect(callMCPTool).toHaveBeenCalledWith('hooks/post-task', { taskId: 'task-123' });
|
|
210
|
+
expect(executor.spawn).not.toHaveBeenCalled();
|
|
211
|
+
});
|
|
212
|
+
it('uses spawn when USE_V3_API is false', async () => {
|
|
213
|
+
enableV3(false);
|
|
214
|
+
const executor = makeSpawnExecutor();
|
|
215
|
+
await runPostTaskHook('task-456', executor);
|
|
216
|
+
expect(executor.spawn).toHaveBeenCalledWith('npx', expect.arrayContaining(['post-task', '--task-id', 'task-456']));
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
//# sourceMappingURL=SessionManager.memory.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionManager.memory.test.js","sourceRoot":"","sources":["../../../tests/session/SessionManager.memory.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,20 @@ import { SyncConfigRepository } from '../../src/repositories/SyncConfigRepositor
|
|
|
9
9
|
import { SyncHistoryRepository } from '../../src/repositories/SyncHistoryRepository.js';
|
|
10
10
|
import { SkillRepository } from '../../src/repositories/SkillRepository.js';
|
|
11
11
|
import { SyncEngine } from '../../src/sync/SyncEngine.js';
|
|
12
|
+
/**
|
|
13
|
+
* Create a mock SkillVersionRepository for testing.
|
|
14
|
+
* All methods return resolved promises so SyncEngine can call recordVersion
|
|
15
|
+
* after each upsert without errors.
|
|
16
|
+
*/
|
|
17
|
+
function createMockSkillVersionRepo() {
|
|
18
|
+
return {
|
|
19
|
+
recordVersion: vi.fn().mockResolvedValue(undefined),
|
|
20
|
+
pruneVersions: vi.fn().mockResolvedValue(undefined),
|
|
21
|
+
getLatestVersion: vi.fn().mockResolvedValue(null),
|
|
22
|
+
getVersionHistory: vi.fn().mockResolvedValue([]),
|
|
23
|
+
getVersionByHash: vi.fn().mockResolvedValue(null),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
12
26
|
/**
|
|
13
27
|
* Create a mock skill for testing
|
|
14
28
|
* Note: quality_score must be between 0 and 1 (database constraint)
|
|
@@ -71,21 +85,21 @@ describe('SyncEngine', () => {
|
|
|
71
85
|
describe('constructor', () => {
|
|
72
86
|
it('should create sync engine with all dependencies', () => {
|
|
73
87
|
const apiClient = createMockApiClient();
|
|
74
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
88
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
75
89
|
expect(engine).toBeDefined();
|
|
76
90
|
});
|
|
77
91
|
});
|
|
78
92
|
describe('sync - offline and health checks', () => {
|
|
79
93
|
it('should fail when API client is offline', async () => {
|
|
80
94
|
const apiClient = createMockApiClient({ offline: true });
|
|
81
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
95
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
82
96
|
const result = await engine.sync();
|
|
83
97
|
expect(result.success).toBe(false);
|
|
84
98
|
expect(result.errors).toContain('API client is in offline mode. Cannot sync.');
|
|
85
99
|
});
|
|
86
100
|
it('should fail when API health check fails', async () => {
|
|
87
101
|
const apiClient = createMockApiClient({ healthStatus: 'unhealthy' });
|
|
88
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
102
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
89
103
|
const result = await engine.sync();
|
|
90
104
|
expect(result.success).toBe(false);
|
|
91
105
|
expect(result.errors).toContain('API is unhealthy. Try again later.');
|
|
@@ -99,7 +113,7 @@ describe('SyncEngine', () => {
|
|
|
99
113
|
createMockSkill('test/skill-3'),
|
|
100
114
|
];
|
|
101
115
|
const apiClient = createMockApiClient({ skills });
|
|
102
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
116
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
103
117
|
const result = await engine.sync();
|
|
104
118
|
expect(result.success).toBe(true);
|
|
105
119
|
expect(result.skillsAdded).toBe(3);
|
|
@@ -119,7 +133,7 @@ describe('SyncEngine', () => {
|
|
|
119
133
|
// API returns updated version with new updated_at
|
|
120
134
|
const skills = [createMockSkill('test/skill-1', new Date(Date.now() + 1000).toISOString())];
|
|
121
135
|
const apiClient = createMockApiClient({ skills });
|
|
122
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
136
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
123
137
|
const result = await engine.sync();
|
|
124
138
|
expect(result.success).toBe(true);
|
|
125
139
|
expect(result.skillsAdded).toBe(0);
|
|
@@ -139,7 +153,7 @@ describe('SyncEngine', () => {
|
|
|
139
153
|
// API returns skill with same timestamp
|
|
140
154
|
const skills = [createMockSkill('test/skill-1', timestamp)];
|
|
141
155
|
const apiClient = createMockApiClient({ skills });
|
|
142
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
156
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
143
157
|
const result = await engine.sync();
|
|
144
158
|
expect(result.success).toBe(true);
|
|
145
159
|
expect(result.skillsUnchanged).toBe(1);
|
|
@@ -156,7 +170,7 @@ describe('SyncEngine', () => {
|
|
|
156
170
|
const oldSkill = createMockSkill('test/old-skill', new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString());
|
|
157
171
|
const newSkill = createMockSkill('test/new-skill', new Date().toISOString());
|
|
158
172
|
const apiClient = createMockApiClient({ skills: [oldSkill, newSkill] });
|
|
159
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
173
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
160
174
|
const result = await engine.sync();
|
|
161
175
|
expect(result.success).toBe(true);
|
|
162
176
|
// Only the new skill should be added (old one filtered out by differential)
|
|
@@ -173,7 +187,7 @@ describe('SyncEngine', () => {
|
|
|
173
187
|
createMockSkill('test/skill-2', new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString()),
|
|
174
188
|
];
|
|
175
189
|
const apiClient = createMockApiClient({ skills });
|
|
176
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
190
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
177
191
|
const result = await engine.sync({ force: true });
|
|
178
192
|
expect(result.success).toBe(true);
|
|
179
193
|
expect(result.skillsAdded).toBe(2); // All skills processed because force=true
|
|
@@ -183,7 +197,7 @@ describe('SyncEngine', () => {
|
|
|
183
197
|
it('should not modify database in dry run mode', async () => {
|
|
184
198
|
const skills = [createMockSkill('test/skill-1')];
|
|
185
199
|
const apiClient = createMockApiClient({ skills });
|
|
186
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
200
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
187
201
|
const result = await engine.sync({ dryRun: true });
|
|
188
202
|
expect(result.success).toBe(true);
|
|
189
203
|
expect(result.dryRun).toBe(true);
|
|
@@ -200,7 +214,7 @@ describe('SyncEngine', () => {
|
|
|
200
214
|
it('should call onProgress callback with phases', async () => {
|
|
201
215
|
const skills = [createMockSkill('test/skill-1')];
|
|
202
216
|
const apiClient = createMockApiClient({ skills });
|
|
203
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
217
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
204
218
|
const progressCalls = [];
|
|
205
219
|
const onProgress = vi.fn((progress) => {
|
|
206
220
|
progressCalls.push(progress.phase);
|
|
@@ -219,7 +233,7 @@ describe('SyncEngine', () => {
|
|
|
219
233
|
// Create 150 skills (more than one page of 100)
|
|
220
234
|
const skills = Array.from({ length: 150 }, (_, i) => createMockSkill(`test/skill-${i}`));
|
|
221
235
|
const apiClient = createMockApiClient({ skills });
|
|
222
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
236
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
223
237
|
const result = await engine.sync({ pageSize: 100 });
|
|
224
238
|
expect(result.success).toBe(true);
|
|
225
239
|
expect(result.skillsAdded).toBe(150);
|
|
@@ -234,7 +248,7 @@ describe('SyncEngine', () => {
|
|
|
234
248
|
it('should record sync history on success', async () => {
|
|
235
249
|
const skills = [createMockSkill('test/skill-1')];
|
|
236
250
|
const apiClient = createMockApiClient({ skills });
|
|
237
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
251
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
238
252
|
await engine.sync();
|
|
239
253
|
const history = syncHistoryRepo.getHistory();
|
|
240
254
|
expect(history).toHaveLength(1);
|
|
@@ -245,7 +259,7 @@ describe('SyncEngine', () => {
|
|
|
245
259
|
const apiClient = createMockApiClient({
|
|
246
260
|
throwOnSearch: new Error('Network failure'),
|
|
247
261
|
});
|
|
248
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
262
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
249
263
|
await engine.sync();
|
|
250
264
|
const history = syncHistoryRepo.getHistory();
|
|
251
265
|
expect(history).toHaveLength(1);
|
|
@@ -255,7 +269,7 @@ describe('SyncEngine', () => {
|
|
|
255
269
|
it('should update sync config on success', async () => {
|
|
256
270
|
const skills = [createMockSkill('test/skill-1')];
|
|
257
271
|
const apiClient = createMockApiClient({ skills });
|
|
258
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
272
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
259
273
|
await engine.sync();
|
|
260
274
|
const config = syncConfigRepo.getConfig();
|
|
261
275
|
expect(config.lastSyncAt).not.toBeNull();
|
|
@@ -264,7 +278,7 @@ describe('SyncEngine', () => {
|
|
|
264
278
|
});
|
|
265
279
|
it('should set error in config on failure', async () => {
|
|
266
280
|
const apiClient = createMockApiClient({ offline: true });
|
|
267
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
281
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
268
282
|
await engine.sync();
|
|
269
283
|
const config = syncConfigRepo.getConfig();
|
|
270
284
|
expect(config.lastSyncError).toBe('API client is in offline mode. Cannot sync.');
|
|
@@ -273,7 +287,7 @@ describe('SyncEngine', () => {
|
|
|
273
287
|
describe('getStatus', () => {
|
|
274
288
|
it('should return sync status summary', () => {
|
|
275
289
|
const apiClient = createMockApiClient();
|
|
276
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
290
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
277
291
|
const status = engine.getStatus();
|
|
278
292
|
expect(status).toHaveProperty('config');
|
|
279
293
|
expect(status).toHaveProperty('lastRun');
|
|
@@ -282,14 +296,14 @@ describe('SyncEngine', () => {
|
|
|
282
296
|
});
|
|
283
297
|
it('should show sync is due when never synced', () => {
|
|
284
298
|
const apiClient = createMockApiClient();
|
|
285
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
299
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
286
300
|
const status = engine.getStatus();
|
|
287
301
|
expect(status.isDue).toBe(true);
|
|
288
302
|
expect(status.lastRun).toBeNull();
|
|
289
303
|
});
|
|
290
304
|
it('should reflect running state', async () => {
|
|
291
305
|
const apiClient = createMockApiClient();
|
|
292
|
-
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo);
|
|
306
|
+
const engine = new SyncEngine(apiClient, skillRepo, syncConfigRepo, syncHistoryRepo, createMockSkillVersionRepo());
|
|
293
307
|
// Start a run manually
|
|
294
308
|
syncHistoryRepo.startRun();
|
|
295
309
|
const status = engine.getStatus();
|